test: demo -> ui test (#24475)

* test: demo -> ui test

* improve comment image width

* use argos-ci

* use by cicleci

* fix circle run

* rebase master

* try pipeline var

* use another branch var

* fix commit id

* ignore image test file

* remove useless report

* fix test coverage
This commit is contained in:
骗你是小猫咪 2020-10-23 18:50:46 +08:00 committed by GitHub
parent 06b25b4d07
commit 6fba4d1136
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 353 additions and 98 deletions

3
.gitignore vendored
View File

@ -61,4 +61,7 @@ components/version/version.tsx
# Image snapshot diff # Image snapshot diff
__diff_output__/ __diff_output__/
__image_snapshots__/
/jest-stare /jest-stare
/imageSnapshots
/imageDiffSnapshots

View File

@ -11,7 +11,7 @@ module.exports = {
'\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor', '\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor',
'\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor', '\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor',
}, },
testRegex: 'image\\.test\\.js$', testRegex: 'image\\.test\\.(j|t)s$',
testEnvironment: 'node', testEnvironment: 'node',
transformIgnorePatterns, transformIgnorePatterns,
snapshotSerializers: ['enzyme-to-json/serializer'], snapshotSerializers: ['enzyme-to-json/serializer'],
@ -20,5 +20,4 @@ module.exports = {
tsConfigFile: './tsconfig.test.json', tsConfigFile: './tsconfig.test.json',
}, },
}, },
reporters: ['default', 'jest-stare'],
}; };

View File

