mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
replace old test framework with cypress, migrate the tests
This commit is contained in:
parent
13eb317c89
commit
6d7d2648e3
115 changed files with 1167 additions and 822 deletions
9
cypress.json
Normal file
9
cypress.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"watchForFileChanges": false,
|
||||
"fixturesFolder": "test/cypress/fixtures",
|
||||
"integrationFolder": "test/cypress/integration",
|
||||
"pluginsFile": "test/cypress/plugins/index.js",
|
||||
"screenshotsFolder": "test/cypress/screenshots",
|
||||
"videosFolder": "test/cypress/videos",
|
||||
"supportFile": "test/cypress/support/index.js"
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
// @deprecated - use streams
|
||||
export default class Bus {
|
||||
|
||||
constructor() {
|
||||
|
|
|
|||
1005
package-lock.json
generated
1005
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -4,10 +4,10 @@
|
|||
"description": "JS.Sketcher is a parametric 2D and 3D CAD modeler written in pure javascript",
|
||||
"scripts": {
|
||||
"start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.config.js --content-base web/ --port 3000 --host 0.0.0.0",
|
||||
"start-test": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.config.dev.js --content-base web/ --port 3000 --host 0.0.0.0",
|
||||
"pack": "node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --progress --profile --colors",
|
||||
"build": "grunt",
|
||||
"lint": "eslint web/app"
|
||||
"lint": "eslint web/app",
|
||||
"cypress": "npx cypress open"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -32,11 +32,13 @@
|
|||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-stage-2": "^7.0.0",
|
||||
"@cypress/webpack-preprocessor": "^4.1.3",
|
||||
"babel-eslint": "^10.0.2",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.5",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"css-loader": "0.28.7",
|
||||
"cypress": "^4.2.0",
|
||||
"eslint": "4.13.1",
|
||||
"eslint-plugin-babel": "4.1.2",
|
||||
"eslint-plugin-import": "2.8.0",
|
||||
|
|
|
|||
58
test/coreTests/defineCypress.js
Normal file
58
test/coreTests/defineCypress.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import {camelCaseSplitToStr} from "gems/camelCaseSplit";
|
||||
import {TestEnv} from "./test";
|
||||
import {ModesConfig} from "./modes";
|
||||
|
||||
export function defineCypressTest(groupName, module) {
|
||||
|
||||
if (!module.TEST_MODE) {
|
||||
throw 'modules should have a mode defined';
|
||||
}
|
||||
|
||||
let hasOnly = false;
|
||||
const tests = Object.keys(module).filter(key => key.startsWith('test')).map(key => {
|
||||
const func = module[key];
|
||||
if (func.only) {
|
||||
hasOnly = true;
|
||||
}
|
||||
return {
|
||||
name: camelCaseSplitToStr(key.substring("test".length)),
|
||||
funcName: key,
|
||||
func,
|
||||
...ModesConfig[module.TEST_MODE]
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
(hasOnly ? describe.only : describe)(groupName, () => {
|
||||
|
||||
for (let test of tests) {
|
||||
(test.func.only ? it.only : it)(test.name, () => {
|
||||
cy.visit(test.startPage);
|
||||
|
||||
cy.window().then(win => {
|
||||
cy.log("Core Test: " + test.funcName);
|
||||
return new Promise((resolve, reject) => {
|
||||
const subject = test.testSubject(win);
|
||||
const testEnv = new TestEnv(() => {
|
||||
cy.log("took: " + durationFormat(testEnv.took));
|
||||
resolve();
|
||||
});
|
||||
test.func(testEnv, subject);
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function durationFormat(millis){
|
||||
function fixed(v) {
|
||||
return v.toFixed(2);
|
||||
}
|
||||
if (millis < 1000) {
|
||||
return fixed(millis) + "ms";
|
||||
} else {
|
||||
return fixed(millis / 1000) + "s";
|
||||
}
|
||||
}
|
||||
|
||||
13
test/coreTests/modes.js
Normal file
13
test/coreTests/modes.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import modellerUISubject from "./subjects/modellerUISubject";
|
||||
import {createSketcherSubject} from "./subjects/sketcherUISubject";
|
||||
|
||||
export const ModesConfig = {
|
||||
modellerUI: {
|
||||
testSubject: win => modellerUISubject(win.__CAD_APP),
|
||||
startPage: 'http://localhost:3000/index.html#TestProject'
|
||||
},
|
||||
sketcherUI: {
|
||||
testSubject: win => createSketcherSubject(win.__CAD_APP),
|
||||
startPage: 'http://localhost:3000/index.html#TestProject'
|
||||
},
|
||||
};
|
||||
|
|
@ -3,8 +3,8 @@ import {
|
|||
ALL_EXCLUDING_SOLID_KINDS,
|
||||
PICK_KIND,
|
||||
traversePickResults
|
||||
} from '../../../../app/cad/scene/controls/pickControlPlugin';
|
||||
import {DATUM} from '../../../../app/cad/scene/entites';
|
||||
} from '../../../web/app/cad/scene/controls/pickControlPlugin';
|
||||
import {DATUM} from '../../../web/app/cad/scene/entites';
|
||||
|
||||
export default ctx => {
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import * as sketcher_utils from '../../../utils/sketcher-utils'
|
||||
import {decapitalize} from '../../../../../modules/gems/capitalize';
|
||||
import genSerpinski, {genSerpinskiImpl} from '../../../../app/utils/genSerpinski';
|
||||
import {distance, distanceAB} from '../../../../app/math/math';
|
||||
import * as sketcher_utils from '../utils/sketcherUtils'
|
||||
import {decapitalize} from '../../../modules/gems/capitalize';
|
||||
import genSerpinski, {genSerpinskiImpl} from '../../../web/app/utils/genSerpinski';
|
||||
import {distance, distanceAB} from '../../../web/app/math/math';
|
||||
|
||||
export function createSubjectFromInPlaceSketcher(ctx) {
|
||||
let actions = {};
|
||||
|
|
@ -1,10 +1,4 @@
|
|||
|
||||
export function createFailError(msg) {
|
||||
let error = new Error(msg);
|
||||
error.assertionFail = true;
|
||||
return error;
|
||||
}
|
||||
|
||||
export class TestEnv {
|
||||
|
||||
constructor(callback) {
|
||||
|
|
@ -28,7 +22,7 @@ export class TestEnv {
|
|||
this.failed = true;
|
||||
this.error = msg + (optionalMsg === undefined ? '' : ' ' + optionalMsg);
|
||||
this.done();
|
||||
throw createFailError(this.error);
|
||||
throw assert.fail(this.error);
|
||||
}
|
||||
|
||||
terminateOnError(error) {
|
||||
|
|
@ -144,60 +138,3 @@ function checkSimilarity(data1, data2) {
|
|||
return info1 === info2;
|
||||
|
||||
}
|
||||
|
||||
export function load(url, callback, apiGet) {
|
||||
const sandbox = $('#sandbox');
|
||||
sandbox.empty();
|
||||
const frame = $('<iframe>');
|
||||
sandbox.append(frame);
|
||||
$(function() { // fire event when iframe is ready
|
||||
frame.on('load', function() {
|
||||
const win = frame.get(0).contentWindow;
|
||||
callback(win, apiGet(win))
|
||||
});
|
||||
});
|
||||
frame.attr('src', window.location.origin + url)
|
||||
}
|
||||
|
||||
const TEST_PROJECT = '$$$__test__$$$';
|
||||
const STORAGE_PREFIX_SKETCH = "TCAD.projects.";
|
||||
|
||||
const SKETCHER_API = win => win.__CAD_APP;
|
||||
const MODELLER_API = win => ({TPI: win.__CAD_APP.services.tpi});
|
||||
|
||||
export function emptySketch(callback) {
|
||||
localStorage.removeItem(STORAGE_PREFIX_SKETCH + TEST_PROJECT);
|
||||
sketch(callback);
|
||||
}
|
||||
|
||||
export function sketch(callback) {
|
||||
load('/sketcher.html#' + TEST_PROJECT, callback, SKETCHER_API);
|
||||
}
|
||||
|
||||
let ModellerWin = null;
|
||||
export function modeller(callback) {
|
||||
if (ModellerWin != null) {
|
||||
ModellerWin.__CAD_APP.services.project.empty();
|
||||
callback(ModellerWin, MODELLER_API(ModellerWin));
|
||||
return;
|
||||
}
|
||||
load('/index.html#' + TEST_PROJECT, (win, api) => {
|
||||
ModellerWin = win;
|
||||
let ctx = win.__CAD_APP;
|
||||
ctx.streams.lifecycle.projectLoaded.attach(loaded => {
|
||||
if (loaded) {
|
||||
callback(win, api);
|
||||
}
|
||||
})
|
||||
}, MODELLER_API);
|
||||
}
|
||||
|
||||
export function emptyModeller(callback) {
|
||||
for(let i = localStorage.length - 1; i >= 0 ; i--) {
|
||||
const key = localStorage.key(i);
|
||||
if (key.startsWith(STORAGE_PREFIX_SKETCH + TEST_PROJECT)) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
modeller(callback);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {DATUM} from '../../app/cad/scene/entites';
|
||||
import {DATUM} from '../../../web/app/cad/scene/entites';
|
||||
import {assertEquals, assertTrue} from '../utils/asserts';
|
||||
|
||||
export const TEST_MODE = 'modellerUI';
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import {assertEquals, assertTrue} from '../utils/asserts';
|
||||
import {DATUM} from '../../app/cad/scene/entites';
|
||||
import {DATUM} from '../../../web/app/cad/scene/entites';
|
||||
|
||||
export const TEST_MODE = 'modellerUI';
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {defineTests} from './craftTestUtils';
|
||||
import {defineTests} from '../craftTestUtils';
|
||||
|
||||
export default defineTests([
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {defineTests} from './craftTestUtils';
|
||||
import {defineTests} from '../craftTestUtils';
|
||||
|
||||
export default defineTests([
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import * as test from '../test'
|
||||
import * as test from '../../test'
|
||||
|
||||
export default {
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import * as test from '../test'
|
||||
import {deepMerge} from '../utils/deep-merge'
|
||||
import {Matrix3} from '../../app/math/l3space'
|
||||
import * as test from '../../test'
|
||||
import {deepMerge} from '../coreTests/utils/deep-merge'
|
||||
import {Matrix3} from '../../../../web/app/math/l3space'
|
||||
|
||||
const OPERANDS_MODE = false;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import * as test from '../test'
|
||||
import * as test from '../../test'
|
||||
|
||||
export default {
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import * as test from '../test'
|
||||
import * as test from '../../test'
|
||||
|
||||
export default {
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import * as test from '../test'
|
||||
import * as test from '../../test'
|
||||
|
||||
const TESTS = {};
|
||||
let counter = 0;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as test from '../test'
|
||||
import * as sketcher_utils from '../utils/sketcher-utils'
|
||||
import * as test from '../../test'
|
||||
import * as sketcher_utils from '../../utils/sketcherUtils'
|
||||
|
||||
export default {
|
||||
testCoincident: function (env) {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import * as test from '../test'
|
||||
import * as sketcher_utils from '../utils/sketcher-utils'
|
||||
import {TestMouseEvent} from '../utils/mouse-event'
|
||||
import * as sketcher_utils from '../utils/sketcherUtils'
|
||||
import {TestMouseEvent} from '../utils/mouseEvent'
|
||||
import Vector from 'math/vector';
|
||||
|
||||
export default {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import * as test from '../test'
|
||||
import * as sketcher_utils from '../utils/sketcher-utils'
|
||||
import * as sketcher_utils from '../utils/sketcherUtils'
|
||||
import * as keyboard from '../utils/keyboard'
|
||||
import {TestMouseEvent} from '../utils/mouse-event'
|
||||
import {TestMouseEvent} from '../utils/mouseEvent'
|
||||
import Vector from 'math/vector';
|
||||
|
||||
export default {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import {createFailError} from '../test';
|
||||
import sketchObjectGlobalId from '../../app/cad/sketch/sketchObjectGlobalId';
|
||||
import sketchObjectGlobalId from '../../../web/app/cad/sketch/sketchObjectGlobalId';
|
||||
|
||||
export function fail(msg, optionalMsg) {
|
||||
throw createFailError(msg + (optionalMsg === undefined ? '' : ' ' + optionalMsg));
|
||||
assert.fail(msg + (optionalMsg === undefined ? '' : ' ' + optionalMsg));
|
||||
}
|
||||
|
||||
export function assertTrue(stmt, msg) {
|
||||
|
|
@ -15,7 +15,7 @@ export function assertTrue(stmt, msg) {
|
|||
}
|
||||
|
||||
export function assertEmpty(array, msg) {
|
||||
if (typeof stmt === 'string') {
|
||||
if (typeof msg === 'string') {
|
||||
throw 'wrong assertion usage, mixed up arguments';
|
||||
}
|
||||
if (array.length !== 0) {
|
||||
|
|
@ -48,7 +48,7 @@ export function assertPointXY2DEquals(expectedX, expectedY, actual, msg) {
|
|||
}
|
||||
|
||||
export function assertPoint2DEquals(expected, actial, msg) {
|
||||
this.assertPointXY2DEquals(expected.x, expected.y, actial, msg);
|
||||
assertPointXY2DEquals(expected.x, expected.y, actial, msg);
|
||||
}
|
||||
|
||||
export function assertFaceIsPlane(face) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {TestMouseEvent} from './mouse-event'
|
||||
import {TestMouseEvent} from './mouseEvent'
|
||||
import Vector from 'math/vector';
|
||||
|
||||
export function toModel(app, x, y) {
|
||||
2
test/cypress/.gitignore
vendored
Normal file
2
test/cypress/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/screenshots/
|
||||
/videos/
|
||||
30
test/cypress/integration/part3d/craft.spec.js
Normal file
30
test/cypress/integration/part3d/craft.spec.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/// <reference types="cypress" />
|
||||
|
||||
import * as PlaneTests from '../../../coreTests/testCases/craftPlane';
|
||||
import * as ExtrudeBasicShapesTests from '../../../coreTests/testCases/craftExtrudeBasicShapes';
|
||||
import * as ExtrudeOptionsTests from '../../../coreTests/testCases/craftExtrudeOptions';
|
||||
import * as ExtrudeTests from '../../../coreTests/testCases/craftExtrude';
|
||||
import * as CutTests from '../../../coreTests/testCases/craftCut';
|
||||
import * as RevolveTests from '../../../coreTests/testCases/craftRevolve';
|
||||
import * as FilletTests from '../../../coreTests/testCases/craftFillet';
|
||||
import * as LoftTests from '../../../coreTests/testCases/craftLoft';
|
||||
import * as DatumTests from '../../../coreTests/testCases/craftDatum';
|
||||
import * as BooleanTests from '../../../coreTests/testCases/craftBoolean';
|
||||
|
||||
import {defineCypressTest} from "../../../coreTests/defineCypress";
|
||||
|
||||
describe("Craft Operations", () => {
|
||||
defineCypressTest("Plane Operation", PlaneTests);
|
||||
defineCypressTest("Extrude - all sketcher objects", ExtrudeBasicShapesTests);
|
||||
defineCypressTest("Extrude Options", ExtrudeOptionsTests);
|
||||
defineCypressTest("Extrude Operation", ExtrudeTests);
|
||||
defineCypressTest("Cut Operation", CutTests);
|
||||
defineCypressTest("Revolve Operation", RevolveTests);
|
||||
defineCypressTest("Fillet Operation", FilletTests);
|
||||
defineCypressTest("Loft Operation", LoftTests);
|
||||
defineCypressTest("Datum Operation", DatumTests);
|
||||
defineCypressTest("General Boolean Operation", BooleanTests);
|
||||
});
|
||||
|
||||
|
||||
|
||||
0
test/cypress/integration/sketcher/tools.spec.js
Normal file
0
test/cypress/integration/sketcher/tools.spec.js
Normal file
29
test/cypress/plugins/index.js
Normal file
29
test/cypress/plugins/index.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
const webpack = require('@cypress/webpack-preprocessor')
|
||||
|
||||
module.exports = (on) => {
|
||||
const options = {
|
||||
// send in the options from your webpack.config.js, so it works the same
|
||||
// as your app's code
|
||||
webpackOptions: require('../../../webpack.config'),
|
||||
watchOptions: {},
|
||||
};
|
||||
|
||||
on('file:preprocessor', webpack(options))
|
||||
};
|
||||
25
test/cypress/support/commands.js
Normal file
25
test/cypress/support/commands.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue