Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/devextreme-cli/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default [
files: ['testing/**/*.js'],
languageOptions: {
globals: {
...globals.jest
...globals.vitest
}
}
}
Expand Down
6 changes: 0 additions & 6 deletions packages/devextreme-cli/jest-themebuilder.config.js

This file was deleted.

8 changes: 0 additions & 8 deletions packages/devextreme-cli/jest.config.js

This file was deleted.

11 changes: 6 additions & 5 deletions packages/devextreme-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"create-template": "node ./testing/creating.js",
"verify-template": "node ./testing/verifying.js",
"lint-template": "node ./testing/linting.js",
"test-template": "node --experimental-vm-modules ./testing/testing.js",
"test-dev": "cross-env TEST_MODE=dev NODE_OPTIONS=--experimental-vm-modules jest",
"test-themebuilder": "jest --config=./jest-themebuilder.config.js --runInBand",
"test-template": "node ./testing/testing.js",
"test-dev": "cross-env TEST_MODE=dev vitest run",
"test-themebuilder": "vitest run --config ./vitest.themebuilder.config.mjs",
"docker:build": "docker build --rm -f \"testing/docker/Dockerfile\" -t devextreme-cli:latest \"testing/docker\" --progress=plain",
"docker:run": "docker run --rm -d -p 9222:9222/tcp devextreme-cli:latest"
},
Expand Down Expand Up @@ -67,13 +67,14 @@
"eslint-plugin-unused-imports": "^4.4.1",
"eslint-plugin-vue": "^10.11.1",
"globals": "^15.15.0",
"jest": "^29.7.0",
"jest-image-snapshot": "^6.5.2",
"pixelmatch": "^7.2.0",
"pngjs": "^7.0.0",
"prettier": "^2.8.8",
"rimraf": "^2.7.1",
"tree-kill": "^1.2.2",
"tree-kill-promise": "^1.0.12",
"typescript": "^4.9.5",
"vitest": "^5.0.5",
"vue-eslint-parser": "^10.4.1",
"wait-on": "8.0.5"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ module.exports = (env, { port = 8080, urls = {} } = {}) => {
interval: 100
});
} catch(e) {
// NOTE jest@27 will fail test, but jest@26 - not
throw new Error(e);
}
});
Expand Down
6 changes: 0 additions & 6 deletions packages/devextreme-cli/testing/jest-setup.js

This file was deleted.

38 changes: 8 additions & 30 deletions packages/devextreme-cli/testing/testing.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const jest = require('jest');
const path = require('path');
const minimist = require('minimist');
const envs = require('./constants').envs;

Expand All @@ -14,34 +12,14 @@ const args = minimist(process.argv.slice(), {
});

async function runTest(envirorments) {
const options = {
testPathIgnorePatterns: [
'./testing/sandbox/'
],
projects: [
'./testing/__tests__'
],
testPathPattern: envirorments.map(env => `./testing/__tests__/${env.engine}.test.js`),
setupFiles: [
path.join(process.cwd(), 'jest.config.js')
],
setupFilesAfterEnv: [
path.join(process.cwd(), 'testing/jest-setup.js')
],
forceExit: true,
showConfig: false,
runInBand: true
};
jest
.runCLI(options, options.projects)
.then(success => {
success.results.numFailedTestSuites || success.results.numFailedTests
? process.exit(1)
: process.exit(0);
})
.catch(() => {
process.exit(1);
});
try {
const { startVitest } = await import('vitest/node');
await startVitest('test', envirorments.map(env => `testing/__tests__/${env.engine}.test.js`), { run: true });
} catch(e) {
console.error(e);
process.exitCode = 1;
}
process.exit();
}

