diff --git a/test/coreTests/defineCypress.js b/test/coreTests/defineCypress.js index 08b3a2cd..d4732c64 100644 --- a/test/coreTests/defineCypress.js +++ b/test/coreTests/defineCypress.js @@ -18,7 +18,7 @@ export function defineCypressTests(groupName, module) { name: camelCaseSplitToStr(key.substring("test".length)), funcName: key, func, - ...ModesConfig[module.TEST_MODE] + ...ModesConfig[module.TEST_MODE], }; }); @@ -33,11 +33,25 @@ export function defineCypressTests(groupName, module) { cy.window().then(win => { return new Promise((resolve, reject) => { const subject = test.testSubject(win); - const testEnv = new TestEnv(() => { + + const onDone = () => { cy.log("took: " + durationFormat(testEnv.took)); resolve(); - }); - win.__CAD_APP.streams.lifecycle.projectLoaded.attach(ready => { + }; + + const navigate = url => { + return new Promise((resolve) => { + cy.visit(url, { + onLoad: (contentWindow) => { + resolve(contentWindow); + } + }); + }); + }; + + const testEnv = new TestEnv(test.startPage, navigate, onDone); + + test.loadStream(win).attach(ready => { if (ready) { test.func(testEnv, subject); } diff --git a/test/coreTests/modes.js b/test/coreTests/modes.js index 587cc517..f70cd2f1 100644 --- a/test/coreTests/modes.js +++ b/test/coreTests/modes.js @@ -1,13 +1,16 @@ import modellerUISubject from "./subjects/modellerTPI"; -import {createSketcherSubject} from "./subjects/sketcherTPI"; +import {createSketcherTPI} from "./subjects/sketcherTPI"; +import {constant} from "lstream"; export const ModesConfig = { modellerUI: { testSubject: win => modellerUISubject(win.__CAD_APP), - startPage: 'http://localhost:3000/index.html#TestProject' + startPage: 'http://localhost:3000/index.html#TestProject', + loadStream: win => win.__CAD_APP.streams.lifecycle.projectLoaded }, sketcherUI: { - testSubject: win => createSketcherSubject(win.__CAD_APP), - startPage: 'http://localhost:3000/sketcher.html#TestProject' + testSubject: win => createSketcherTPI(win.__CAD_APP), + startPage: 'http://localhost:3000/sketcher.html#TestProject', + loadStream: win => constant(true) }, }; \ No newline at end of file diff --git a/test/coreTests/subjects/sketcherTPI.js b/test/coreTests/subjects/sketcherTPI.js index d1caa47d..d023fa86 100644 --- a/test/coreTests/subjects/sketcherTPI.js +++ b/test/coreTests/subjects/sketcherTPI.js @@ -20,21 +20,21 @@ export function createSubjectFromInPlaceSketcher(ctx) { actions }; - return createSketcherSubject(oldStyleSketcherApp); + return createSketcherTPI(oldStyleSketcherApp); } -export function createSketcherSubject(sketcherApp) { +export function createSketcherTPI(context) { - const viewer = sketcherApp.viewer; + const viewer = context.viewer; viewer.parametricManager.messageSink = msg => console.log(msg); - const addSegment = sketcher_utils.addSegmentInModel.bind(this, sketcherApp); - const addArc = sketcher_utils.addArc.bind(this, sketcherApp); - const addCircle = sketcher_utils.addCircle.bind(this, sketcherApp); - const addEllipse = sketcher_utils.addEllipse.bind(this, sketcherApp); - const addEllipticalArc = sketcher_utils.addEllipticalArc.bind(this, sketcherApp); - const addBezier = sketcher_utils.addBezier.bind(this, sketcherApp); - const move = sketcher_utils.moveInModel.bind(this, sketcherApp); + const addSegment = sketcher_utils.addSegmentInModel.bind(this, context); + const addArc = sketcher_utils.addArc.bind(this, context); + const addCircle = sketcher_utils.addCircle.bind(this, context); + const addEllipse = sketcher_utils.addEllipse.bind(this, context); + const addEllipticalArc = sketcher_utils.addEllipticalArc.bind(this, context); + const addBezier = sketcher_utils.addBezier.bind(this, context); + const move = sketcher_utils.moveInModel.bind(this, context); function addRectangle(x0, y0, x1, y1) { return [ addSegment(x0, y0, x1, y0), @@ -82,24 +82,32 @@ export function createSketcherSubject(sketcherApp) { function click(modelX, modelY, attrs) { let [x, y] = sketcher_utils.modelToScreen(viewer, modelX, modelY); - sketcher_utils.clickXY(sketcherApp, x, y, attrs); + sketcher_utils.clickXY(context, x, y, attrs); } function select(objects, inclusive) { - sketcherApp.viewer.select(objects, !inclusive); + context.viewer.select(objects, !inclusive); } - function runAction(id) { - sketcherApp.actions[id].action(); + function runAction(id, actionContext) { + const action = context.actions[id]; + if (!action ) { + throw `action ${id} doesn't exist`; + } + action.invoke(context, actionContext); } function toModel(x, y) { - return sketcher_utils.toModel(sketcherApp, x, y); + return sketcher_utils.toModel(context, x, y); } - + + function toScreen(x, y) { + return sketcher_utils.modelToScreen(context.viewer, x, y); + } + return { addSegment, addRectangle, addArc, addCircle, addEllipse, addEllipticalArc, addSerpinski, addBezier, addPolygon, - move, changeLayer, changeToConstructionLayer, changeToDefaultLayer, toModel, + move, changeLayer, changeToConstructionLayer, changeToDefaultLayer, toModel, toScreen, click, select, runAction, viewer } diff --git a/test/coreTests/test.js b/test/coreTests/test.js index 697cde9f..5c6c65fc 100644 --- a/test/coreTests/test.js +++ b/test/coreTests/test.js @@ -1,14 +1,21 @@ export class TestEnv { - constructor(callback) { + constructor(startingPage, navigate, callback) { + this.currentPage = startingPage; + this.navigateImpl = navigate; + this.callback = callback; this.failed = false; this.finished = false; this.error = undefined; - this.callback = callback; this.took = performance.now() } + navigate(page) { + this.currentPage = page; + return this.navigateImpl(page); + } + done() { if (this.finished) { return; @@ -18,123 +25,9 @@ export class TestEnv { this.callback(this); } - fail(msg, optionalMsg) { - this.failed = true; - this.error = msg + (optionalMsg === undefined ? '' : ' ' + optionalMsg); - this.done(); - throw assert.fail(this.error); - } - - terminateOnError(error) { - this.failed = true; - this.error = error + ""; - this.done(); - throw error; - } - test(testBlock) { - const env = this; - return function() { - try { - testBlock.apply(this, arguments); - } catch (e) { - if (!env.finished) { - env.terminateOnError(e); - } - console.error(e); - } - } + testBlock.apply(this, arguments); } - assertTrue(stmt, msg) { - if (!stmt) { - this.fail('assertTrue fails.', msg); - } - } - - assertEmpty(array, msg) { - if (array.length !== 0) { - this.fail('assertEmpty fails. Array length = ' + array.length, msg); - } - } - - assertFalse(stmt, msg) { - if (stmt) { - this.fail('assertFalse fails.', msg); - } - } - - assertEquals(expected, actual, msg) { - if (expected !== actual) { - this.fail('assertEquals: Expected: ' + expected + ' but was ' + actual, msg); - } - } - - assertFloatEquals(expected, actual, msg) { - if (Math.abs(expected - actual) >= 1E-6) { - this.fail('assertFloatEquals: Expected: ' + expected + ' but was ' + actual, msg); - } - } - - assertPointXY2DEquals(expectedX, expectedY, actual, msg) { - if (actual.x !== expectedX || actual.y !== expectedY) { - this.fail('assertPoint2DEquals: Expected: (' + expectedX + ', ' + expectedY + ') but was (' + actual.x + ', ' + actual.y + ')' , msg); - } - } - - assertPoint2DEquals(expected, actial, msg) { - this.assertPointXY2DEquals(expected.x, expected.y, actial, msg); - } - - assertData(expected, actual) { - const expectedJSON = JSON.stringify(expected).replace(/\s/g, ''); - const actualJSON = JSON.stringify(actual).replace(/\s/g, ''); - if (actualJSON !== expectedJSON) { - console.log('EXPECTED:'); - console.log(this.prettyJSON(expected)); - console.log('ACTUAL:'); - console.log(this.prettyJSON(actual)); - if (checkSimilarity(expected, actual)) { - console.log("The data is similar(has same number of faces, loops and half-edges). Most likely it the test needs to be updated."); - } else { - console.warn("The data isn't similar(has different number of faces, loops or half-edges). Most likely something is really broken."); - } - this.fail('expected data different from actual. ^^see log above^^'); - } - } - - prettyJSON(obj) { - return JSON.stringify(obj, null, 0); - } } -function checkSimilarity(data1, data2) { - - function edgesCount(data) { - let count = 0; - for (let face of data.faces) { - face.forEach((loop) => count += loop.length); - } - return count; - } - - function loopsCount(data) { - let count = 0; - for (let face of data.faces) { - face.forEach(() => count ++); - } - return count; - } - - function info(data) { - const loops = loopsCount(data); - const edges = edgesCount(data); - return `faces: ${data.faces.length}; loops: ${loops}; half-edges: ${edges}`; - } - - const info1 = info(data1); - const info2 = info(data2); - console.log(info1 + " : " + info2); - return info1 === info2; - -} diff --git a/test/coreTests/testCases/segment.js b/test/coreTests/testCases/segment.js index b041ad9d..b1cb03db 100644 --- a/test/coreTests/testCases/segment.js +++ b/test/coreTests/testCases/segment.js @@ -1,31 +1,41 @@ import Vector from 'math/vector'; import {assertEquals, assertPoint2DEquals} from "../utils/asserts"; +import {createSketcherTPI} from "../subjects/sketcherTPI"; export const TEST_MODE = 'sketcherUI'; export function testSegmentWizard(env, tpi) { - env.assertEquals(0, tpi.viewer.activeLayer.objects.length); + assertEquals(0, tpi.viewer.activeLayer.objects.length); tpi.addSegment(10, 10, 100, 100); assertEquals(1, tpi.viewer.activeLayer.objects.length); const segment = tpi.viewer.activeLayer.objects[0]; assertEquals('TCAD.TWO.Segment', segment._class); - assertPoint2DEquals(tpi.toModel(10, 10), segment.a); - assertPoint2DEquals(tpi.toModel(100, 100), segment.b); + const [asx, asy] = tpi.toScreen(10, 10); + const [bsx, bsy] = tpi.toScreen(100, 100); + assertPoint2DEquals(tpi.toModel(asx, asy), segment.a); + assertPoint2DEquals(tpi.toModel(bsx, bsy), segment.b); env.done(); } -// -// function testSaveLoad(env, tpi) { -// env.assertEquals(0, app.viewer.activeLayer.objects.length); -// tpi.addSegment(10, 10, 100, 100); -// app.actions['save'].action(); -// test.sketch(env.test((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(); -// })); -// }, + +export function testSaveLoad(env, tpi) { + assertEquals(0, tpi.viewer.activeLayer.objects.length); + tpi.addSegment(10, 10, 100, 100); + tpi.runAction('Save'); + cy.visit('http://localhost:3000'); + cy.window().then(win => { + env.done(); + }); + // env.navigate('http://google.com').then(win => { + // const tpi = createSketcherTPI(win.__CAD_APP); + // assertEquals(1, tpi.viewer.activeLayer.objects.length); + // const segment = tpi.viewer.activeLayer.objects[0]; + // assertEquals('TCAD.TWO.Segment', segment._class); + // + // }); + +} +testSaveLoad.only = true; // // testSelection: function(env) { // test.emptySketch(env.test((win, app) => { diff --git a/test/coreTests/utils/sketcherUtils.js b/test/coreTests/utils/sketcherUtils.js index 3be48b7a..dda49319 100644 --- a/test/coreTests/utils/sketcherUtils.js +++ b/test/coreTests/utils/sketcherUtils.js @@ -1,43 +1,43 @@ import {TestMouseEvent} from './mouseEvent' import Vector from 'math/vector'; -export function toModel(app, x, y) { - return app.viewer._screenToModel(x, y); +export function toModel(ctx, x, y) { + return ctx.viewer._screenToModel(x, y); } -export function toModelP(app, point) { - return app.viewer._screenToModel(point.x, point.y); +export function toModelP(ctx, point) { + return ctx.viewer._screenToModel(point.x, point.y); } -export function getConstraints(app) { - return app.viewer.parametricManager.system.constraints; +export function getConstraints(ctx) { + return ctx.viewer.parametricManager.system.constraints; } -export function click(app, point, attrs) { - clickXY(app, point.x, point.y, attrs); +export function click(ctx, point, attrs) { + clickXY(ctx, point.x, point.y, attrs); } -export function clickXY(app, x, y, attrs) { - app.viewer.toolManager.tool.mousedown(new TestMouseEvent(x, y, 'mousedown', attrs)); - app.viewer.toolManager.tool.mouseup(new TestMouseEvent(x, y, 'mouseup', attrs)); +export function clickXY(ctx, x, y, attrs) { + ctx.viewer.toolManager.tool.mousedown(new TestMouseEvent(x, y, 'mousedown', attrs)); + ctx.viewer.toolManager.tool.mouseup(new TestMouseEvent(x, y, 'mouseup', attrs)); } -export function moveAndClickXY(app, x, y, attrs) { - app.viewer.toolManager.tool.mousemove(new TestMouseEvent(x, y, 'mousedown', attrs)); - clickXY(app, x, y, attrs); +export function moveAndClickXY(ctx, x, y, attrs) { + ctx.viewer.toolManager.tool.mousemove(new TestMouseEvent(x, y, 'mousedown', attrs)); + clickXY(ctx, x, y, attrs); } -export function move(app, from, to) { - const toolManager = app.viewer.toolManager; +export function move(ctx, from, to) { + const toolManager = ctx.viewer.toolManager; toolManager.tool.mousedown(new TestMouseEvent(from.x, from.y)); toolManager.tool.mousemove(new TestMouseEvent(to.x, to.y)); toolManager.tool.mouseup(new TestMouseEvent(to.x, to.y)); } -export function moveInModel(app, fromX, fromY, toX, toY) { - const toolManager = app.viewer.toolManager; - [fromX, fromY] = modelToScreen(app.viewer, fromX, fromY); - [toX, toY] = modelToScreen(app.viewer, toX, toY); +export function moveInModel(ctx, fromX, fromY, toX, toY) { + const toolManager = ctx.viewer.toolManager; + [fromX, fromY] = modelToScreen(ctx.viewer, fromX, fromY); + [toX, toY] = modelToScreen(ctx.viewer, toX, toY); toolManager.tool.mousemove(new TestMouseEvent(fromX, fromY)); toolManager.tool.mousedown(new TestMouseEvent(fromX, fromY)); @@ -46,94 +46,94 @@ export function moveInModel(app, fromX, fromY, toX, toY) { } -export function addSegment(app, aX, aY, bX, bY) { - app.actions.SegmentTool.invoke(app.context); - const tool = app.viewer.toolManager.tool; +export function addSegment(ctx, aX, aY, bX, bY) { + ctx.actions.SegmentTool.invoke(ctx); + const tool = ctx.viewer.toolManager.tool; tool.mousemove(new TestMouseEvent(aX, aY)); tool.mousedown(new TestMouseEvent(aX, aY)); tool.mouseup(new TestMouseEvent(aX, aY)); tool.mousemove(new TestMouseEvent(bX, bY)); const segment = tool.line; tool.mouseup(new TestMouseEvent(bX, bY)); - app.viewer.toolManager.releaseControl(); + ctx.viewer.toolManager.releaseControl(); return segment; } -export function addSegmentInModel(app, aX, aY, bX, bY) { +export function addSegmentInModel(ctx, aX, aY, bX, bY) { - [aX, aY] = modelToScreen(app.viewer, aX, aY); - [bX, bY] = modelToScreen(app.viewer, bX, bY); + [aX, aY] = modelToScreen(ctx.viewer, aX, aY); + [bX, bY] = modelToScreen(ctx.viewer, bX, bY); - return addSegment(app, aX, aY, bX, bY); + return addSegment(ctx, aX, aY, bX, bY); } -export function addArc(app, cX, cY, aX, aY, bX, bY) { +export function addArc(ctx, cX, cY, aX, aY, bX, bY) { - [aX, aY] = modelToScreen(app.viewer, aX, aY); - [bX, bY] = modelToScreen(app.viewer, bX, bY); - [cX, cY] = modelToScreen(app.viewer, cX, cY); + [aX, aY] = modelToScreen(ctx.viewer, aX, aY); + [bX, bY] = modelToScreen(ctx.viewer, bX, bY); + [cX, cY] = modelToScreen(ctx.viewer, cX, cY); - app.actions['addArc'].action(); + ctx.actions['addArc'].action(); - moveAndClickXY(app, cX, cY); - moveAndClickXY(app, aX, aY); - let arc = app.viewer.toolManager.tool.arc; - moveAndClickXY(app, bX, bY); - app.viewer.toolManager.releaseControl(); + moveAndClickXY(ctx, cX, cY); + moveAndClickXY(ctx, aX, aY); + let arc = ctx.viewer.toolManager.tool.arc; + moveAndClickXY(ctx, bX, bY); + ctx.viewer.toolManager.releaseControl(); return arc; } -export function addCircle(app, cX, cY, R) { - let [rX, rY] = modelToScreen(app.viewer, cX + R, cY); - [cX, cY] = modelToScreen(app.viewer, cX, cY); - app.actions['addCircle'].action(); - moveAndClickXY(app, cX, cY); - let circle = app.viewer.toolManager.tool.circle; - moveAndClickXY(app, rX, rY); - app.viewer.toolManager.releaseControl(); +export function addCircle(ctx, cX, cY, R) { + let [rX, rY] = modelToScreen(ctx.viewer, cX + R, cY); + [cX, cY] = modelToScreen(ctx.viewer, cX, cY); + ctx.actions['addCircle'].action(); + moveAndClickXY(ctx, cX, cY); + let circle = ctx.viewer.toolManager.tool.circle; + moveAndClickXY(ctx, rX, rY); + ctx.viewer.toolManager.releaseControl(); return circle; } -export function addEllipse(app, aX, aY, bX, bY, rX, rY) { - [aX, aY] = modelToScreen(app.viewer, aX, aY); - [bX, bY] = modelToScreen(app.viewer, bX, bY); - [rX, rY] = modelToScreen(app.viewer, rX, rY); - app.actions['addEllipse'].action(); - moveAndClickXY(app, aX, aY); - let ellipse = app.viewer.toolManager.tool.ellipse; - moveAndClickXY(app, bX, bY); - moveAndClickXY(app, rX, rY); - app.viewer.toolManager.releaseControl(); +export function addEllipse(ctx, aX, aY, bX, bY, rX, rY) { + [aX, aY] = modelToScreen(ctx.viewer, aX, aY); + [bX, bY] = modelToScreen(ctx.viewer, bX, bY); + [rX, rY] = modelToScreen(ctx.viewer, rX, rY); + ctx.actions['addEllipse'].action(); + moveAndClickXY(ctx, aX, aY); + let ellipse = ctx.viewer.toolManager.tool.ellipse; + moveAndClickXY(ctx, bX, bY); + moveAndClickXY(ctx, rX, rY); + ctx.viewer.toolManager.releaseControl(); return ellipse; } -export function addEllipticalArc(app, aX, aY, bX, bY, rX, rY) { - [aX, aY] = modelToScreen(app.viewer, aX, aY); - [bX, bY] = modelToScreen(app.viewer, bX, bY); - [rX, rY] = modelToScreen(app.viewer, rX, rY); - app.actions['addEllipticalArc'].action(); - moveAndClickXY(app, aX, aY); - let ellipse = app.viewer.toolManager.tool.ellipse; - moveAndClickXY(app, bX, bY); - moveAndClickXY(app, rX, rY); - app.viewer.toolManager.releaseControl(); +export function addEllipticalArc(ctx, aX, aY, bX, bY, rX, rY) { + [aX, aY] = modelToScreen(ctx.viewer, aX, aY); + [bX, bY] = modelToScreen(ctx.viewer, bX, bY); + [rX, rY] = modelToScreen(ctx.viewer, rX, rY); + ctx.actions['addEllipticalArc'].action(); + moveAndClickXY(ctx, aX, aY); + let ellipse = ctx.viewer.toolManager.tool.ellipse; + moveAndClickXY(ctx, bX, bY); + moveAndClickXY(ctx, rX, rY); + ctx.viewer.toolManager.releaseControl(); return ellipse; } -export function addBezier(app, aX, aY, bX, bY) { - [aX, aY] = modelToScreen(app.viewer, aX, aY); - [bX, bY] = modelToScreen(app.viewer, bX, bY); - app.actions['addBezierCurve'].action(); - moveAndClickXY(app, aX, aY); - let curve = app.viewer.toolManager.tool.curve; - moveAndClickXY(app, bX, bY); - app.viewer.toolManager.releaseControl(); +export function addBezier(ctx, aX, aY, bX, bY) { + [aX, aY] = modelToScreen(ctx.viewer, aX, aY); + [bX, bY] = modelToScreen(ctx.viewer, bX, bY); + ctx.actions['addBezierCurve'].action(); + moveAndClickXY(ctx, aX, aY); + let curve = ctx.viewer.toolManager.tool.curve; + moveAndClickXY(ctx, bX, bY); + ctx.viewer.toolManager.releaseControl(); return curve; } -export function polyLine(app) { - app.actions['addMultiSegment'].action(); - const tool = app.viewer.toolManager.tool; +export function polyLine(ctx) { + ctx.actions['addMultiSegment'].action(); + const tool = ctx.viewer.toolManager.tool; for (let i = 1; i < arguments.length; ++i) { let p = arguments[i]; tool.mousemove(new TestMouseEvent(p.x, p.y)); @@ -141,7 +141,7 @@ export function polyLine(app) { tool.mouseup(new TestMouseEvent(p.x, p.y)); } tool.cancelSegment(); - app.viewer.toolManager.releaseControl(); + ctx.viewer.toolManager.releaseControl(); } @@ -161,17 +161,11 @@ export class TestSegment { return this.a.plus(half); } - add(app) { - return addSegment(app, this.a.x, this.a.y, this.b.x, this.b.y); + add(ctx) { + return addSegment(ctx, this.a.x, this.a.y, this.b.x, this.b.y); } } export function modelToScreen(viewer, x, y) { - if (viewer.screenToModelMatrix) { - let modelToScreenMx = viewer.screenToModelMatrix.invert(); - [x, y] = modelToScreenMx.apply3([x, y, 0]); - } - x /= viewer.retinaPxielRatio; - y = (viewer.canvas.height - y) / viewer.retinaPxielRatio; - return [x, y]; + return viewer.modelToScreen(x, y); } diff --git a/web/app/sketcher/viewer2d.js b/web/app/sketcher/viewer2d.js index adf6915d..46b9aea9 100644 --- a/web/app/sketcher/viewer2d.js +++ b/web/app/sketcher/viewer2d.js @@ -357,6 +357,16 @@ class Viewer { return out; }; + modelToScreen(x, y) { + if (this.screenToModelMatrix) { + let modelToScreenMx = this.screenToModelMatrix.invert(); + [x, y] = modelToScreenMx.apply3([x, y, 0]); + } + x /= this.retinaPxielRatio; + y = (this.canvas.height - y) / this.retinaPxielRatio; + return [x, y]; + } + accept = visitor => { for (let layer of this.layers) { for (let object of layer.objects) {