Skip to content

Commit bbcce79

Browse files
committed
feat: add e2e test
1 parent 7e73121 commit bbcce79

34 files changed

+3628
-72
lines changed

.changeset/rich-moons-hide.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/small-avocados-brush.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.github/workflows/ci.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,45 @@ on:
77
jobs:
88
call-rust-build:
99
uses: ./.github/workflows/plugin-build.yaml
10+
examples-test:
11+
name: Examples Test
12+
runs-on: ${{ matrix.settings.os }}
13+
needs: [call-rust-build]
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
settings:
18+
- os: ubuntu-latest
19+
abi: linux-x64-gnu
20+
- os: macos-latest
21+
abi: darwin-arm64
22+
- os: macos-13
23+
abi: darwin-x64
24+
- os: windows-latest
25+
abi: win32-x64-msvc
26+
steps:
27+
- name: Checkout Repo
28+
uses: actions/checkout@v3
29+
- name: Setup Node.js 18.x
30+
uses: actions/setup-node@v3
31+
with:
32+
node-version: 18.x
33+
- uses: actions/download-artifact@v3
34+
with:
35+
path: /tmp/artifacts
36+
- name: Move Artifacts
37+
run: |
38+
for abi in linux-x64-gnu linux-x64-musl darwin-x64 win32-x64-msvc linux-arm64-musl linux-arm64-gnu darwin-arm64 win32-ia32-msvc win32-arm64-msvc
39+
do
40+
for package in dsv react-components virtual yaml strip image url icons
41+
do
42+
folder_path="/tmp/artifacts/${{github.sha}}-${abi}-${package}"
43+
if [ -d "${folder_path}"] && [ -n "$(ls -A $folder_path)"]; then
44+
mv /tmp/artifacts/${{ github.sha }}-${abi}-${package}/* ./packages/${package}/npm/${abi}
45+
fi
46+
done
47+
done
48+
- name: Install Dependencies
49+
run: npm install -g pnpm@9.1.0 && pnpm i --frozen-lockfile
50+
- name: E2E Test Examples - ${{ matrix.settings.abi }}
51+
run: npm run test-e2e

.github/workflows/plugin-build.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,45 @@ jobs:
9898
if: ${{ !matrix.settings.docker && matrix.settings.build }}
9999
run: ${{ matrix.settings.build }}
100100
shell: bash
101+
- name: Upload Plugin react-components
102+
uses: actions/upload-artifact@v3
103+
with:
104+
name: ${{ github.sha }}-${{ matrix.settings.abi }}-react-components
105+
path: ./packages/react-components/npm/${{ matrix.settings.abi }}/index.farm
106+
if-no-files-found: ignore
107+
- name: Upload Plugin virtual
108+
uses: actions/upload-artifact@v3
109+
with:
110+
name: ${{ github.sha }}-${{ matrix.settings.abi }}-virtual
111+
path: ./packages/virtual/npm/${{ matrix.settings.abi }}/index.farm
112+
if-no-files-found: ignore
113+
- name: Upload Plugin yaml
114+
uses: actions/upload-artifact@v3
115+
with:
116+
name: ${{ github.sha }}-${{ matrix.settings.abi }}-yaml
117+
path: ./packages/yaml/npm/${{ matrix.settings.abi }}/index.farm
118+
if-no-files-found: ignore
119+
- name: Upload Plugin strip
120+
uses: actions/upload-artifact@v3
121+
with:
122+
name: ${{ github.sha }}-${{ matrix.settings.abi }}-strip
123+
path: ./packages/strip/npm/${{ matrix.settings.abi }}/index.farm
124+
if-no-files-found: ignore
125+
- name: Upload Plugin image
126+
uses: actions/upload-artifact@v3
127+
with:
128+
name: ${{ github.sha }}-${{ matrix.settings.abi }}-image
129+
path: ./packages/image/npm/${{ matrix.settings.abi }}/index.farm
130+
if-no-files-found: ignore
131+
- name: Upload Plugin url
132+
uses: actions/upload-artifact@v3
133+
with:
134+
name: ${{ github.sha }}-${{ matrix.settings.abi }}-url
135+
path: ./packages/url/npm/${{ matrix.settings.abi }}/index.farm
136+
if-no-files-found: ignore
137+
- name: Upload Plugin icons
138+
uses: actions/upload-artifact@v3
139+
with:
140+
name: ${{ github.sha }}-${{ matrix.settings.abi }}-icons
141+
path: ./packages/icons/npm/${{ matrix.settings.abi }}/index.farm
142+
if-no-files-found: ignore

e2e/utils.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
export type SimpleUnwrapArray<T> = T extends ReadonlyArray<infer P> ? P : T;
2+
3+
export function logger(msg: any, { title = 'FARM INFO', color = 'green' } = {}) {
4+
const COLOR_CODE = [
5+
'black',
6+
'red',
7+
'green',
8+
'yellow',
9+
'blue',
10+
'magenta',
11+
'cyan',
12+
'white',
13+
].indexOf(color);
14+
if (COLOR_CODE >= 0) {
15+
const TITLE_STR = title ? `\x1b[4${COLOR_CODE};30m ${title} \x1b[0m ` : '';
16+
console.log(`${TITLE_STR}\x1b[3${COLOR_CODE}m${msg}\x1b[;0m`);
17+
} else {
18+
console.log(title ? `${title} ${msg}` : msg);
19+
}
20+
}
21+
22+
export interface Deferred<T = any> {
23+
resolve: (result: T) => void;
24+
reject: (reason: any) => void;
25+
promise: Promise<T>;
26+
}
27+
28+
export const createDeferred = <T = any>(silent?: boolean) => {
29+
const deferred = {} as Deferred<T>;
30+
31+
deferred.promise = new Promise<T>((resolve, reject) => {
32+
deferred.resolve = resolve;
33+
deferred.reject = reject;
34+
});
35+
36+
if (silent) {
37+
deferred.promise.catch(() => { });
38+
}
39+
40+
return deferred;
41+
};
42+
43+
44+
export const concurrentify = <F extends (...args: any) => Promise<any>>(maxConcurrent: number, fn: F) => {
45+
const queue = [] as {
46+
deferred: Deferred;
47+
args: any;
48+
ctx: any;
49+
}[];
50+
51+
let concurrent = 0;
52+
53+
function next() {
54+
concurrent -= 1;
55+
if (queue.length > 0) {
56+
const { ctx, deferred, args } = queue.shift()!;
57+
try {
58+
// eslint-disable-next-line no-use-before-define
59+
newFn.apply(ctx, args).then(deferred.resolve, deferred.reject);
60+
} catch (e) {
61+
deferred.reject(e);
62+
}
63+
}
64+
}
65+
66+
function newFn(this: any) {
67+
// eslint-disable-next-line @typescript-eslint/no-this-alias
68+
const ctx = this;
69+
const args = arguments as any;
70+
71+
if (concurrent >= maxConcurrent) {
72+
const deferred = createDeferred();
73+
queue.push({
74+
deferred,
75+
ctx,
76+
args,
77+
});
78+
return deferred.promise;
79+
}
80+
81+
concurrent += 1;
82+
83+
return fn.apply(ctx, args).finally(next);
84+
}
85+
86+
return newFn as F;
87+
};
88+
89+
export const concurrentMap = <
90+
Arr extends readonly unknown[],
91+
F extends (item: SimpleUnwrapArray<Arr>, index: number, arr: Arr) => Promise<any>,
92+
>(arr: Arr, maxConcurrent: number, cb: F) => arr.map(
93+
concurrentify(maxConcurrent, cb) as any,
94+
) as ReturnType<F>[];

e2e/vitestGlobalSetup.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import type { GlobalSetupContext } from 'vitest/node';
2+
import { chromium } from 'playwright-chromium';
3+
import type { BrowserServer } from 'playwright-chromium';
4+
import { createServer, Server } from 'http';
5+
6+
let browserServer: BrowserServer | undefined;
7+
let client: Server | undefined;
8+
9+
const buffer = new SharedArrayBuffer(2);
10+
const u16 = new Uint16Array(buffer);
11+
12+
function addPort() {
13+
return Atomics.add(u16, 0, 10);
14+
}
15+
16+
function setPort(port: number) {
17+
return Atomics.store(u16, 0, port);
18+
}
19+
20+
setPort(9100);
21+
22+
export async function setup({ provide }: GlobalSetupContext): Promise<void> {
23+
browserServer = await chromium.launchServer({
24+
headless: true
25+
});
26+
27+
client = createServer((req, res) => {
28+
if (req.url!.startsWith('/port')) {
29+
res.end(addPort().toString());
30+
return;
31+
}
32+
// not found path
33+
res.statusCode = 404;
34+
res.end();
35+
});
36+
37+
client.listen(12306);
38+
39+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
40+
// @ts-ignore
41+
provide('wsEndpoint', browserServer.wsEndpoint());
42+
}
43+
44+
export async function teardown(): Promise<void> {
45+
await browserServer?.close();
46+
await new Promise((resolve, reject) => {
47+
client!.close((err) => {
48+
if (err) {
49+
reject(err);
50+
} else {
51+
resolve(undefined);
52+
}
53+
});
54+
});
55+
}

0 commit comments

Comments
 (0)