mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Add async/await to unit tests; modify server rendering tests to use async/await. (#9089)
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
"babel-jest": "^19.0.0",
|
||||
"babel-plugin-check-es2015-constants": "^6.5.0",
|
||||
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
|
||||
"babel-plugin-transform-async-to-generator": "^6.22.0",
|
||||
"babel-plugin-transform-class-properties": "^6.11.5",
|
||||
"babel-plugin-transform-es2015-arrow-functions": "^6.5.2",
|
||||
"babel-plugin-transform-es2015-block-scoped-functions": "^6.5.0",
|
||||
|
||||
@@ -22,6 +22,7 @@ var pathToBabel = path.join(require.resolve('babel-core'), '..', 'package.json')
|
||||
var pathToModuleMap = require.resolve('fbjs/module-map');
|
||||
var pathToBabelPluginDevWithCode = require.resolve('../error-codes/dev-expression-with-codes');
|
||||
var pathToBabelPluginModules = require.resolve('fbjs-scripts/babel-6/rewrite-modules');
|
||||
var pathToBabelPluginAsyncToGenerator = require.resolve('babel-plugin-transform-async-to-generator');
|
||||
var pathToBabelrc = path.join(__dirname, '..', '..', '.babelrc');
|
||||
var pathToErrorCodes = require.resolve('../error-codes/codes.json');
|
||||
|
||||
@@ -54,11 +55,17 @@ module.exports = {
|
||||
!filePath.match(/\/node_modules\//) &&
|
||||
!filePath.match(/\/third_party\//)
|
||||
) {
|
||||
// for test files, we also apply the async-await transform, but we want to
|
||||
// make sure we don't accidentally apply that transform to product code.
|
||||
var isTestFile = !!filePath.match(/\/__tests__\//);
|
||||
return babel.transform(
|
||||
src,
|
||||
Object.assign(
|
||||
{filename: path.relative(process.cwd(), filePath)},
|
||||
babelOptions
|
||||
babelOptions,
|
||||
isTestFile ? {
|
||||
plugins: [pathToBabelPluginAsyncToGenerator].concat(babelOptions.plugins),
|
||||
} : {}
|
||||
)
|
||||
).code;
|
||||
}
|
||||
|
||||
@@ -19,41 +19,44 @@ let ReactDOMServer;
|
||||
// Helper functions for rendering tests
|
||||
// ====================================
|
||||
|
||||
// promisified version of ReactDOM.render()
|
||||
function asyncReactDOMRender(reactElement, domElement) {
|
||||
return new Promise(resolve =>
|
||||
ReactDOM.render(reactElement, domElement, resolve));
|
||||
}
|
||||
// performs fn asynchronously and expects count errors logged to console.error.
|
||||
// will fail the test if the count of errors logged is not equal to count.
|
||||
function expectErrors(fn, count) {
|
||||
async function expectErrors(fn, count) {
|
||||
if (console.error.calls && console.error.calls.reset) {
|
||||
console.error.calls.reset();
|
||||
} else {
|
||||
spyOn(console, 'error');
|
||||
}
|
||||
|
||||
return fn().then((result) => {
|
||||
if (console.error.calls.count() !== count) {
|
||||
console.log(`We expected ${count} warning(s), but saw ${console.error.calls.count()} warning(s).`);
|
||||
if (console.error.calls.count() > 0) {
|
||||
console.log(`We saw these warnings:`);
|
||||
for (var i = 0; i < console.error.calls.count(); i++) {
|
||||
console.log(console.error.calls.argsFor(i)[0]);
|
||||
}
|
||||
const result = await fn();
|
||||
if (console.error.calls.count() !== count && console.error.calls.count() !== 0) {
|
||||
console.log(`We expected ${count} warning(s), but saw ${console.error.calls.count()} warning(s).`);
|
||||
if (console.error.calls.count() > 0) {
|
||||
console.log(`We saw these warnings:`);
|
||||
for (var i = 0; i < console.error.calls.count(); i++) {
|
||||
console.log(console.error.calls.argsFor(i)[0]);
|
||||
}
|
||||
}
|
||||
expectDev(console.error.calls.count()).toBe(count);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
expectDev(console.error.calls.count()).toBe(count);
|
||||
return result;
|
||||
}
|
||||
|
||||
// renders the reactElement into domElement, and expects a certain number of errors.
|
||||
// returns a Promise that resolves when the render is complete.
|
||||
function renderIntoDom(reactElement, domElement, errorCount = 0) {
|
||||
return expectErrors(
|
||||
() => new Promise((resolve) => {
|
||||
async () => {
|
||||
ExecutionEnvironment.canUseDOM = true;
|
||||
ReactDOM.render(reactElement, domElement, () => {
|
||||
ExecutionEnvironment.canUseDOM = false;
|
||||
resolve(domElement.firstChild);
|
||||
});
|
||||
}),
|
||||
await asyncReactDOMRender(reactElement, domElement);
|
||||
ExecutionEnvironment.canUseDOM = false;
|
||||
return domElement.firstChild;
|
||||
},
|
||||
errorCount
|
||||
);
|
||||
}
|
||||
@@ -61,15 +64,14 @@ function renderIntoDom(reactElement, domElement, errorCount = 0) {
|
||||
// Renders text using SSR and then stuffs it into a DOM node; returns the DOM
|
||||
// element that corresponds with the reactElement.
|
||||
// Does not render on client or perform client-side revival.
|
||||
function serverRender(reactElement, errorCount = 0) {
|
||||
return expectErrors(
|
||||
async function serverRender(reactElement, errorCount = 0) {
|
||||
const markup = await expectErrors(
|
||||
() => Promise.resolve(ReactDOMServer.renderToString(reactElement)),
|
||||
errorCount)
|
||||
.then((markup) => {
|
||||
var domElement = document.createElement('div');
|
||||
domElement.innerHTML = markup;
|
||||
return domElement.firstChild;
|
||||
});
|
||||
errorCount
|
||||
);
|
||||
var domElement = document.createElement('div');
|
||||
domElement.innerHTML = markup;
|
||||
return domElement.firstChild;
|
||||
}
|
||||
|
||||
const clientCleanRender = (element, errorCount = 0) => {
|
||||
@@ -77,12 +79,11 @@ const clientCleanRender = (element, errorCount = 0) => {
|
||||
return renderIntoDom(element, div, errorCount);
|
||||
};
|
||||
|
||||
const clientRenderOnServerString = (element, errorCount = 0) => {
|
||||
return serverRender(element, errorCount).then((markup) => {
|
||||
var domElement = document.createElement('div');
|
||||
domElement.innerHTML = markup;
|
||||
return renderIntoDom(element, domElement, errorCount);
|
||||
});
|
||||
const clientRenderOnServerString = async (element, errorCount = 0) => {
|
||||
const markup = await serverRender(element, errorCount);
|
||||
var domElement = document.createElement('div');
|
||||
domElement.innerHTML = markup;
|
||||
return renderIntoDom(element, domElement, errorCount);
|
||||
};
|
||||
|
||||
const clientRenderOnBadMarkup = (element, errorCount = 0) => {
|
||||
@@ -143,24 +144,26 @@ describe('ReactDOMServerIntegration', () => {
|
||||
});
|
||||
|
||||
describe('basic rendering', function() {
|
||||
itRenders('a blank div', render =>
|
||||
render(<div />).then(e => expect(e.tagName).toBe('DIV')));
|
||||
itRenders('a blank div', async render => {
|
||||
const e = await render(<div />);
|
||||
expect(e.tagName).toBe('DIV');
|
||||
});
|
||||
|
||||
itRenders('a div with inline styles', render =>
|
||||
render(<div style={{color:'red', width:'30px'}} />).then(e => {
|
||||
expect(e.style.color).toBe('red');
|
||||
expect(e.style.width).toBe('30px');
|
||||
})
|
||||
);
|
||||
itRenders('a div with inline styles', async render => {
|
||||
const e = await render(<div style={{color:'red', width:'30px'}} />);
|
||||
expect(e.style.color).toBe('red');
|
||||
expect(e.style.width).toBe('30px');
|
||||
});
|
||||
|
||||
itRenders('a self-closing tag', render =>
|
||||
render(<br />).then(e => expect(e.tagName).toBe('BR')));
|
||||
itRenders('a self-closing tag', async render => {
|
||||
const e = await render(<br />);
|
||||
expect(e.tagName).toBe('BR');
|
||||
});
|
||||
|
||||
itRenders('a self-closing tag as a child', render =>
|
||||
render(<div><br /></div>).then(e => {
|
||||
expect(e.childNodes.length).toBe(1);
|
||||
expect(e.firstChild.tagName).toBe('BR');
|
||||
})
|
||||
);
|
||||
itRenders('a self-closing tag as a child', async render => {
|
||||
const e = await render(<div><br /></div>);
|
||||
expect(e.childNodes.length).toBe(1);
|
||||
expect(e.firstChild.tagName).toBe('BR');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user