Zeke Zhang df0d3ddee3
perf(e2e): reduce e2e runtime (#4280)
* chore: reuse page instance

* refactor: optimize

* chore: revert

* chore: ignore workflows

* chore: upgrade playwright to 1.44.0

* chore: fix failed tests

* refactor: optimize e2eUtils

* chore: make tests pass

* chore: optimize workflow for e2e

* chore: fix fialed tests

* chore: optimize workflows

* chore: optimize

* chore: fix path

* chore: fix

* chore: test

* chore: fix

* chore: test

* chore: test

* chore: add bot for e2e

* chore: wait to revert

* chore: wait to revert

* chore: fix

* chore: fix

* chore: fix bot

* chore: test

* chore: ignore pro-plugins on PR author is not member

* chore: optimize

* chore: test

* chore: test

* chore: test bot

* chore: remove title link

* chore: fix

* chore: fix error and cache yarn

* chore: optimize md

* chore: add new workflows
2024-05-10 20:51:11 +08:00

89 lines
2.5 KiB
JavaScript

/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
const execa = require('execa');
const { resolve } = require('path');
const pAll = require('p-all');
const dotenv = require('dotenv');
const fs = require('fs');
const glob = require('glob');
const _ = require('lodash');
let ENV_FILE = resolve(process.cwd(), '.env.e2e');
if (!fs.existsSync(ENV_FILE)) {
ENV_FILE = resolve(process.cwd(), '.env.e2e.example');
}
const data = fs.readFileSync(ENV_FILE, 'utf-8');
const config = {
...dotenv.parse(data),
...process.env,
};
async function runApp(dir, index = 0) {
// 一个进程需要占用两个端口? (一个是应用端口,一个是 socket 端口)
index = index * 2;
const { Client } = require('pg');
const database = `nocobase${index}`;
const client = new Client({
host: config['DB_HOST'],
port: Number(config['DB_PORT']),
user: config['DB_USER'],
password: config['DB_PASSWORD'],
database: 'postgres',
});
await client.connect();
await client.query(`DROP DATABASE IF EXISTS "${database}"`);
await client.query(`CREATE DATABASE "${database}";`);
await client.end();
return execa('yarn', ['nocobase', 'e2e', 'test', dir], {
shell: true,
stdio: 'inherit',
env: {
...config,
CI: process.env.CI,
__E2E__: true,
APP_BASE_URL: undefined,
LOGGER_LEVEL: 'error',
APP_ENV: 'production',
APP_PORT: 20000 + index,
DB_DATABASE: `nocobase${index}`,
SOCKET_PATH: `storage/e2e/gateway-e2e-${index}.sock`,
PM2_HOME: resolve(process.cwd(), `storage/e2e/.pm2-${index}`),
PLAYWRIGHT_AUTH_FILE: resolve(process.cwd(), `storage/playwright/.auth/admin-${index}.json`),
E2E_JOB_ID: index,
},
});
}
exports.pTest = async (options) => {
const dir = resolve(process.cwd(), 'storage/e2e');
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
const files = glob.sync(options.match, {
ignore: options.ignore,
root: process.cwd(),
});
const commands = splitArrayIntoParts(_.shuffle(files), options.concurrency || 4).map((v, i) => {
return () => runApp(v.join(' '), i);
});
await pAll(commands, { concurrency: 4, stopOnError: false, ...options });
};
function splitArrayIntoParts(array, parts) {
let chunkSize = Math.ceil(array.length / parts);
return _.chunk(array, chunkSize);
}