(async function testProccess() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const {
const workDirectory = join(__dirname, 'bootstrap');

describe('ThemeBuilder bootstrap integration tests', () => {
jest.setTimeout(1800000); // 30min
beforeAll(async() => {
await buildPackage();
await mkdir(workDirectory, { recursive: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const {
const workDirectory = join(__dirname, 'install-local');

describe('ThemeBuilder local install tests', () => {
jest.setTimeout(1800000); // 30min
beforeAll(async() => {
await buildPackage();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ const runThemeBuilder = async(command, meta, parameters) => {
};

describe('ThemeBuilder save metadata and variables tests', () => {
jest.setTimeout(1800000); // 30min
beforeAll(async() => {
await buildPackage();
});
Expand Down
99 changes: 99 additions & 0 deletions packages/devextreme-cli/testing/utils/image-snapshot.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs';
import { dirname, join } from 'path';
import pixelmatch from 'pixelmatch';
import { PNG } from 'pngjs';

const SNAPSHOTS_DIR = '__image_snapshots__';
const diffConfig = { threshold: 0.01 };

const writeImage = (filePath, content) => {
mkdirSync(dirname(filePath), { recursive: true });
writeFileSync(filePath, content);
};

const resize = (image, width, height) => {
if(image.width === width && image.height === height) {
return image;
}

const result = new PNG({ width, height, fill: true });
PNG.bitblt(image, result, 0, 0, image.width, image.height, 0, 0);
return result;
};

const composeDiff = (images) => {
const { width, height } = images[0];
const result = new PNG({ width: width * images.length, height });

images.forEach((image, index) => PNG.bitblt(image, result, 0, 0, width, height, width * index, 0));
return PNG.sync.write(result, { filterType: 4 });
};

export function toMatchImageSnapshot(received, {
customSnapshotIdentifier,
customDiffDir,
customReceivedDir,
storeReceivedOnFailure = false
}) {
const { testPath, snapshotState, isNot } = this;

if(isNot) {
throw new Error('`.not` cannot be used with `.toMatchImageSnapshot()`.');
}

const receivedBuffer = Buffer.from(received);
const snapshotsDir = join(dirname(testPath), SNAPSHOTS_DIR);
const snapshotPath = join(snapshotsDir, `${customSnapshotIdentifier}.png`);
const diffPath = join(customDiffDir || join(snapshotsDir, '__diff_output__'), `${customSnapshotIdentifier}-diff.png`);
const receivedPath = join(customReceivedDir || join(snapshotsDir, '__received_output__'), `${customSnapshotIdentifier}-received.png`);
const updateState = snapshotState.snapshotUpdateState;

if(!existsSync(snapshotPath)) {
if(updateState === 'none') {
return {
pass: false,
message: () => `New snapshot ${snapshotPath} was not written. The update flag must be explicitly passed to write a new snapshot on CI.`
};
}

writeImage(snapshotPath, receivedBuffer);
return { pass: true, message: () => '' };
}

rmSync(diffPath, { force: true });
rmSync(receivedPath, { force: true });

const rawReceivedImage = PNG.sync.read(receivedBuffer);
const rawSnapshotImage = PNG.sync.read(readFileSync(snapshotPath));
const isSizeMatched = rawReceivedImage.width === rawSnapshotImage.width && rawReceivedImage.height === rawSnapshotImage.height;
const width = Math.max(rawReceivedImage.width, rawSnapshotImage.width);
const height = Math.max(rawReceivedImage.height, rawSnapshotImage.height);
const receivedImage = resize(rawReceivedImage, width, height);
const snapshotImage = resize(rawSnapshotImage, width, height);
const diffImage = new PNG({ width, height });

const diffPixelCount = pixelmatch(receivedImage.data, snapshotImage.data, diffImage.data, width, height, diffConfig);

if(isSizeMatched && diffPixelCount === 0) {
return { pass: true, message: () => '' };
}

if(updateState === 'all') {
writeImage(snapshotPath, receivedBuffer);
return { pass: true, message: () => '' };
}

if(storeReceivedOnFailure) {
writeImage(receivedPath, receivedBuffer);
}
writeImage(diffPath, composeDiff([snapshotImage, diffImage, receivedImage]));

const failure = isSizeMatched
? `Expected image to match the snapshot, but ${diffPixelCount} pixels (${diffPixelCount / (width * height) * 100}%) are different.`
: `Expected image to be the same size as the snapshot (${rawSnapshotImage.width}x${rawSnapshotImage.height}), but was ${rawReceivedImage.width}x${rawReceivedImage.height}.`;

return {
pass: false,
message: () => `${failure}\nSee diff for details: ${diffPath}`
};
}
4 changes: 4 additions & 0 deletions packages/devextreme-cli/testing/vitest-setup.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { expect } from 'vitest';
import { toMatchImageSnapshot } from './utils/image-snapshot.mjs';

expect.extend({ toMatchImageSnapshot });
12 changes: 12 additions & 0 deletions packages/devextreme-cli/vitest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
include: ['testing/__tests__/*.test.js'],
setupFiles: ['testing/vitest-setup.mjs'],
globals: true,
testTimeout: 300000,
hookTimeout: 300000,
fileParallelism: false
}
});
11 changes: 11 additions & 0 deletions packages/devextreme-cli/vitest.themebuilder.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
include: ['testing/themebuilder/*.test.js'],
globals: true,
testTimeout: 1800000,
hookTimeout: 1800000,
fileParallelism: false
}
});
Loading
Loading