chore: use playwright (#9345)
* chore: use playwright * 修改图表 * e2e * up version
This commit is contained in:
parent
f6b856c309
commit
7a5c54a16a
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
- run: yarn run lint
|
||||
- run: yarn run tsc
|
||||
- run: yarn run build
|
||||
- run: yarn run test:all
|
||||
- run: yarn run test:e2e
|
||||
env:
|
||||
CI: true
|
||||
PROGRESS: none
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ RUN yarn
|
|||
|
||||
COPY ./ ./
|
||||
|
||||
RUN npm run test:all
|
||||
RUN npm run test:e2e
|
||||
|
||||
RUN npm run fetch:blocks
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ RUN yarn
|
|||
|
||||
COPY ./ ./
|
||||
|
||||
RUN npm run test:all
|
||||
RUN npm run test:e2e
|
||||
|
||||
RUN npm run fetch:blocks
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
module.exports = {
|
||||
testURL: 'http://localhost:8000',
|
||||
testEnvironment: './tests/PuppeteerEnvironment',
|
||||
verbose: false,
|
||||
extraSetupFiles: ['./tests/setupTests.js'],
|
||||
globals: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ant-design-pro",
|
||||
"version": "5.0.0",
|
||||
"version": "5.1.0",
|
||||
"private": true,
|
||||
"description": "An out-of-box UI solution for enterprise applications",
|
||||
"scripts": {
|
||||
|
|
@ -26,19 +26,19 @@
|
|||
"lint:prettier": "prettier -c --write \"src/**/*\" --end-of-line auto",
|
||||
"lint:style": "stylelint --fix \"src/**/*.less\" --syntax less",
|
||||
"openapi": "umi openapi",
|
||||
"playwright": "playwright install && playwright test",
|
||||
"precommit": "lint-staged",
|
||||
"prettier": "prettier -c --write \"src/**/*\"",
|
||||
"serve": "umi-serve",
|
||||
"start": "cross-env UMI_ENV=dev umi dev",
|
||||
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev umi dev",
|
||||
"start:no-mock": "cross-env MOCK=none UMI_ENV=dev umi dev",
|
||||
"start:no-ui": "cross-env UMI_UI=none UMI_ENV=dev umi dev",
|
||||
"start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev umi dev",
|
||||
"start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev umi dev",
|
||||
"pretest": "node ./tests/beforeTest",
|
||||
"test": "umi test",
|
||||
"test:all": "node ./tests/run-tests.js",
|
||||
"test:e2e": "node ./tests/run-tests.js",
|
||||
"test:component": "umi test ./src/components",
|
||||
"serve": "umi-serve",
|
||||
"tsc": "tsc --noEmit"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
|
@ -76,6 +76,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/pro-cli": "^2.0.2",
|
||||
"@playwright/test": "^1.16.3",
|
||||
"@types/express": "^4.17.0",
|
||||
"@types/history": "^4.7.2",
|
||||
"@types/jest": "^26.0.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// playwright.config.ts
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
import { devices } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
use: {
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
],
|
||||
};
|
||||
export default config;
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
const { uniq } = require('lodash');
|
||||
const RouterConfig = require('../../config/config').default.routes;
|
||||
|
||||
const BASE_URL = `http://localhost:${process.env.PORT || 8001}`;
|
||||
|
||||
function formatter(routes, parentPath = '') {
|
||||
const fixedParentPath = parentPath.replace(/\/{1,}/g, '/');
|
||||
let result = [];
|
||||
routes.forEach((item) => {
|
||||
if (item.path && !item.path.startsWith('/')) {
|
||||
result.push(`${fixedParentPath}/${item.path}`.replace(/\/{1,}/g, '/'));
|
||||
}
|
||||
if (item.path && item.path.startsWith('/')) {
|
||||
result.push(`${item.path}`.replace(/\/{1,}/g, '/'));
|
||||
}
|
||||
if (item.routes) {
|
||||
result = result.concat(
|
||||
formatter(item.routes, item.path ? `${fixedParentPath}/${item.path}` : parentPath),
|
||||
);
|
||||
}
|
||||
});
|
||||
return uniq(result.filter((item) => !!item));
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
await page.goto(`${BASE_URL}`);
|
||||
await page.evaluate(() => {
|
||||
localStorage.setItem('antd-pro-authority', '["admin"]');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Ant Design Pro E2E test', () => {
|
||||
const testPage = (path) => async () => {
|
||||
await page.goto(`${BASE_URL}${path}`);
|
||||
await page.waitForSelector('footer', {
|
||||
timeout: 2000,
|
||||
});
|
||||
const haveFooter = await page.evaluate(
|
||||
() => document.getElementsByTagName('footer').length > 0,
|
||||
);
|
||||
expect(haveFooter).toBeTruthy();
|
||||
};
|
||||
|
||||
const routers = formatter(RouterConfig);
|
||||
routers.forEach((route) => {
|
||||
it(`test pages ${route}`, testPage(route));
|
||||
});
|
||||
|
||||
it('topmenu should have footer', async () => {
|
||||
const params = '?navTheme=light&layout=topmenu';
|
||||
await page.goto(`${BASE_URL}${params}`);
|
||||
await page.waitForSelector('footer', {
|
||||
timeout: 2000,
|
||||
});
|
||||
|
||||
const haveFooter = await page.evaluate(
|
||||
() => document.getElementsByTagName('footer').length > 0,
|
||||
);
|
||||
expect(haveFooter).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import type { Page } from '@playwright/test';
|
||||
import { test, expect } from '@playwright/test';
|
||||
const { uniq } = require('lodash');
|
||||
const RouterConfig = require('../../config/routes').default;
|
||||
|
||||
const BASE_URL = `http://localhost:${process.env.PORT || 8001}`;
|
||||
|
||||
function formatter(routes: any, parentPath = ''): string[] {
|
||||
const fixedParentPath = parentPath.replace(/\/{1,}/g, '/');
|
||||
let result: string[] = [];
|
||||
routes.forEach((item: { path: string; routes: string }) => {
|
||||
if (item.path && !item.path.startsWith('/')) {
|
||||
result.push(`${fixedParentPath}/${item.path}`.replace(/\/{1,}/g, '/'));
|
||||
}
|
||||
if (item.path && item.path.startsWith('/')) {
|
||||
result.push(`${item.path}`.replace(/\/{1,}/g, '/'));
|
||||
}
|
||||
if (item.routes) {
|
||||
result = result.concat(
|
||||
formatter(item.routes, item.path ? `${fixedParentPath}/${item.path}` : parentPath),
|
||||
);
|
||||
}
|
||||
});
|
||||
return uniq(result.filter((item) => !!item));
|
||||
}
|
||||
|
||||
const testPage = (path: string, page: Page) => async () => {
|
||||
await page.evaluate(() => {
|
||||
localStorage.setItem('antd-pro-authority', '["admin"]');
|
||||
});
|
||||
await page.goto(`${BASE_URL}${path}`);
|
||||
await page.waitForSelector('footer', {
|
||||
timeout: 2000,
|
||||
});
|
||||
const haveFooter = await page.evaluate(() => document.getElementsByTagName('footer').length > 0);
|
||||
expect(haveFooter).toBeTruthy();
|
||||
};
|
||||
|
||||
const routers = formatter(RouterConfig);
|
||||
|
||||
routers.forEach((route) => {
|
||||
test(`test route page ${route}`, async ({ page }) => {
|
||||
await testPage(route, page);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// eslint-disable-next-line
|
||||
const NodeEnvironment = require('jest-environment-node');
|
||||
const getBrowser = require('./getBrowser');
|
||||
|
||||
class PuppeteerEnvironment extends NodeEnvironment {
|
||||
// Jest is not available here, so we have to reverse engineer
|
||||
// the setTimeout function, see https://github.com/facebook/jest/blob/v23.1.0/packages/jest-runtime/src/index.js#L823
|
||||
setTimeout(timeout) {
|
||||
if (this.global.jasmine) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
this.global.jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout;
|
||||
} else {
|
||||
this.global[Symbol.for('TEST_TIMEOUT_SYMBOL')] = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
async setup() {
|
||||
const browser = await getBrowser();
|
||||
const page = await browser.newPage();
|
||||
this.global.browser = browser;
|
||||
this.global.page = page;
|
||||
}
|
||||
|
||||
async teardown() {
|
||||
const { page, browser } = this.global;
|
||||
|
||||
if (page) {
|
||||
await page.close();
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
await browser.disconnect();
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PuppeteerEnvironment;
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/* eslint-disable global-require */
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
const { execSync } = require('child_process');
|
||||
const { join } = require('path');
|
||||
const findChrome = require('carlo/lib/find_chrome');
|
||||
const detectInstaller = require('detect-installer');
|
||||
|
||||
const installPuppeteer = () => {
|
||||
// find can use package manager
|
||||
const packages = detectInstaller(join(__dirname, '../'));
|
||||
// get installed package manager
|
||||
const packageName = packages.find(detectInstaller.hasPackageCommand) || 'npm';
|
||||
console.log(`🤖 will use ${packageName} install puppeteer`);
|
||||
const command = `${packageName} ${packageName.includes('yarn') ? 'add' : 'i'} puppeteer`;
|
||||
execSync(command, {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
};
|
||||
|
||||
const initPuppeteer = async () => {
|
||||
try {
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const findChromePath = await findChrome({});
|
||||
const { executablePath } = findChromePath;
|
||||
console.log(`🧲 find you browser in ${executablePath}`);
|
||||
return;
|
||||
} catch (error) {
|
||||
console.log('🧲 no find chrome');
|
||||
}
|
||||
|
||||
try {
|
||||
require.resolve('puppeteer');
|
||||
} catch (error) {
|
||||
// need install puppeteer
|
||||
await installPuppeteer();
|
||||
}
|
||||
};
|
||||
|
||||
initPuppeteer();
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/* eslint-disable global-require */
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
const findChrome = require('carlo/lib/find_chrome');
|
||||
|
||||
const getBrowser = async () => {
|
||||
try {
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const puppeteer = require('puppeteer');
|
||||
const browser = await puppeteer.launch({
|
||||
args: [
|
||||
'--disable-gpu',
|
||||
'--disable-dev-shm-usage',
|
||||
'--no-first-run',
|
||||
'--no-zygote',
|
||||
'--no-sandbox',
|
||||
],
|
||||
});
|
||||
return browser;
|
||||
} catch (error) {
|
||||
// console.log(error)
|
||||
}
|
||||
|
||||
try {
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const puppeteer = require('puppeteer-core');
|
||||
const findChromePath = await findChrome({});
|
||||
const { executablePath } = findChromePath;
|
||||
const browser = await puppeteer.launch({
|
||||
executablePath,
|
||||
args: [
|
||||
'--disable-gpu',
|
||||
'--disable-dev-shm-usage',
|
||||
'--no-first-run',
|
||||
'--no-zygote',
|
||||
'--no-sandbox',
|
||||
],
|
||||
});
|
||||
return browser;
|
||||
} catch (error) {
|
||||
console.log('🧲 no find chrome');
|
||||
}
|
||||
throw new Error('no find puppeteer');
|
||||
};
|
||||
|
||||
module.exports = getBrowser;
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/* eslint-disable eslint-comments/no-unlimited-disable */
|
||||
const { spawn } = require('child_process');
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const { kill } = require('cross-port-killer');
|
||||
|
||||
const env = Object.create(process.env);
|
||||
|
|
@ -36,7 +33,7 @@ startServer.stdout.on('data', (data) => {
|
|||
console.log('Development server is started, ready to run tests.');
|
||||
const testCmd = spawn(
|
||||
/^win/.test(process.platform) ? 'npm.cmd' : 'npm',
|
||||
['test', '--', '--maxWorkers=1', '--runInBand'],
|
||||
['run', 'playwright'],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
"include": [
|
||||
"mock/**/*",
|
||||
"src/**/*",
|
||||
"playwright.config.ts",
|
||||
"tests/**/*",
|
||||
"test/**/*",
|
||||
"__test__/**/*",
|
||||
|
|
|
|||
Loading…
Reference in New Issue