46 changed files with 223 additions and 288 deletions
@ -0,0 +1 @@ |
|||||
|
_ |
||||
@ -0,0 +1,7 @@ |
|||||
|
#!/bin/sh |
||||
|
. "$(dirname "$0")/_/husky.sh" |
||||
|
|
||||
|
# Export Git hook params |
||||
|
export GIT_PARAMS=$* |
||||
|
|
||||
|
npx --no-install fabric verify-commit |
||||
@ -0,0 +1,4 @@ |
|||||
|
#!/bin/sh |
||||
|
. "$(dirname "$0")/_/husky.sh" |
||||
|
|
||||
|
npx --no-install lint-staged |
||||
@ -1,5 +1,3 @@ |
|||||
const fabric = require('@umijs/fabric'); |
|
||||
|
|
||||
module.exports = { |
module.exports = { |
||||
...fabric.stylelint, |
extends: [require.resolve('@umijs/fabric/dist/stylelint')], |
||||
}; |
}; |
||||
|
|||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"recommendations": [ |
||||
|
"esbenp.prettier-vscode", |
||||
|
"dbaeumer.vscode-eslint", |
||||
|
"stylelint.vscode-stylelint", |
||||
|
"wangzy.sneak-mark" |
||||
|
] |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
{ |
||||
|
"editor.formatOnSave": true, |
||||
|
"prettier.requireConfig": true, |
||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode" |
||||
|
} |
||||
@ -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; |
|
||||
Loading…
Reference in new issue