Skip to content

Commit

Permalink
Merge pull request #272 from Tencent/test/unit
Browse files Browse the repository at this point in the history
test: update vitest config
  • Loading branch information
honkinglin authored Aug 17, 2022
2 parents 3ea19ca + bdfed43 commit 2efc5e6
Show file tree
Hide file tree
Showing 125 changed files with 69,284 additions and 4,223 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"test:snap-update": "cross-env NODE_ENV=test-snap vitest run --config site/vite.config.js -u",
"test:e2e": "cypress run --config-file scripts/test/cypress.json",
"test:e2e-gui": "cypress open --config-file scripts/test/cypress.json",
"test:demo": "node src/_common/test/script/generate-demo-test.js",
"test:demo": "node scripts/test/generate-demo-test.js",
"lint": "eslint --ext .vue,.ts,.tsx ./ --max-warnings 0 --ignore-path .gitignore --ignore-path .eslintignore",
"lint:fix": "npm run lint:fix-prettier && npm run lint:fix-eslint",
"lint:fix-eslint": "eslint --ext .vue,.ts,.tsx ./ --max-warnings 0 --ignore-path .gitignore --ignore-path .eslintignore --fix",
Expand Down
55 changes: 52 additions & 3 deletions scripts/test/generate-coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,57 @@ const DomParser = require('dom-parser');
const parser = new DomParser();
const result = {};

// 只关注组件本身的测试覆盖率
const components_enum = [
'button',
'fab',
'icon',
'cell',
'divider',
'grid',
'DropdownMenu',
'indexes',
'navbar',
'steps',
'stikcy',
'tabBar',
'checkbox',
'DateTimePicker',
'input',
'picker',
'radio',
'rate',
'search',
'slider',
'stepper',
'switch',
'textarea',
'upload',
'avater',
'badge',
'collapse',
'countDown',
'image',
'imageViewer',
'list',
'reault',
'skeleton',
'swiper',
'tag',
'actionSheet',
'backTop',
'dialog',
'drawer',
'loading',
'message',
'noticeBar',
'overlay',
'popup',
'progress',
'PullDownRefresh',
'swipeCell',
]

