Skip to content

Commit

Permalink
feat: workflow of ci test (#3934)
Browse files Browse the repository at this point in the history
* feat: workflow of ci test

* fix: force exit when jest test finished
  • Loading branch information
ClarkXia committed Dec 22, 2020
1 parent 3c53878 commit a7c73b2
Show file tree
Hide file tree
Showing 15 changed files with 1,274 additions and 957 deletions.
4 changes: 2 additions & 2 deletions examples/basic-spa/build.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"ignoreHtmlTemplate": true,
"ignoreHtmlTemplate": false,
"plugins": [],
"modeConfig": {
"prod": {
"ignoreHtmlTemplate": false
"ignoreHtmlTemplate": true
}
},
"eslint": {
Expand Down
11 changes: 9 additions & 2 deletions examples/basic-spa/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { runApp, APP_MODE, IAppConfig, request } from 'ice';
import { runApp, APP_MODE, IAppConfig } from 'ice';

console.log('APP_MODE', APP_MODE);
const appConfig: IAppConfig = {
Expand All @@ -8,7 +8,14 @@ const appConfig: IAppConfig = {
errorBoundary: true,
parseSearchParams: true,
getInitialData: async() => {
const result = await request('/repo');
// const result = await request('/repo');
const result = {
status: 'SUCCESS',
data: {
group: 'ice.js',
url: 'http://github.com/ice-lab/ice.js',
}
};
return result;
},
onShow() {
Expand Down
4 changes: 3 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ module.exports = {
'coverageDirectory': './coverage/',
'testEnvironment': 'node',
'collectCoverage': true,
'collectCoverageFrom': ['packages/*/lib/*.{js,jsx}'],
'coveragePathIgnorePatterns': [
'<rootDir>/node_modules/'
],
'roots': [
'<rootDir>/packages'
'<rootDir>/packages',
'<rootDir>/test',
],
'testPathIgnorePatterns': [
'/node_modules/',
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"clean": "lerna clean --yes && rimraf packages/*/lib",
"lint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./",
"lint:fix": "npm run lint -- --fix",
"test": "jest",
"test": "jest --forceExit",
"test:watch": "jest --watch",
"coverage": "codecov"
},
Expand All @@ -40,6 +40,7 @@
"@ice/spec": "^1.0.0",
"@testing-library/react-hooks": "^3.2.1",
"@types/jest": "^25.2.1",
"@types/puppeteer": "^5.4.2",
"ali-oss": "^6.7.0",
"codecov": "^3.6.5",
"create-test-server": "^3.0.1",
Expand All @@ -48,6 +49,7 @@
"esm": "^3.2.25",
"execa": "^4.0.0",
"fs-extra": "^8.1.0",
"get-port": "^5.1.1",
"glob": "^7.1.6",
"husky": "^3.1.0",
"ice-npm-utils": "^2.0.1",
Expand All @@ -58,6 +60,7 @@
"npm-run-all": "^4.1.5",
"nsfw": "1.2.6",
"pify": "^4.0.1",
"puppeteer": "^5.5.0",
"react-test-renderer": "^16.13.1",
"rimraf": "^3.0.0",
"semver": "^7.3.2",
Expand Down
24 changes: 15 additions & 9 deletions packages/icejs/src/getBuiltInPlugins.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { IGetBuiltInPlugins, IPluginList, Json } from '@alib/build-scripts';

// eslint-disable-next-line
const chalk = require('chalk');

module.exports = (userConfig: any) => {
const getBuiltInPlugins: IGetBuiltInPlugins = (userConfig) => {
if (userConfig.disableRuntime) {
return [
'build-plugin-react-app',
'build-plugin-ice-mpa'
];
}

const plugins = [
const coreOptions = {
'framework': 'react',
'alias': process.env.__FRAMEWORK_NAME__ || 'ice'
} as Json;
const plugins: IPluginList = [
// common plugins
[
'build-plugin-app-core', {
'framework': 'react',
'alias': process.env.__FRAMEWORK_NAME__ || 'ice'
}
],
['build-plugin-app-core', coreOptions],

// react base plugin
'build-plugin-react-app',

// for ice/miniapp plugins
Expand Down Expand Up @@ -60,3 +63,6 @@ module.exports = (userConfig: any) => {

return plugins;
};

export = getBuiltInPlugins;

9 changes: 4 additions & 5 deletions packages/icejs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/* eslint @typescript-eslint/no-var-requires: 0 */
const utils = require('create-cli-utils');
const getBuiltInPlugins = require('./getBuiltInPlugins');
const pkg = require('../package.json');
import * as utils from 'create-cli-utils';
import getBuiltInPlugins = require('./getBuiltInPlugins');

const forkChildProcessPath = require.resolve('../bin/child-process-start');

module.exports = (frameworkName, { packageInfo, extendCli }) => {
// eslint-disable-next-line global-require
const pkg = require('../package.json');
process.env.__FRAMEWORK_NAME__ = frameworkName;
packageInfo.__ICEJS_INFO__ = { name: pkg.name, version: pkg.version };
utils.createCli(getBuiltInPlugins, forkChildProcessPath, packageInfo, extendCli);
};

3 changes: 2 additions & 1 deletion packages/icejs/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "../../tsconfig.settings.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib"
"outDir": "lib",
"esModuleInterop": true
}
}
2 changes: 1 addition & 1 deletion packages/plugin-react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.7.13",
"description": "The basic webpack configuration for ice project",
"author": "ice-admin@alibaba-inc.com",
"main": "src/index.js",
"main": "lib/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down
2 changes: 1 addition & 1 deletion scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { run } from './fn/shell';

(async () => {
await run('npm run clean');
await run('npx tsc --build ./tsconfig.json');

const fileParten = '*/src/**/!(*.ts|*.tsx)';
console.log(`[COPY]: ${fileParten}`);
Expand All @@ -21,6 +20,7 @@ import { run } from './fn/shell';
// eslint-disable-next-line
await fs.copyFile(from, to);
}
await run('npx tsc --build ./tsconfig.json');

})().catch((e) => {
console.trace(e);
Expand Down
4 changes: 4 additions & 0 deletions test/basic-auth.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { buildFixture } from './utils/build';

const example = 'basic-auth';
buildFixture(example);
28 changes: 28 additions & 0 deletions test/basic-spa.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { buildFixture, setupBrowser } from './utils/build';
import { IPage } from './utils/browser';

const example = 'basic-spa';
let page: IPage = null;
let browser = null;

buildFixture(example);

test('open /', async () => {
const res = await setupBrowser({ example });
page = res.page;
browser = res.page;
expect(await page.$$text('h2')).toStrictEqual(['SPA', 'Home Page...1']);
});

test('open /dashboard', async () => {
await page.push('#/dashboard');
// lazy load
expect(await page.html()).toContain('加载中...');
// wait for render
await page.waitForFunction(`document.getElementsByTagName('h2').length > 1`);
expect(await page.$$text('h2')).toStrictEqual(['SPA', 'Dashboard Page...']);
});

afterAll(async () => {
await browser.close();
});
100 changes: 100 additions & 0 deletions test/utils/browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import * as http from 'http';
import * as url from 'url';
import * as fse from 'fs-extra';
import * as path from 'path';
import * as puppeteer from 'puppeteer';

export interface IPage extends puppeteer.Page {
html?: () => Promise<string>;
$text?: (selector: string, trim?: boolean) => Promise<string|null>;
$$text?: (selector: string, trim?: boolean) => Promise<(string|null)[]>;
$attr?: (selector: string, attr: string) => Promise<string|null>;
$$attr?: (selector: string, attr: string) => Promise<(string|null)[]>;
push?: (url: string, options?: puppeteer.DirectNavigationOptions) => Promise<puppeteer.Response>;
}

export default class Browser {
private server: http.Server;
private browser: puppeteer.Browser;
private baseUrl: string;

constructor (cwd: string, port: number) {
this.server = this.createServer(cwd, port);
}

createServer(cwd: string, port: number) {
return http.createServer((req, res) => {
const requrl: string = req.url || '';
const pathname = `${cwd}${url.parse(requrl).pathname}`;
if (fse.existsSync(pathname)) {
switch (path.extname(pathname)) { // set HTTP HEAD
case '.html':
res.writeHead(200, { 'Content-Type': 'text/html' });
break;
case '.js':
res.writeHead(200, { 'Content-Type': 'text/javascript' });
break;
case '.css':
res.writeHead(200, { 'Content-Type': 'text/css' });
break;
case '.gif':
res.writeHead(200, { 'Content-Type': 'image/gif' });
break;
case '.jpg':
res.writeHead(200, { 'Content-Type': 'image/jpeg' });
break;
case '.png':
res.writeHead(200, { 'Content-Type': 'image/png' });
break;
default:
res.writeHead(200, {
'Content-Type': 'application/octet-stream',
});
}
fse.readFile(pathname, (_err, data) => {
res.end(data);
});
} else {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('<h1>404 Not Found</h1>');
console.log(`${pathname} Not Found.`);
}
}).listen(port, '127.0.0.1');
}

async start () {
this.browser = await puppeteer.launch();
}

async close () {
if (!this.browser) { return }
await this.browser.close();
this.server.close();
}

async page (url: string) {
this.baseUrl = url;
if (!this.browser) { throw new Error('Please call start() before page(url)'); }
const page: IPage = await this.browser.newPage();
await page.goto(url);
page.push = (url, options) => page.goto(`${this.baseUrl}${url}`, options);
page.html = () =>
page.evaluate(() => window.document.documentElement.outerHTML);
page.$text = (selector, trim) => page.$eval(selector, (el, trim) => {
return trim ? (el.textContent || '').replace(/^\s+|\s+$/g, '') : el.textContent
}, trim);
page.$$text = (selector, trim) =>
page.$$eval(selector, (els, trim) => els.map((el) => {
return trim ? (el.textContent || '').replace(/^\s+|\s+$/g, '') : el.textContent
}), trim);
page.$attr = (selector, attr) =>
page.$eval(selector, (el, attr: string) => el.getAttribute(attr), attr);
page.$$attr = (selector, attr) =>
page.$$eval(
selector,
(els, attr: string) => els.map(el => el.getAttribute(attr)),
attr
);
return page;
}
}
47 changes: 47 additions & 0 deletions test/utils/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as path from 'path';
import { build } from '@alib/build-scripts';
import * as getPort from 'get-port';
import Browser, { IPage } from './browser';
import getBuiltInPlugins = require('../../packages/icejs/src/getBuiltInPlugins');

interface ISetupBrowser {
(options: {
example: string;
outputDir?: string;
defaultHtml?: string;
}): Promise<IReturn>;
}

interface IReturn {
page: IPage;
browser: Browser;
}

// get builtIn plugins
export const buildFixture = function(example: string) {
test(`setup ${example}`, async () => {
const rootDir = path.join(__dirname, `../../examples/${example}`);
await build({
args: {
config: path.join(rootDir, 'build.json'),
},
rootDir,
getBuiltInPlugins: (userConfig) => {
return getBuiltInPlugins(userConfig).concat(require.resolve('./test-plugin'));
},
});
}, 120000);
}

export const setupBrowser: ISetupBrowser = async (options) => {
const { example, outputDir = 'build', defaultHtml = 'index.html' } = options;
const rootDir = path.join(__dirname, `../../examples/${example}`);
const port = await getPort();
const browser = new Browser(path.join(rootDir, outputDir), port);
await browser.start();
const page = await browser.page(`http://127.0.0.1:${port}/${defaultHtml}`);
return {
browser,
page,
}
}
4 changes: 4 additions & 0 deletions test/utils/test-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default ({ modifyUserConfig }) => {
// disable minify to speed-up fixture builds
modifyUserConfig('minify', false);
}
Loading

0 comments on commit a7c73b2

Please sign in to comment.