mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-01-12 22:46:30 +08:00
Cleanup Jest config (#6654)
General cleanup after the [Jest 24 PR](#6278).
This also includes `jsdom@14` via https://www.npmjs.com/package/jest-environment-jsdom-fourteen. Since we have a node >= 8.10 requirement, we are able to use the latest version of `jsdom` which includes additional implementations of browser APIs such as `MutationObserver` (which we had an issue filed for over at #6617).
/cc @SimenB. Is there more you recommend we do to cleanup our [Jest config](b0cbf2caa1/packages/react-scripts/scripts/utils/createJestConfig.js) for TypeScript?
Co-authored-by: Ian Sutherland <ian@iansutherland.ca>
This commit is contained in:
committed by
Ian Sutherland
parent
e630238d0d
commit
76fea02277
@@ -25,7 +25,7 @@
|
||||
"get-port": "^4.2.0",
|
||||
"globby": "^9.1.0",
|
||||
"husky": "^1.3.1",
|
||||
"jest": "^24.5.0",
|
||||
"jest": "24.7.1",
|
||||
"lerna": "2.9.1",
|
||||
"lerna-changelog": "~0.8.2",
|
||||
"lint-staged": "^8.0.4",
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
"@babel/core": "^7.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-tester": "^5.5.1",
|
||||
"jest": "^24.5.0"
|
||||
"babel-plugin-tester": "^6.0.1",
|
||||
"jest": "24.7.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
"index.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"jest": "24.5.0"
|
||||
"jest": "24.7.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^5.2.0",
|
||||
"jest": "^24.5.0"
|
||||
"jest": "24.7.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "cross-env FORCE_COLOR=true jest"
|
||||
|
||||
@@ -33,9 +33,8 @@
|
||||
"@babel/code-frame": "7.0.0",
|
||||
"@babel/core": "7.3.4",
|
||||
"anser": "1.4.8",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "10.0.1",
|
||||
"babel-jest": "24.5.0",
|
||||
"babel-jest": "24.7.1",
|
||||
"babel-loader": "8.0.5",
|
||||
"babel-preset-react-app": "^7.0.2",
|
||||
"chalk": "^2.4.2",
|
||||
@@ -49,7 +48,7 @@
|
||||
"eslint-plugin-react": "7.12.4",
|
||||
"flow-bin": "^0.63.1",
|
||||
"html-entities": "1.2.1",
|
||||
"jest": "24.5.0",
|
||||
"jest": "24.7.1",
|
||||
"jest-fetch-mock": "2.1.1",
|
||||
"object-assign": "4.1.1",
|
||||
"promise": "8.0.2",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"bootstrap": "4.1.1",
|
||||
"jest": "24.5.0",
|
||||
"jest": "24.7.1",
|
||||
"node-sass": "4.8.3",
|
||||
"normalize.css": "7.0.0",
|
||||
"prop-types": "15.5.6",
|
||||
|
||||
@@ -8,7 +8,7 @@ Tests are automatically run by the CI tools.
|
||||
In order to run them locally, without having to manually install and configure everything, the `yarn e2e:docker` CLI command can be used.
|
||||
|
||||
This is a simple script that runs a **Docker** container, where the node version, git branch to clone, test suite, and whether to run it with `yarn` or `npm` can be chosen.
|
||||
Simply run `yarn e2e:docker -- --help` to get additional info.
|
||||
Simply run `yarn e2e:docker --help` to get additional info.
|
||||
|
||||
If you need guidance installing **Docker**, you should follow their [official docs](https://docs.docker.com/engine/installation/).
|
||||
|
||||
|
||||
@@ -9,8 +9,15 @@ import initDOM from './initDOM';
|
||||
|
||||
describe('Integration', () => {
|
||||
describe('Environment variables', () => {
|
||||
let doc;
|
||||
|
||||
afterEach(() => {
|
||||
doc && doc.defaultView.close();
|
||||
doc = undefined;
|
||||
});
|
||||
|
||||
it('file env variables', async () => {
|
||||
const doc = await initDOM('file-env-variables');
|
||||
doc = await initDOM('file-env-variables');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-file-env-original-1').textContent
|
||||
@@ -34,18 +41,16 @@ describe('Integration', () => {
|
||||
'x-from-development-env'
|
||||
);
|
||||
}
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('NODE_PATH', async () => {
|
||||
const doc = await initDOM('node-path');
|
||||
doc = await initDOM('node-path');
|
||||
|
||||
expect(doc.getElementById('feature-node-path').childElementCount).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('PUBLIC_URL', async () => {
|
||||
const doc = await initDOM('public-url');
|
||||
doc = await initDOM('public-url');
|
||||
|
||||
const prefix =
|
||||
process.env.NODE_ENV === 'development'
|
||||
@@ -57,20 +62,18 @@ describe('Integration', () => {
|
||||
expect(
|
||||
doc.querySelector('head link[rel="shortcut icon"]').getAttribute('href')
|
||||
).toBe(`${prefix}/favicon.ico`);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('shell env variables', async () => {
|
||||
const doc = await initDOM('shell-env-variables');
|
||||
doc = await initDOM('shell-env-variables');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-shell-env-variables').textContent
|
||||
).toBe('fromtheshell.');
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('expand .env variables', async () => {
|
||||
const doc = await initDOM('expand-env-variables');
|
||||
doc = await initDOM('expand-env-variables');
|
||||
|
||||
expect(doc.getElementById('feature-expand-env-1').textContent).toBe(
|
||||
'basic'
|
||||
@@ -84,7 +87,6 @@ describe('Integration', () => {
|
||||
expect(
|
||||
doc.getElementById('feature-expand-env-existing').textContent
|
||||
).toBe('fromtheshell');
|
||||
doc.defaultView.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,46 +6,31 @@
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const jsdom = require('jsdom/lib/old-api.js');
|
||||
const { JSDOM, ResourceLoader } = require('jsdom');
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
|
||||
let getMarkup;
|
||||
export let resourceLoader;
|
||||
|
||||
if (process.env.E2E_FILE) {
|
||||
const file = path.isAbsolute(process.env.E2E_FILE)
|
||||
const file =
|
||||
process.env.E2E_FILE &&
|
||||
(path.isAbsolute(process.env.E2E_FILE)
|
||||
? process.env.E2E_FILE
|
||||
: path.join(process.cwd(), process.env.E2E_FILE);
|
||||
|
||||
const markup = fs.readFileSync(file, 'utf8');
|
||||
getMarkup = () => markup;
|
||||
: path.join(process.cwd(), process.env.E2E_FILE));
|
||||
|
||||
export const fetchFile = url => {
|
||||
const pathPrefix = process.env.PUBLIC_URL.replace(/^https?:\/\/[^/]+\/?/, '');
|
||||
return fs.readFileSync(
|
||||
path.join(path.dirname(file), url.pathname.replace(pathPrefix, '')),
|
||||
'utf8'
|
||||
);
|
||||
};
|
||||
|
||||
resourceLoader = (resource, callback) =>
|
||||
callback(
|
||||
null,
|
||||
fs.readFileSync(
|
||||
path.join(
|
||||
path.dirname(file),
|
||||
resource.url.pathname.replace(pathPrefix, '')
|
||||
),
|
||||
'utf8'
|
||||
)
|
||||
);
|
||||
} else if (process.env.E2E_URL) {
|
||||
getMarkup = () =>
|
||||
new Promise(resolve => {
|
||||
http.get(process.env.E2E_URL, res => {
|
||||
let rawData = '';
|
||||
res.on('data', chunk => (rawData += chunk));
|
||||
res.on('end', () => resolve(rawData));
|
||||
});
|
||||
});
|
||||
const fileResourceLoader = new class FileResourceLoader extends ResourceLoader {
|
||||
fetch(href, options) {
|
||||
return Promise.resolve(fetchFile(url.parse(href)));
|
||||
}
|
||||
}();
|
||||
|
||||
resourceLoader = (resource, callback) => resource.defaultFetch(callback);
|
||||
} else {
|
||||
if (!process.env.E2E_FILE && !process.env.E2E_URL) {
|
||||
it.only('can run jsdom (at least one of "E2E_FILE" or "E2E_URL" environment variables must be provided)', () => {
|
||||
expect(
|
||||
new Error("This isn't the error you are looking for.")
|
||||
@@ -54,18 +39,46 @@ if (process.env.E2E_FILE) {
|
||||
}
|
||||
|
||||
export default feature =>
|
||||
new Promise(async resolve => {
|
||||
const markup = await getMarkup();
|
||||
const host = process.env.E2E_URL || 'http://www.example.org/spa:3000';
|
||||
const doc = jsdom.jsdom(markup, {
|
||||
created: (_, win) =>
|
||||
win.addEventListener('ReactFeatureDidMount', () => resolve(doc), true),
|
||||
deferClose: true,
|
||||
pretendToBeVisual: true,
|
||||
resourceLoader,
|
||||
url: `${host}#${feature}`,
|
||||
virtualConsole: jsdom.createVirtualConsole().sendTo(console),
|
||||
});
|
||||
new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const host = process.env.E2E_URL || 'http://www.example.org/spa:3000';
|
||||
const url = `${host}#${feature}`;
|
||||
|
||||
doc.close();
|
||||
let window;
|
||||
|
||||
if (process.env.E2E_FILE) {
|
||||
window = (await JSDOM.fromFile(file, {
|
||||
pretendToBeVisual: true,
|
||||
resources: fileResourceLoader,
|
||||
runScripts: 'dangerously',
|
||||
url,
|
||||
})).window;
|
||||
} else {
|
||||
window = (await JSDOM.fromURL(url, {
|
||||
pretendToBeVisual: true,
|
||||
resources: 'usable',
|
||||
runScripts: 'dangerously',
|
||||
})).window;
|
||||
}
|
||||
|
||||
const { document } = window;
|
||||
|
||||
document.addEventListener(
|
||||
'ReactFeatureDidMount',
|
||||
() => resolve(document),
|
||||
{ capture: true, once: true }
|
||||
);
|
||||
document.addEventListener(
|
||||
'ReactFeatureError',
|
||||
() => {
|
||||
// Cleanup jsdom instance since we don't need it anymore
|
||||
window.close();
|
||||
|
||||
reject(`Error loading feature: ${feature}`);
|
||||
},
|
||||
{ capture: true, once: true }
|
||||
);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,137 +9,129 @@ import initDOM from './initDOM';
|
||||
|
||||
describe('Integration', () => {
|
||||
describe('Language syntax', () => {
|
||||
let doc;
|
||||
|
||||
afterEach(() => {
|
||||
doc && doc.defaultView.close();
|
||||
doc = undefined;
|
||||
});
|
||||
|
||||
it('array destructuring', async () => {
|
||||
const doc = await initDOM('array-destructuring');
|
||||
doc = await initDOM('array-destructuring');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-array-destructuring').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('array spread', async () => {
|
||||
const doc = await initDOM('array-spread');
|
||||
doc = await initDOM('array-spread');
|
||||
|
||||
expect(doc.getElementById('feature-array-spread').childElementCount).toBe(
|
||||
4
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('async/await', async () => {
|
||||
const doc = await initDOM('async-await');
|
||||
doc = await initDOM('async-await');
|
||||
|
||||
expect(doc.getElementById('feature-async-await').childElementCount).toBe(
|
||||
4
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('class properties', async () => {
|
||||
const doc = await initDOM('class-properties');
|
||||
doc = await initDOM('class-properties');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-class-properties').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('computed properties', async () => {
|
||||
const doc = await initDOM('computed-properties');
|
||||
doc = await initDOM('computed-properties');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-computed-properties').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('custom interpolation', async () => {
|
||||
const doc = await initDOM('custom-interpolation');
|
||||
doc = await initDOM('custom-interpolation');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-custom-interpolation').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('default parameters', async () => {
|
||||
const doc = await initDOM('default-parameters');
|
||||
doc = await initDOM('default-parameters');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-default-parameters').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('destructuring and await', async () => {
|
||||
const doc = await initDOM('destructuring-and-await');
|
||||
doc = await initDOM('destructuring-and-await');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-destructuring-and-await').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('generators', async () => {
|
||||
const doc = await initDOM('generators');
|
||||
doc = await initDOM('generators');
|
||||
|
||||
expect(doc.getElementById('feature-generators').childElementCount).toBe(
|
||||
4
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('object destructuring', async () => {
|
||||
const doc = await initDOM('object-destructuring');
|
||||
doc = await initDOM('object-destructuring');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-object-destructuring').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('object spread', async () => {
|
||||
const doc = await initDOM('object-spread');
|
||||
doc = await initDOM('object-spread');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-object-spread').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('promises', async () => {
|
||||
const doc = await initDOM('promises');
|
||||
doc = await initDOM('promises');
|
||||
|
||||
expect(doc.getElementById('feature-promises').childElementCount).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('rest + default', async () => {
|
||||
const doc = await initDOM('rest-and-default');
|
||||
doc = await initDOM('rest-and-default');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-rest-and-default').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('rest parameters', async () => {
|
||||
const doc = await initDOM('rest-parameters');
|
||||
doc = await initDOM('rest-parameters');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-rest-parameters').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('template interpolation', async () => {
|
||||
const doc = await initDOM('template-interpolation');
|
||||
doc = await initDOM('template-interpolation');
|
||||
|
||||
expect(
|
||||
doc.getElementById('feature-template-interpolation').childElementCount
|
||||
).toBe(4);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import initDOM, { resourceLoader } from './initDOM';
|
||||
import initDOM, { fetchFile } from './initDOM';
|
||||
import url from 'url';
|
||||
|
||||
const matchCSS = (doc, regexes) => {
|
||||
@@ -17,11 +17,11 @@ const matchCSS = (doc, regexes) => {
|
||||
href = elem.href;
|
||||
}
|
||||
}
|
||||
resourceLoader({ url: url.parse(href) }, (_, textContent) => {
|
||||
for (const regex of regexes) {
|
||||
expect(textContent).toMatch(regex);
|
||||
}
|
||||
});
|
||||
|
||||
const textContent = fetchFile(url.parse(href));
|
||||
for (const regex of regexes) {
|
||||
expect(textContent).toMatch(regex);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < regexes.length; ++i) {
|
||||
expect(
|
||||
@@ -33,118 +33,111 @@ const matchCSS = (doc, regexes) => {
|
||||
|
||||
describe('Integration', () => {
|
||||
describe('Webpack plugins', () => {
|
||||
let doc;
|
||||
|
||||
afterEach(() => {
|
||||
doc && doc.defaultView.close();
|
||||
doc = undefined;
|
||||
});
|
||||
|
||||
it('css inclusion', async () => {
|
||||
const doc = await initDOM('css-inclusion');
|
||||
doc = await initDOM('css-inclusion');
|
||||
matchCSS(doc, [
|
||||
/html\{/,
|
||||
/#feature-css-inclusion\{background:.+;color:.+}/,
|
||||
]);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('css modules inclusion', async () => {
|
||||
const doc = await initDOM('css-modules-inclusion');
|
||||
doc = await initDOM('css-modules-inclusion');
|
||||
matchCSS(doc, [
|
||||
/.+style_cssModulesInclusion__.+\{background:.+;color:.+}/,
|
||||
/.+assets_cssModulesIndexInclusion__.+\{background:.+;color:.+}/,
|
||||
]);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('scss inclusion', async () => {
|
||||
const doc = await initDOM('scss-inclusion');
|
||||
doc = await initDOM('scss-inclusion');
|
||||
matchCSS(doc, [/#feature-scss-inclusion\{background:.+;color:.+}/]);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('scss modules inclusion', async () => {
|
||||
const doc = await initDOM('scss-modules-inclusion');
|
||||
doc = await initDOM('scss-modules-inclusion');
|
||||
matchCSS(doc, [
|
||||
/.+scss-styles_scssModulesInclusion.+\{background:.+;color:.+}/,
|
||||
/.+assets_scssModulesIndexInclusion.+\{background:.+;color:.+}/,
|
||||
]);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('sass inclusion', async () => {
|
||||
const doc = await initDOM('sass-inclusion');
|
||||
doc = await initDOM('sass-inclusion');
|
||||
matchCSS(doc, [/#feature-sass-inclusion\{background:.+;color:.+}/]);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('sass modules inclusion', async () => {
|
||||
const doc = await initDOM('sass-modules-inclusion');
|
||||
doc = await initDOM('sass-modules-inclusion');
|
||||
matchCSS(doc, [
|
||||
/.+sass-styles_sassModulesInclusion.+\{background:.+;color:.+}/,
|
||||
/.+assets_sassModulesIndexInclusion.+\{background:.+;color:.+}/,
|
||||
]);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('image inclusion', async () => {
|
||||
const doc = await initDOM('image-inclusion');
|
||||
doc = await initDOM('image-inclusion');
|
||||
|
||||
expect(doc.getElementById('feature-image-inclusion').src).toMatch(
|
||||
/^data:image\/jpeg;base64.+==$/
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('no ext inclusion', async () => {
|
||||
const doc = await initDOM('no-ext-inclusion');
|
||||
doc = await initDOM('no-ext-inclusion');
|
||||
|
||||
expect(doc.getElementById('feature-no-ext-inclusion').href).toMatch(
|
||||
/\/static\/media\/aFileWithoutExt\.[a-f0-9]{8}\.bin$/
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('json inclusion', async () => {
|
||||
const doc = await initDOM('json-inclusion');
|
||||
doc = await initDOM('json-inclusion');
|
||||
|
||||
expect(doc.getElementById('feature-json-inclusion').textContent).toBe(
|
||||
'This is an abstract.'
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('linked modules', async () => {
|
||||
const doc = await initDOM('linked-modules');
|
||||
doc = await initDOM('linked-modules');
|
||||
|
||||
expect(doc.getElementById('feature-linked-modules').textContent).toBe(
|
||||
'2.0.0'
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('svg inclusion', async () => {
|
||||
const doc = await initDOM('svg-inclusion');
|
||||
doc = await initDOM('svg-inclusion');
|
||||
expect(doc.getElementById('feature-svg-inclusion').src).toMatch(
|
||||
/\/static\/media\/logo\..+\.svg$/
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('svg component', async () => {
|
||||
const doc = await initDOM('svg-component');
|
||||
doc = await initDOM('svg-component');
|
||||
|
||||
expect(doc.getElementById('feature-svg-component').textContent).toBe('');
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('svg in css', async () => {
|
||||
const doc = await initDOM('svg-in-css');
|
||||
doc = await initDOM('svg-in-css');
|
||||
matchCSS(doc, [/\/static\/media\/logo\..+\.svg/]);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
|
||||
it('unknown ext inclusion', async () => {
|
||||
const doc = await initDOM('unknown-ext-inclusion');
|
||||
doc = await initDOM('unknown-ext-inclusion');
|
||||
|
||||
expect(doc.getElementById('feature-unknown-ext-inclusion').href).toMatch(
|
||||
/\/static\/media\/aFileWithExt\.[a-f0-9]{8}\.unknown$/
|
||||
);
|
||||
doc.defaultView.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,11 +10,17 @@ import PropTypes from 'prop-types';
|
||||
|
||||
class BuiltEmitter extends Component {
|
||||
static propTypes = {
|
||||
feature: PropTypes.func.isRequired,
|
||||
error: PropTypes.string,
|
||||
feature: PropTypes.func,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { feature } = this.props;
|
||||
const { error, feature } = this.props;
|
||||
|
||||
if (error) {
|
||||
this.handleError(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Class components must call this.props.onReady when they're ready for the test.
|
||||
// We will assume functional components are ready immediately after mounting.
|
||||
@@ -23,6 +29,10 @@ class BuiltEmitter extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleError(error) {
|
||||
document.dispatchEvent(new Event('ReactFeatureError'));
|
||||
}
|
||||
|
||||
handleReady() {
|
||||
document.dispatchEvent(new Event('ReactFeatureDidMount'));
|
||||
}
|
||||
@@ -34,9 +44,10 @@ class BuiltEmitter extends Component {
|
||||
} = this;
|
||||
return (
|
||||
<div>
|
||||
{createElement(feature, {
|
||||
onReady: handleReady,
|
||||
})}
|
||||
{feature &&
|
||||
createElement(feature, {
|
||||
onReady: handleReady,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -52,7 +63,13 @@ class App extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const feature = window.location.hash.slice(1);
|
||||
const url = window.location.href;
|
||||
// const feature = window.location.hash.slice(1);
|
||||
// This works around an issue of a duplicate hash in the href
|
||||
// Ex: http://localhost:3001/#array-destructuring#array-destructuring
|
||||
// This seems like a jsdom bug as the URL in initDom.js appears to be correct
|
||||
const feature = url.slice(url.lastIndexOf("#") + 1);
|
||||
|
||||
switch (feature) {
|
||||
case 'array-destructuring':
|
||||
import('./features/syntax/ArrayDestructuring').then(f =>
|
||||
@@ -223,7 +240,7 @@ class App extends Component {
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Missing feature "${feature}"`);
|
||||
this.setState({ error: `Missing feature "${feature}"` });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,9 +249,9 @@ class App extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { feature } = this.state;
|
||||
if (feature !== null) {
|
||||
return <BuiltEmitter feature={feature} />;
|
||||
const { error, feature } = this.state;
|
||||
if (error || feature) {
|
||||
return <BuiltEmitter error={error} feature={feature} />;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
"@svgr/webpack": "4.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "1.4.1",
|
||||
"@typescript-eslint/parser": "1.4.1",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "10.0.1",
|
||||
"babel-jest": "24.5.0",
|
||||
"babel-jest": "24.7.1",
|
||||
"babel-loader": "8.0.5",
|
||||
"babel-plugin-named-asset-import": "^0.3.1",
|
||||
"babel-preset-react-app": "^7.0.2",
|
||||
@@ -50,9 +49,10 @@
|
||||
"fs-extra": "7.0.1",
|
||||
"html-webpack-plugin": "4.0.0-beta.5",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"jest": "24.5.0",
|
||||
"jest-resolve": "24.5.0",
|
||||
"jest-watch-typeahead": "^0.2.1",
|
||||
"jest": "24.7.1",
|
||||
"jest-environment-jsdom-fourteen": "0.1.0",
|
||||
"jest-resolve": "24.7.1",
|
||||
"jest-watch-typeahead": "0.3.0",
|
||||
"mini-css-extract-plugin": "0.5.0",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.1",
|
||||
"pnp-webpack-plugin": "1.2.1",
|
||||
|
||||
@@ -35,8 +35,7 @@ module.exports = (resolve, rootDir, isEjecting) => {
|
||||
'<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
|
||||
'<rootDir>/src/**/?(*.)(spec|test).{js,jsx,ts,tsx}',
|
||||
],
|
||||
testEnvironment: 'jsdom',
|
||||
testURL: 'http://localhost',
|
||||
testEnvironment: 'jest-environment-jsdom-fourteen',
|
||||
transform: {
|
||||
'^.+\\.(js|jsx|ts|tsx)$': isEjecting
|
||||
? '<rootDir>/node_modules/babel-jest'
|
||||
@@ -58,8 +57,8 @@ module.exports = (resolve, rootDir, isEjecting) => {
|
||||
ext => !ext.includes('mjs')
|
||||
),
|
||||
watchPlugins: [
|
||||
require.resolve('jest-watch-typeahead/filename'),
|
||||
require.resolve('jest-watch-typeahead/testname'),
|
||||
'jest-watch-typeahead/filename',
|
||||
'jest-watch-typeahead/testname',
|
||||
],
|
||||
};
|
||||
if (rootDir) {
|
||||
|
||||
@@ -114,6 +114,7 @@ docker run \
|
||||
--env NPM_CONFIG_PREFIX=/home/node/.npm \
|
||||
--env NPM_CONFIG_QUIET=true \
|
||||
--tty \
|
||||
--rm \
|
||||
--user node \
|
||||
--volume ${PWD}/..:/var/create-react-app \
|
||||
--workdir /home/node \
|
||||
|
||||
Reference in New Issue
Block a user