function resolveCwd(...args) {
args.unshift(process.cwd());
return path.join(...args);
Expand All @@ -26,17 +77,15 @@ fs.readFile(resolveCwd('test/unit/coverage/index.html'), 'utf8', (err, html) =>

Array.from(tds).forEach((item, index) => {
const col = index % 10;

if (col === 0) {
const [, name] = item.getAttribute('data-value').split('src/');
name && (key = camelCase(name));
components_enum.includes(name) && (key = camelCase(name));
} else if (col === 8) {
value = `${item.getAttribute('data-value')}%`;
} else if (col === 9) {
result[key] = value;
}
});

const finalRes = `module.exports = ${JSON.stringify(result, null, 2)}`;
fs.writeFileSync(resolveCwd('site/web/test-coverage.js'), finalRes);
console.log('successful re-generate coverage');
Expand Down
123 changes: 123 additions & 0 deletions scripts/test/generate-demo-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
const fs = require('fs');
const path = require('path');
const camelCase = require('lodash/camelCase');
const upperFirst = require('lodash/upperFirst');

function resolveCwd(...args) {
args.unshift(process.cwd());
return path.join(...args);
}

const pkg = require(resolveCwd('package.json'));

const framework = pkg.name;

const fixedDateComponentList = ['config-provider', 'time-picker', 'date-picker', 'table', 'form', 'calendar']; // 需要在测试阶段固定日期的组件,table中因为有filter例子 渲染datepicker需要固定

// TODO 过滤掉一些导致挂掉的demo
const filterCom = ['table'];
const filterDemo = {
table: ['virtual-scroll'],
};

const CONFIG = {
'tdesign-mobile-react': {
sourcePath: path.resolve(__dirname, resolveCwd('src')),
targetPath: path.resolve(__dirname, resolveCwd('src')),
defaultTemplate: 'import { mount } from \'@vue/test-utils\';',
},
'tdesign-mobile-vue': {
sourcePath: path.resolve(__dirname, resolveCwd('src')),
targetPath: path.resolve(__dirname, resolveCwd(`src`)),
defaultTemplate: 'import { mount } from \'@vue/test-utils\';',
},
};

const { sourcePath, targetPath, defaultTemplate } = CONFIG[framework];

const data = `/**
* 该文件为由脚本 \`npm run test:demo\` 自动生成,如需修改,执行脚本命令即可。请勿手写直接修改,否则会被覆盖
*/
${defaultTemplate}
{{ HERE IS DEMO LIST }}
`;

function filterFileFunction(files) {
// 过滤非 vue jsx 文件
const fileType = ['vue', 'jsx']
return files.filter(item => {
return fileType.includes(item.substr(item.lastIndexOf('.') + 1, item.length))
})
}

function getKeyFunction(component) {
const newComponent = upperFirst(camelCase(component));

return `
describe('${newComponent}', () => {
Object.keys(mapper).forEach((demoName) => {
it(\`${newComponent} \${demoName} demo works fine\`, () => {
const wrapper = mount(mapper[demoName]);
expect(wrapper.element).toMatchSnapshot();
});
});
});`;
}

function outputOneComponentTestFile(component, demoFiles) {
const outputPath = `${targetPath}/${component}/__test__`;
const imports = [];
const demos = ['\nconst mapper = {'];

demoFiles.forEach((demo) => {
if (filterCom.includes(component) && filterDemo[component].includes(demo.replace('.vue', ''))) return;

const name = camelCase(demo);
imports.push(`import ${name} from '@/${component}/demos/${demo}';`);
demos.push(` ${name},`);
});
if (fixedDateComponentList.includes(component)) {
imports.unshift('import MockDate from \'mockdate\';\n');
imports.push('\nMockDate.set(\'2020-12-28\');');
}

demos.push('};');
const keyData = [imports.join('\n'), demos.join('\n'), getKeyFunction(component)].join('\n');
const testFileData = data.replace('{{ HERE IS DEMO LIST }}', keyData);
fs.mkdir(outputPath, { recursive: true }, (err) => {
if (err) {
console.error(err);
return;
}
fs.writeFile(`${outputPath}/demo.test.jsx`, testFileData, (writeErr) => {
if (writeErr) {
return console.error(writeErr);
}
return console.log(`test file: ${outputPath} has been created.`);
});
});
}

function main() {
fs.readdir(sourcePath, (err, files) => {
if (err) {
console.log('Error', err);
} else {
files.forEach((componentFolder) => {
const demoPath = `${sourcePath}/${componentFolder}/demos`;
fs.readdir(demoPath, (err1, demoFiles) => {
if (err1) {
console.log('Error', err1);
} else {
if (['icon', 'local-provider'].includes(componentFolder)) return;
const finalDemoFiles = filterFileFunction(demoFiles);
outputOneComponentTestFile(componentFolder, finalDemoFiles);
}
});
});
}
});
}

main();
24 changes: 16 additions & 8 deletions site/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,30 @@ const publicPathMap = {

// 单元测试相关配置
const testConfig = {
// include:
// process.env.NODE_ENV === 'test-snap'
// ? ['test/snap/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']
// : ['test/unit/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
include: ['{test,src}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
exclude: ['**/ssr/**'],
include:
/**
* 快照涵盖 `__test__/*.test.jsx`
* 生成demo测试文件: npm run test:demo
* 生成快照:npm run test:snap || npm run test:snap-update
*
* 测试用例检测 && GUI && 覆盖率报告,仅涵盖 `__test__/index.test.jsx`
* 单测: npm run test:unit
* 覆盖率报告: npm run test:unit-coverage
* GUI:npm run test:unit-gui
*/
process.env.NODE_ENV === 'test-snap'
? ['src/**/__test__/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']
: ['src/**/__test__/index.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
globals: true,
environment: 'jsdom',
testTimeout: 5000,
setupFiles: path.resolve(__dirname, '../scripts/test/test-setup.js'),
// setupFiles: process.env.NODE_ENV === 'test-snap' ? path.resolve(__dirname, '../scripts/test/test-setup.js') : '',
setupFiles: process.env.NODE_ENV === 'test-snap' ? path.resolve(__dirname, '../scripts/test/test-setup.js') : '',
transformMode: {
web: [/\.[jt]sx$/],
},
coverage: {
reporter: ['text', 'json', 'html'],
reportsDirectory: 'test/unit/coverage',
},
};

Expand Down
Loading

0 comments on commit 2efc5e6

Please sign in to comment.