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 = { |
|||
...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