@ -27,7 +27,7 @@ module.exports = {
'^react-dnd-test-utils$': 'react-dnd-test-utils/dist/cjs', '^react-dnd-test-utils$': 'react-dnd-test-utils/dist/cjs',
'\\.(css|less)$': 'identity-obj-proxy', '\\.(css|less)$': 'identity-obj-proxy',
}, },
testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js'], testPathIgnorePatterns: ['/node_modules/', 'dekko', 'node', 'image.test.js', 'image.test.ts'],
transform: { transform: {
'\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor', '\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
'\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor', '\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
@ -42,6 +42,7 @@ module.exports = {
'!components/*/locale/index.tsx', '!components/*/locale/index.tsx',
'!components/*/__tests__/type.test.tsx', '!components/*/__tests__/type.test.tsx',
'!components/**/*/interface.{ts,tsx}', '!components/**/*/interface.{ts,tsx}',
'!components/*/__tests__/image.test.{ts,tsx}',
], ],
transformIgnorePatterns, transformIgnorePatterns,
snapshotSerializers: ['enzyme-to-json/serializer'], snapshotSerializers: ['enzyme-to-json/serializer'],

View File

@ -74,44 +74,7 @@ stages:
versionSpec: '14.7.0' versionSpec: '14.7.0'
- script: npm install - script: npm install
displayName: 'Install modules' displayName: 'Install modules'
- script: |
node ./scripts/azure-github-comment.js -ui "[![UI Testing](https://user-images.githubusercontent.com/14831261/82744255-6bfc8800-9da8-11ea-9017-857933e8433b.gif)](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
displayName: 'Comment on github'
- script: npm run test-image - script: npm run test-image
displayName: 'UI Test' displayName: 'UI Test'
- task: PublishPipelineArtifact@1 - script: npm run argos -- --token $ARGOS_TOKEN --branch $(Build.SourceBranch) --commit $(Build.SourceVersion)
inputs: displayName: 'Upload to argos-ci'
targetPath: $(System.DefaultWorkingDirectory)/jest-stare
artifactName: jestStare
condition: failed()
- script: |
node ./scripts/azure-github-comment.js -ui "[<img width="306" src="https://user-images.githubusercontent.com/14831261/82744259-6e5ee200-9da8-11ea-8479-685f6e280b77.jpg">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
displayName: 'Update comment on github'
- job: UI_Test_Failed
dependsOn: UI_Test
condition: failed()
steps:
- checkout: self
displayName: 'Checkout'
clean: true
fetchDepth: 1
- task: NodeTool@0
displayName: 'Install Node.js'
inputs:
versionSpec: '14.7.0'
- script: npm install
displayName: 'Install modules'
- task: DownloadPipelineArtifact@2
inputs:
artifact: jestStare
path: './jest-stare'
- script: ls -al ./jest-stare
displayName: 'List report'
- script: |
export DEPLOY_DOMAIN=https://ui-test-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
echo "Deploy to $DEPLOY_DOMAIN"
npx surge --project ./jest-stare --domain $DEPLOY_DOMAIN
displayName: 'Deploy Report Site'
- script: |
node ./scripts/azure-github-comment.js -ui "[<img width="306" src="https://user-images.githubusercontent.com/14831261/82744257-6dc64b80-9da8-11ea-80cf-05b2279a5602.jpg">](https://ui-test-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh)"
displayName: 'Update comment on github'

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Affix image', () => {
imageDemoTest('affix');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Alert image', () => {
imageDemoTest('alert');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Anchor image', () => {
imageDemoTest('anchor');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('AutoComplete image', () => {
imageDemoTest('auto-complete');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Avatar image', () => {
imageDemoTest('avatar');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('BackTop image', () => {
imageDemoTest('back-top');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Badge image', () => {
imageDemoTest('badge');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Breadcrumb image', () => {
imageDemoTest('breadcrumb', { skip: ['router-4.md'] });
});

View File

@ -1,14 +0,0 @@
import React from 'react';
import Button from '..';
import imageTest from '../../../tests/shared/imageTest';
describe('Button image', () => {
imageTest(
<>
<Button type="primary">Primary</Button>
<Button>Default</Button>
<Button type="dashed">Dashed</Button>
<Button type="link">Link</Button>
</>,
);
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Button image', () => {
imageDemoTest('button', { skip: ['loading.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Calendar image', () => {
imageDemoTest('calendar');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Card image', () => {
imageDemoTest('card');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Carousel image', () => {
imageDemoTest('carousel');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Cascader image', () => {
imageDemoTest('cascader');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Checkbox image', () => {
imageDemoTest('checkbox');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Collapse image', () => {
imageDemoTest('collapse');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Comment image', () => {
imageDemoTest('comment');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('ConfigProvider image', () => {
imageDemoTest('config-provider', { skip: ['direction.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('DatePicker image', () => {
imageDemoTest('date-picker');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Descriptions image', () => {
imageDemoTest('descriptions');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Divider image', () => {
imageDemoTest('divider');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Drawer image', () => {
imageDemoTest('drawer');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Dropdown image', () => {
imageDemoTest('dropdown');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Empty image', () => {
imageDemoTest('empty');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Form image', () => {
imageDemoTest('form', { skip: ['complex-form-control.md'] });
});

View File

@ -1,37 +0,0 @@
import React from 'react';
import { Col, Row } from '..';
import imageTest from '../../../tests/shared/imageTest';
describe('Grid image', () => {
imageTest(
<>
<Row>
<Col>col</Col>
</Row>
<Row>
<Col>col</Col>
<Col>col</Col>
<Col>col</Col>
<Col>col</Col>
</Row>
<Row>
<Col span={24}>col</Col>
</Row>
<Row>
<Col span={12}>col-12</Col>
<Col span={12}>col-12</Col>
</Row>
<Row>
<Col span={8}>col-8</Col>
<Col span={8}>col-8</Col>
<Col span={8}>col-8</Col>
</Row>
<Row>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
</Row>
</>,
);
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Grid image', () => {
imageDemoTest('grid');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Icon image', () => {
imageDemoTest('icon', { skip: ['basic.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('InputNumber image', () => {
imageDemoTest('input-number');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Input image', () => {
imageDemoTest('input', { skip: ['search-input-loading.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Layout image', () => {
imageDemoTest('layout', { skip: ['countdown.md '] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('List image', () => {
imageDemoTest('list');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Mentions image', () => {
imageDemoTest('mentions');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Menu image', () => {
imageDemoTest('menu');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Message image', () => {
imageDemoTest('message');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Modal image', () => {
imageDemoTest('modal');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Notification image', () => {
imageDemoTest('notification');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('PageHeader image', () => {
imageDemoTest('page-header');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Pagination image', () => {
imageDemoTest('pagination');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Popconfirm image', () => {
imageDemoTest('popconfirm');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Popover image', () => {
imageDemoTest('popover');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Progress image', () => {
imageDemoTest('progress');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Radio image', () => {
imageDemoTest('radio');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Rate image', () => {
imageDemoTest('rate');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Result image', () => {
imageDemoTest('result');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Select image', () => {
imageDemoTest('select', { skip: ['basic.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Skeleton image', () => {
imageDemoTest('skeleton');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Slider image', () => {
imageDemoTest('slider');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Space image', () => {
imageDemoTest('space');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Statistic image', () => {
imageDemoTest('statistic', { skip: ['countdown.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Steps image', () => {
imageDemoTest('steps', { skip: ['icon.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Switch image', () => {
imageDemoTest('switch', { skip: ['loading.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Table image', () => {
imageDemoTest('table');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Tabs image', () => {
imageDemoTest('tabs');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Tag image', () => {
imageDemoTest('tag', { skip: ['status.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('TimePicker image', () => {
imageDemoTest('time-picker');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Timeline image', () => {
imageDemoTest('timeline', { skip: ['pending.md'] });
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Tooltip image', () => {
imageDemoTest('tooltip');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Transfer image', () => {
imageDemoTest('transfer');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('TreeSelect image', () => {
imageDemoTest('tree-select');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Tree image', () => {
imageDemoTest('tree');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Typography image', () => {
imageDemoTest('typography');
});

View File

@ -0,0 +1,5 @@
import { imageDemoTest } from '../../../tests/shared/imageTest';
describe('Upload image', () => {
imageDemoTest('upload');
});

View File

@ -9,4 +9,7 @@ services:
- './tests:/app/tests' - './tests:/app/tests'
- './jest-stare:/app/jest-stare' - './jest-stare:/app/jest-stare'
- './dist:/app/dist' - './dist:/app/dist'
entrypoint: "jest --config .jest.image.js --no-cache" - '.jest.image.js:/app/.jest.image.js'
- './imageSnapshots:/app/imageSnapshots'
- './imageDiffSnapshots:/app/imageDiffSnapshots'
entrypoint: "jest --config .jest.image.js --no-cache -i"

View File

@ -91,7 +91,8 @@
"tsc": "tsc --noEmit", "tsc": "tsc --noEmit",
"site:test": "jest --config .jest.site.js --cache=false", "site:test": "jest --config .jest.site.js --cache=false",
"test-image": "npm run compile:less && docker-compose run tests", "test-image": "npm run compile:less && docker-compose run tests",
"version": "node ./scripts/generate-version" "version": "node ./scripts/generate-version",
"argos": "argos upload imageSnapshots"
}, },
"husky": { "husky": {
"hooks": { "hooks": {
@ -176,6 +177,7 @@
"antd-img-crop": "^3.1.1", "antd-img-crop": "^3.1.1",
"antd-pro-merge-less": "^3.0.9", "antd-pro-merge-less": "^3.0.9",
"antd-theme-generator": "^1.2.3", "antd-theme-generator": "^1.2.3",
"argos-cli": "^0.3.0",
"array-move": "^3.0.0", "array-move": "^3.0.0",
"babel-eslint": "^10.0.1", "babel-eslint": "^10.0.1",
"babel-plugin-add-react-displayname": "^0.0.5", "babel-plugin-add-react-displayname": "^0.0.5",
@ -222,7 +224,6 @@
"intersection-observer": "^0.11.0", "intersection-observer": "^0.11.0",
"jest": "^26.0.0", "jest": "^26.0.0",
"jest-image-snapshot": "^4.0.0", "jest-image-snapshot": "^4.0.0",
"jest-stare": "^2.0.1",
"jquery": "^3.4.1", "jquery": "^3.4.1",
"jsdom": "^16.0.0", "jsdom": "^16.0.0",
"jsonml.js": "^0.1.0", "jsonml.js": "^0.1.0",

View File

@ -4,7 +4,11 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Amazing Antd</title> <title>Amazing Antd</title>
<link rel="stylesheet" href="antd.css" /> <style>
body {
border: 5px solid #1890ff;
}
</style>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@ -2,8 +2,14 @@ import React from 'react';
// Reference: https://github.com/ant-design/ant-design/pull/24003#discussion_r427267386 // Reference: https://github.com/ant-design/ant-design/pull/24003#discussion_r427267386
// eslint-disable-next-line import/no-unresolved // eslint-disable-next-line import/no-unresolved
import puppeteer, { Browser, Page } from 'puppeteer'; import puppeteer, { Browser, Page } from 'puppeteer';
import { toMatchImageSnapshot } from 'jest-image-snapshot'; import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
import ReactDOMServer from 'react-dom/server'; import ReactDOMServer from 'react-dom/server';
import glob from 'glob';
const toMatchImageSnapshot = configureToMatchImageSnapshot({
customSnapshotsDir: `${process.cwd()}/imageSnapshots`,
customDiffDir: `${process.cwd()}/imageDiffSnapshots`,
});
expect.extend({ toMatchImageSnapshot }); expect.extend({ toMatchImageSnapshot });
@ -45,3 +51,24 @@ export default function imageTest(component: React.ReactElement) {
}); });
}); });
} }
type Options = {
skip?: boolean | string[];
};
// eslint-disable-next-line jest/no-export
export function imageDemoTest(component: string, options: Options = {}) {
let testMethod = options.skip === true ? describe.skip : describe;
const files = glob.sync(`./components/${component}/demo/*.md`);
files.forEach(file => {
if (Array.isArray(options.skip) && options.skip.some(c => file.includes(c))) {
testMethod = test.skip;
}
testMethod(`Test ${file} image`, () => {
// eslint-disable-next-line global-require,import/no-dynamic-require
const demo = require(`../.${file}`).default;
imageTest(demo);
});
});
}