diff --git a/web/app/sketcher.js b/web/app/sketcher.js index 712fe4eb..9141f342 100644 --- a/web/app/sketcher.js +++ b/web/app/sketcher.js @@ -10,6 +10,7 @@ import '../css/app.less' function initializeSketcherApplication() { var app = new App2D(); + window._TCAD_APP = app; var sketchId = app.getSketchId(); if (sketchId == App2D.STORAGE_PREFIX + '__sample2D__') { var sample = '{"layers":[{"name":"_dim","style":{"lineWidth":1,"strokeStyle":"#bcffc1","fillStyle":"#00FF00"},"data":[{"id":0,"_class":"TCAD.TWO.DiameterDimension","obj":90},{"id":1,"_class":"TCAD.TWO.DiameterDimension","obj":95},{"id":2,"_class":"TCAD.TWO.DiameterDimension","obj":42},{"id":3,"_class":"TCAD.TWO.Dimension","a":5,"b":8,"flip":false},{"id":4,"_class":"TCAD.TWO.DiameterDimension","obj":105}]},{"name":"sketch","style":{"lineWidth":2,"strokeStyle":"#ffffff","fillStyle":"#000000"},"data":[{"id":11,"_class":"TCAD.TWO.Segment","points":[[5,[6,110.1295615870824],[7,313.66509156975803]],[8,[9,419.44198895058975],[10,516.7065215258621]]]},{"id":18,"_class":"TCAD.TWO.Segment","points":[[12,[13,489.1218947877601],[14,477.98601743930897]],[15,[16,481.90945628911174],[17,182.9391540301952]]]},{"id":25,"_class":"TCAD.TWO.Segment","points":[[19,[20,427.6872468325118],[21,163.96220645927505]],[22,[23,349.9023145352797],[24,256.7344291384989]]]},{"id":32,"_class":"TCAD.TWO.Segment","points":[[26,[27,306.81261277555075],[28,273.1404656521002]],[29,[30,135.09050734792822],[31,247.98348666778958]]]},{"id":42,"_class":"TCAD.TWO.Arc","points":[[33,[34,489.1218947877601],[35,477.98601743930897]],[36,[37,419.44198895058975],[38,516.7065215258621]],[39,[40,444.1353623657045],[41,479.08688157090376]]]},{"id":53,"_class":"TCAD.TWO.Arc","points":[[44,[45,427.6872468325118],[46,163.96220645927505]],[47,[48,481.90945628911174],[49,182.9391540301952]],[50,[51,451.2148840882273],[52,183.68960424767275]]]},{"id":64,"_class":"TCAD.TWO.Arc","points":[[55,[56,349.9023145352797],[57,256.7344291384989]],[58,[59,306.81261277555075],[60,273.1404656521002]],[61,[62,313.6665992835383],[63,226.35256652594512]]]},{"id":75,"_class":"TCAD.TWO.Arc","points":[[66,[67,110.1295615870824],[68,313.66509156975803]],[69,[70,135.09050734792822],[71,247.98348666778958]],[72,[73,129.8749213918784],[74,283.58516027516237]]]},{"id":80,"_class":"TCAD.TWO.Circle","c":[77,[78,444.1353623657045],[79,479.08688157090376]],"r":17},{"id":85,"_class":"TCAD.TWO.Circle","c":[82,[83,451.2148840882273],[84,183.68960424767275]],"r":17},{"id":90,"_class":"TCAD.TWO.Circle","c":[87,[88,129.8749213918784],[89,283.58516027516237]],"r":17},{"id":95,"_class":"TCAD.TWO.Circle","c":[92,[93,364.7627927122075],[94,358.27520724354514]],"r":50},{"id":100,"_class":"TCAD.TWO.Circle","c":[97,[98,450.6425914465028],[99,356.1758703461729]],"r":13},{"id":105,"_class":"TCAD.TWO.Circle","c":[102,[103,281.1241663120215],[104,360.3197585470608]],"r":13}]},{"name":"_construction_","style":{"lineWidth":1,"strokeStyle":"#aaaaaa","fillStyle":"#000000"},"data":[{"id":113,"_class":"TCAD.TWO.Segment","points":[[107,[108,366.96497096679207],[109,448.36204633886825]],[110,[111,362.6842565514955],[112,273.2463262825022]]]},{"id":120,"_class":"TCAD.TWO.Segment","points":[[114,[115,254.60331148100178],[116,360.9680624545806]],[117,[118,474.9222739434132],[119,355.5823520325097]]]}]}],"constraints":[["Tangent",[42,18]],["Tangent",[42,11]],["coi",[33,12]],["coi",[36,8]],["Tangent",[53,25]],["Tangent",[53,18]],["coi",[44,19]],["coi",[47,15]],["Tangent",[64,25]],["Tangent",[64,32]],["coi",[55,22]],["coi",[58,26]],["Tangent",[75,11]],["Tangent",[75,32]],["coi",[66,5]],["coi",[69,29]],["coi",[77,39]],["coi",[82,50]],["coi",[87,72]],["RR",[80,85]],["RR",[85,90]],["parallel",[113,18]],["perpendicular",[120,113]],["Symmetry",[92,120]],["PointOnLine",[92,113]],["PointOnLine",[102,120]],["PointOnLine",[97,120]],["RR",[105,100]]]}'; diff --git a/web/test/cases/arc-io.js b/web/test/cases/arc-io.js deleted file mode 100644 index 1d01ccb9..00000000 --- a/web/test/cases/arc-io.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - testSaveLoad: function() { - - } -} diff --git a/web/test/cases/arc.js b/web/test/cases/arc.js new file mode 100644 index 00000000..02dbeb3e --- /dev/null +++ b/web/test/cases/arc.js @@ -0,0 +1,7 @@ +export default { + testSaveLoad: function(env) { + + + env.done(); + } +} diff --git a/web/test/cases/segment-io.js b/web/test/cases/segment-io.js deleted file mode 100644 index a74e375e..00000000 --- a/web/test/cases/segment-io.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as test from '../test' - -export default { - testSaveLoad: function() { - test.fail('Nothing works'); - } -} diff --git a/web/test/cases/segment.js b/web/test/cases/segment.js new file mode 100644 index 00000000..9f52490b --- /dev/null +++ b/web/test/cases/segment.js @@ -0,0 +1,86 @@ +import * as test from '../test' +import {TestMouseEvent} from '../utils/mouse-event' + +function addSegment(app, aX, aY, bX, bY) { + app.actions['addSegment'].action(); + app.viewer.toolManager.tool.mouseup(new TestMouseEvent(aX, aY)); + app.viewer.toolManager.tool.mousemove(new TestMouseEvent(bX, bY)); + app.viewer.toolManager.tool.mouseup(new TestMouseEvent(bX, bY)); + app.viewer.toolManager.releaseControl(); +} + +function click(tool, x, y) { + tool.mousedown(new TestMouseEvent(x, y)); + tool.mouseup(new TestMouseEvent(x, y)); +} + +export default { + testSegmentWizard: function(env) { + const win = test.emptySketch((win, app) => { + env.assertEquals(0, app.viewer.activeLayer.objects.length); + addSegment(app, 10, 10, 100, 100); + env.assertEquals(1, app.viewer.activeLayer.objects.length); + const segment = app.viewer.activeLayer.objects[0]; + env.assertEquals('TCAD.TWO.Segment', segment._class); + env.assertPoint2DEquals(10, 10, segment.a); + env.assertPoint2DEquals(101, 100, segment.b); + env.done(); + }); + }, + + testSaveLoad: function(env) { + test.emptySketch((win, app) => { + env.assertEquals(0, app.viewer.activeLayer.objects.length); + addSegment(app, 10, 10, 100, 100); + app.actions['save'].action(); + test.sketch((win, app) => { + env.assertEquals(1, app.viewer.activeLayer.objects.length); + const segment = app.viewer.activeLayer.objects[0]; + env.assertEquals('TCAD.TWO.Segment', segment._class); + env.done(); + }); + }); + }, + + testSelection: function(env) { + test.emptySketch((win, app) => { + addSegment(app, 10, 10, 100, 100); + env.assertEquals(0, app.viewer.selected.length); + click(app.viewer.toolManager.tool, 50, 50); + env.assertEquals(1, app.viewer.selected.length); + env.done(); + }); + }, + + testSelectionNeighborhood: function(env) { + test.emptySketch((win, app) => { + addSegment(app, 10, 10, 100, 100); + env.assertEquals(0, app.viewer.selected.length); + // this point technically isn't on the line but should trigger the selection + click(app.viewer.toolManager.tool, 55, 50); + env.assertEquals(1, app.viewer.selected.length); + env.done(); + }); + }, + + testSnap: function(env) { + test.emptySketch((win, app) => { + addSegment(app, 10, 10, 100, 100); + env.assertEquals(0, app.viewer.selected.length); + // this point technically isn't on the line but should trigger the selection + click(app.viewer.toolManager.tool, 55, 50); + env.assertEquals(1, app.viewer.selected.length); + env.done(); + }); + } + +} + + +function collectObjects(visitable) { + const objects = []; + visitable.accept((o) => { + objects.push(o); + }); + return objects; +} \ No newline at end of file diff --git a/web/test/runner.html b/web/test/runner.html index 9dcd4fc7..5c42ee87 100644 --- a/web/test/runner.html +++ b/web/test/runner.html @@ -7,10 +7,10 @@
- + 0 run / 0 passed / 0 failures
- +
diff --git a/web/test/runner.js b/web/test/runner.js index e52c54e5..f125a943 100644 --- a/web/test/runner.js +++ b/web/test/runner.js @@ -3,7 +3,9 @@ import TestList from './tmpl/test-list.html' import '../app/utils/jqueryfy' import suites from './suites' import {Menu} from './menu' -import {AssertionError} from './test' +import {TestEnv} from './test' +import DurationFormat from './utils/duration-format' + $(() => { const runBtn = $('#run-button'); @@ -13,71 +15,87 @@ $(() => { runBtn.click(() => { run(); - disableBtn(runBtn); - enableBtn(pauseBtn); + //disableBtn(runBtn); + //enableBtn(pauseBtn); }); pauseBtn.click(() => { disableBtn(pauseBtn); enableBtn(runBtn); }); - console.log(suites); $('#test-list').html(TestList({suites})); new Menu(ACTIONS); }); +const queue = []; +let running = false; -function runSuite(name) { +function scheduleSuite(name) { const testCases = suites[name]; - let success = true; for (let testCase of testCases) { - if (!runTestCase(testCase, name + ':' +testCase.name)) { - success = false; - } + scheduleTestCase(testCase, name + ':' +testCase.name); } - updateIcon($('#suite-' + name), success); + //updateIcon($('#suite-' + name), success); } -function runTestCase(testCase, caseId) { - let success = true; - for (let test of testCase.tests) { - if (!runTest(test, caseId + ':' + test.name)) { - success = false; - } - } - updateIcon($('#case-' + caseId.replace(/:/g, '-')), success); +function scheduleTestCase(testCase, caseId) { + testCase.tests.forEach(test => scheduleTest(test, caseId + ':' + test.name)); + //updateIcon($('#case-' + caseId.replace(/:/g, '-')), success); } -function runTest(test, testId) { - let success = true; +function scheduleTest(test, id) { + queue.push({ + id, + func: test + }); +} + +function pokeQueue() { + if (running) return; + //let ui refresh + setTimeout(() => { + if (queue.length != 0) { + const test = queue.shift(); + running = true; + runTest(test.func, test.id, (testSuccess) => { + running = false; + pokeQueue(); + }); + } + }); +} + +function runTest(test, testId, callback) { let testDom = $('#test-' + testId.replace(/:/g, '-')); testDom.find('.status').hide(); testDom.find('.progress').show(); - try { - test(); - } catch (e) { - success = false; - if (e instanceof AssertionError) { - testDom.find('.result').text(e.msg); + const env = new TestEnv((env) => { + testDom.find('.progress').hide(); + testDom.find('.status').show(); + let success = env.finished && !env.failed; + updateIcon(testDom, success); + let result = 'took: ' + DurationFormat(env.took); + if (env.error) { + result += ' ' + env.error; } - } - testDom.find('.progress').hide(); - testDom.find('.status').show(); - updateIcon(testDom, success); - return success; + testDom.find('.result').html(result); + callback(success); + }); + test(env); } function run() { + queue.length = 0; for (let suite of Object.keys(suites)) { - runSuite(suite); + scheduleSuite(suite); } + pokeQueue(); } function pause() { } - function updateIcon(dom, success) { dom.find('.status').addClass(success ? 'status-success' : 'status-fail'); } @@ -104,7 +122,11 @@ function enableBtn(btn) { const ACTIONS = { RunSuite: { label: "Run Suite", - invoke: (target) => runSuite(target.data('suiteName')) + invoke: (target) => { + queue.length = 0; + scheduleSuite(target.data('suiteName')); + pokeQueue(); + } }, RunTestCase: { @@ -112,7 +134,9 @@ const ACTIONS = { invoke: (target) => { var testCaseIdStr = target.data('testCaseId'); const testCaseId = testCaseIdStr.split(':'); - runTestCase(findTestCaseById(testCaseId), testCaseIdStr); + queue.length = 0; + scheduleTestCase(findTestCaseById(testCaseId), testCaseIdStr); + pokeQueue(); } }, @@ -121,7 +145,9 @@ const ACTIONS = { invoke: (target) => { var testIdStr = target.data('testId'); const testId = testIdStr.split(':'); - runTest(findTestById(testId), testIdStr) + queue.length = 0; + scheduleTest(findTestById(testId), testIdStr); + pokeQueue(); } } }; diff --git a/web/test/runner.less b/web/test/runner.less index 360c75bc..2fab5ef3 100644 --- a/web/test/runner.less +++ b/web/test/runner.less @@ -3,11 +3,18 @@ body { margin: 0; } -#main-sandbox { +#sandbox { border: 3px plum solid; box-sizing: border-box; width: 100%; height: 60%; + background-color: #233930; +} + +#sandbox iframe { + border: 0; + width: 100%; + height: 100%; } .page-row { diff --git a/web/test/suites.js b/web/test/suites.js index 7f399b4f..89c7e2b2 100644 --- a/web/test/suites.js +++ b/web/test/suites.js @@ -1,7 +1,7 @@ export default { SketcherIO: [ - TestCase('segment-io'), - TestCase('arc-io') + TestCase('segment'), + TestCase('arc') ], SketcherTools: [ diff --git a/web/test/test.js b/web/test/test.js index 2fac06a8..d913247b 100644 --- a/web/test/test.js +++ b/web/test/test.js @@ -1,15 +1,71 @@ -export function fail(msg, optionalMsg) { - optionalMsg = (optionalMsg === undefined ? '' : ' ' + optionalMsg); - throw new AssertionError(msg + optionalMsg); +export function FailError(msg) { + this.msg = msg; } -export function assertEquals(expected, actual, msg) { - if (expected !== actual) { - fail('assertEquals: Expected: ' + expected + ' but was ' + actual, msg); +export class TestEnv { + + constructor(callback) { + this.failed = false; + this.finished = false; + this.error = undefined; + this.callback = callback; + this.took = performance.now() + } + + done() { + this.finished = true; + this.took = performance.now() - this.took; + this.callback(this); + } + + fail(msg, optionalMsg) { + this.failed = true; + this.error = msg + (optionalMsg === undefined ? '' : ' ' + optionalMsg); + this.done(); + throw new FailError(this.error); + } + + assertTrue(stmt, msg) { + if (!stmt) { + this.fail('assertTrue fails.', msg); + } + } + assertEquals(expected, actual, msg) { + if (expected !== actual) { + this.fail('assertEquals: Expected: ' + expected + ' but was ' + actual, msg); + } + } + + assertPoint2DEquals(expectedX, expectedY, actial, msg) { + if (actial.x !== expectedX || actial.y !== expectedY) { + this.fail('assertPoint2DEquals: Expected: (' + expectedX + ', ' + expectedY + ') but was (' + actial.x + ', ' + actial.y + ')' , msg); + } } } -export function AssertionError(msg) { - this.msg = msg; -} \ No newline at end of file +export function load(url, callback) { + const sandbox = $('#sandbox'); + sandbox.empty(); + const frame = $('