Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci(e2e): support relative imports #9108

Merged
merged 24 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
4 changes: 3 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/cached-install
with:
node-version: 18.x
- name: Build fabric.js
uses: ./.github/actions/build-fabric-cached
# Playwright suggests against caching the browser install
Expand All @@ -127,7 +129,7 @@ jobs:
with:
name: e2e-report
path: ./e2e/test-report/
- name: Upload test coverage
- name: Upload Test Coverage
uses: actions/upload-artifact@v3
with:
name: coverage-e2e
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [next]

- ci(e2e): support relative imports [#9108](https://github.com/fabricjs/fabric.js/pull/9108)
- chore(TS): complete type check [#9119](https://github.com/fabricjs/fabric.js/pull/9119)
- chore(TS): Add type-checking to files excluded with ts-nocheck [#9097](https://github.com/fabricjs/fabric.js/pull/9097)
- chore(TS): Add type-checking to files excluded with ts-nocheck ( Parser mostly ) [#9085](https://github.com/fabricjs/fabric.js/pull/9085)
Expand Down
49 changes: 49 additions & 0 deletions e2e/.babelrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// https://github.com/viruscamp/babel-plugin-transform-imports#using-a-function-as-the-transformer

const path = require('path');
const testsDir = path.resolve('./e2e/tests');
const testsBuiltDir = path.resolve('./e2e/dist');

function resolve(file) {
const found = ['', '.ts', '/index.ts']
.map((resolution) => `${file}${resolution}`)
.find((file) => {
try {
return require.resolve(file);
} catch (error) {
return false;
}
});
if (!found) {
console.error(`Failed to resolve ${file}`);
process.exit(1);
}
return require.resolve(found).replace(/\.ts$/, '.js');
}

module.exports = {
extends: '../.babelrcAlt',
plugins: [
[
'transform-imports',
{
'\\..*': {
skipDefaultConversion: true,
transform: function (importName, matches, filename) {
const file = resolve(
path.resolve(path.dirname(filename), `${matches[0]}`)
);
return `/${path
.relative(
process.cwd(),
file.startsWith(testsDir)
? path.resolve(testsBuiltDir, path.relative(testsDir, file))
: file
)
.replaceAll('\\', '/')}`;
},
},
},
],
],
};
6 changes: 3 additions & 3 deletions e2e/imports.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { readJSONSync } from 'fs-extra';

/**
* The import map used by `./utils/setupApp` to inject into the page
* so test scripts can use modules (relative imports don't seem to work out of the box)
* The import map used by `./utils/setupApp` to inject into the page so test scripts can use modules.
*
* Relative imports are supported thanks to babel, see `./.babelrc.js`.
*
* **IMPORTANT**: be sure to update the paths field in `./tsconfig.json` to reflect imports correctly
*/
export default {
fabric: readJSONSync('./package.json').module.slice(1),
test: '/e2e/dist/test.js',
};
2 changes: 1 addition & 1 deletion e2e/setup/setupApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ test.beforeEach(async ({ page }, { file }) => {
await page.addScriptTag({
type: 'module',
content: `${readFileSync(
path.relative(process.cwd(), pathToApp)
path.relative(process.cwd(), pathToBuiltApp)
).toString()}
window.dispatchEvent(new CustomEvent('fabric:setup'));
`,
Expand Down
4 changes: 2 additions & 2 deletions e2e/tests/template/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/**
* Runs in the **BROWSER**
* Use absolute imports defined in 'e2e/imports.ts'
* Imports are defined in 'e2e/imports.ts'
*/

import * as fabric from 'fabric';
import { beforeAll } from 'test';
import { beforeAll } from '../test';

beforeAll((canvas) => {
const textbox = new fabric.Textbox('fabric.js test', {
Expand Down
27 changes: 19 additions & 8 deletions e2e/tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { Canvas } from 'fabric';
const canvasMap = (window.canvasMap = new Map<HTMLCanvasElement, Canvas>());
const objectMap = (window.objectMap = new Map<string, FabricObject>());

type AsyncReturnValue<T> = T | Promise<T>;

const setupTasks: Promise<void>[] = [];
const teardownTasks: Awaited<VoidFunction>[] = [];

Expand All @@ -26,14 +28,16 @@ export function before(
/**
* @returns a map of objects for playwright to access during tests
*/
cb: Awaited<(canvas: Canvas) => Record<string, FabricObject>>,
options?
cb: (canvas: HTMLCanvasElement) => AsyncReturnValue<{
canvas: Canvas;
objects?: Record<string, FabricObject>;
}>
) {
const task = Promise.resolve().then(async () => {
const el = document.querySelector<HTMLCanvasElement>(selector);
const canvas = new Canvas(el, options);
const { canvas, objects = {} } = await cb(el);
canvasMap.set(el, canvas);
Object.entries((await cb(canvas)) || {}).forEach(([key, value]) => {
Object.entries(objects).forEach(([key, value]) => {
if (objectMap.has(key)) {
throw new Error(
`Object identifiers must be unique: ${key} is already defined`
Expand All @@ -52,20 +56,27 @@ export function before(
* @param options canvas options
*/
export function beforeAll(
cb: Awaited<(canvas: Canvas) => Record<string, FabricObject>>,
cb: (canvas: Canvas) => AsyncReturnValue<Record<string, FabricObject>>,
options?
) {
before('#canvas', cb, options);
before('#canvas', async (el) => {
const canvas = new Canvas(el, options);
const objects = await cb(canvas);
return { canvas, objects };
});
}

export function after(selector: string, cb: Awaited<(canvas: Canvas) => void>) {
export function after(
selector: string,
cb: (canvas: Canvas) => AsyncReturnValue<void>
) {
teardownTasks.push(() => {
const el = document.querySelector<HTMLCanvasElement>(selector);
const canvas = canvasMap.get(el);
return cb(canvas);
});
}

export function afterAll(cb: Awaited<(canvas: Canvas) => void>) {
export function afterAll(cb: (canvas: Canvas) => AsyncReturnValue<void>) {
after('#canvas', cb);
}
7 changes: 1 addition & 6 deletions e2e/tests/text/text-editing/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
/**
* Runs in the **BROWSER**
* Use absolute imports defined in 'e2e/imports.ts'
*/

import { Textbox } from 'fabric';
import { beforeAll } from 'test';
import { beforeAll } from '../../test';

beforeAll((canvas) => {
const textbox = new Textbox('initial text', { width: 200, left: 50 });
Expand Down
2 changes: 1 addition & 1 deletion e2e/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
* A reflection of the configured imports used by test scripts
* **IMPORTANT**: be sure to keep this updated to reflect `./imports.ts` correctly
*/
"paths": { "fabric": ["../dist"], "test": ["./tests/test.ts"] }
"paths": { "fabric": ["../dist"] }
}
}
Loading