diff --git a/.jest.site.js b/.jest.site.js new file mode 100644 index 0000000000..b58a456e03 --- /dev/null +++ b/.jest.site.js @@ -0,0 +1,22 @@ +const { moduleNameMapper, transformIgnorePatterns } = require('./.jest'); + +// jest config for server render environment +module.exports = { + moduleFileExtensions: ['ts', 'tsx', 'js', 'md'], + moduleNameMapper, + transform: { + '\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor', + '\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor', + '\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor', + '\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor', + }, + testRegex: 'check-site\\.js$', + testEnvironment: 'node', + transformIgnorePatterns, + snapshotSerializers: ['enzyme-to-json/serializer'], + globals: { + 'ts-jest': { + tsConfigFile: './tsconfig.test.json', + }, + }, +}; diff --git a/package.json b/package.json index eb04672508..7ed761a217 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "bundlesize": "bundlesize", "check-commit": "node ./scripts/check-commit.js", "compile": "antd-tools run compile", - "predeploy": "antd-tools run clean && npm run site && cp netlify.toml CNAME _site && cp .circleci/config.yml _site", + "predeploy": "antd-tools run clean && npm run site && cp netlify.toml CNAME _site && cp .circleci/config.yml _site && npm run site:test", "deploy": "bisheng gh-pages --push-only", "deploy:china-mirror": "git checkout gh-pages && git pull origin gh-pages && git push git@gitee.com:ant-design/ant-design.git gh-pages", "dist": "antd-tools run dist", @@ -73,7 +73,8 @@ "test": "jest --config .jest.js --no-cache", "test-all": "./scripts/test-all.sh", "test-node": "jest --config .jest.node.js --no-cache", - "tsc": "tsc" + "tsc": "tsc", + "site:test": "jest --config .jest.site.js --cache=false" }, "husky": { "hooks": { @@ -168,6 +169,7 @@ "bisheng-plugin-toc": "^0.4.4", "bundlesize": "^0.18.0", "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.3", "cross-env": "^6.0.0", "css-split-webpack-plugin": "^0.2.6", "dekko": "^0.2.1", @@ -189,6 +191,7 @@ "fetch-jsonp": "^1.1.3", "full-icu": "^1.3.0", "glob": "^7.1.4", + "http-server": "^0.11.1", "husky": "^3.0.2", "immutability-helper": "^3.0.0", "intersection-observer": "^0.7.0", diff --git a/scripts/check-site.js b/scripts/check-site.js new file mode 100755 index 0000000000..85f66a3cfb --- /dev/null +++ b/scripts/check-site.js @@ -0,0 +1,92 @@ +/* eslint-disable no-await-in-loop */ +/* eslint-disable no-restricted-syntax */ +const fetch = require('node-fetch'); +const { join } = require('path'); +const cheerio = require('cheerio'); +const glob = require('glob'); +const uniq = require('lodash/uniq'); +const { createServer } = require('http-server'); +const zhCN = require('../site/theme/zh-CN'); +const enUS = require('../site/theme/en-US'); + +const components = uniq( + glob + .sync('components/*/*.md', { + ignore: '**/{__tests__,_util,version,index.tsx}', + cwd: join(process.cwd()), + dot: false, + }) + .map(path => path.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '')), +); + +describe('site test', () => { + let server; + const host = 3000; + const render = async path => { + const resp = await fetch(`http://localhost:${host}${path}`).then(async res => { + const html = await res.text(); + const $ = cheerio.load(html, { decodeEntities: false, recognizeSelfClosing: true }); + return { + html, + status: res.status, + $, + }; + }); + return resp; + }; + const handleComponentName = name => { + const componentMap = { + descriptions: 'description list', + }; + // eslint-disable-next-line no-unused-vars + const [_, componentName] = name.split('/'); + const compName = componentName.toLowerCase().replace('-', ''); + return componentMap[compName] || compName; + }; + + const expectComponent = async component => { + const { status, $ } = await render(`/${component}/`); + expect(status).toBe(200); + expect( + $('.markdown > h1') + .text() + .toLowerCase(), + ).toMatch(handleComponentName(component)); + }; + + beforeAll(() => { + server = createServer({ + root: join(process.cwd(), '_site'), + }); + server.listen(host); + console.log('site static server run: http://localhost:3000'); + }); + + afterAll(() => { + if (server) { + server.close(); + } + }); + + it('Basic Pages en', async () => { + const { status, $ } = await render('/'); + expect($('title').text()).toEqual(`Ant Design - ${enUS.messages['app.home.slogan']}`); + expect(status).toBe(200); + }); + + it('Basic Pages zh', async () => { + const { status, $ } = await render('/index-cn'); + expect($('title').text()).toEqual(`Ant Design - ${zhCN.messages['app.home.slogan']}`); + expect(status).toBe(200); + }); + + for (const component of components) { + it(`Component ${component} zh Page`, async () => { + await expectComponent(component); + }); + + it(`Component ${component} en Page`, async () => { + await expectComponent(component); + }); + } +});