mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-10-27 15:47:30 +03:00
177 lines
5.2 KiB
JavaScript
177 lines
5.2 KiB
JavaScript
|
/**
|
||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* This source code is licensed under the BSD-style license found in the
|
||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||
|
*/
|
||
|
|
||
|
/* @flow */
|
||
|
|
||
|
let fs = require("fs");
|
||
|
let path = require("path");
|
||
|
let { prepackSources } = require("../lib/prepack-node.js");
|
||
|
let babel = require("babel-core");
|
||
|
let React = require("react");
|
||
|
let ReactTestRenderer = require("react-test-renderer");
|
||
|
let { mergeAdacentJSONTextNodes } = require("../lib/utils/json.js");
|
||
|
/* eslint-disable no-undef */
|
||
|
let { expect, describe, it } = global;
|
||
|
|
||
|
let reactTestRoot = path.join(__dirname, "../test/react/");
|
||
|
let prepackOptions = {
|
||
|
compatibility: "react-mocks",
|
||
|
errorHandler: diag => "Fail",
|
||
|
internalDebug: true,
|
||
|
serialize: true,
|
||
|
uniqueSuffix: "",
|
||
|
maxStackDepth: 100,
|
||
|
reactEnabled: true,
|
||
|
inlineExpressions: true,
|
||
|
omitInvariants: true,
|
||
|
};
|
||
|
|
||
|
function compileSourceWithPrepack(source) {
|
||
|
let code = `(function(){${source}})()`;
|
||
|
let serialized = prepackSources([{ filePath: "", fileContents: code, sourceMapContents: "" }], prepackOptions);
|
||
|
// add the React require back in, as we've removed it with our Prepack mock
|
||
|
// the regex checks for any Prepack variable that matches "_$**any digit**.React"
|
||
|
let compiledSource = serialized.code.replace(/_\$[\d].React/, "React = require('react')");
|
||
|
if (serialized == null || serialized.reactStatistics == null) {
|
||
|
throw new Error("React test runner failed during serialization");
|
||
|
}
|
||
|
return {
|
||
|
// replace the code to put back the generator (Prepack doesn't serialize them yet)
|
||
|
compiledSource,
|
||
|
statistics: serialized.reactStatistics,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function runSource(source) {
|
||
|
let codeAfterBabel = babel.transform(source, {
|
||
|
presets: ["babel-preset-react"],
|
||
|
plugins: ["transform-object-rest-spread"],
|
||
|
}).code;
|
||
|
/* eslint-disable no-new-func */
|
||
|
let fn = new Function("require", "module", codeAfterBabel);
|
||
|
let moduleShim = { exports: null };
|
||
|
let requireShim = name => {
|
||
|
switch (name) {
|
||
|
case "react":
|
||
|
return React;
|
||
|
default:
|
||
|
throw new Error(`Unrecognized import: "${name}".`);
|
||
|
}
|
||
|
};
|
||
|
let global = {
|
||
|
require: requireShim,
|
||
|
module: moduleShim,
|
||
|
Object,
|
||
|
String,
|
||
|
};
|
||
|
try {
|
||
|
// $FlowFixMe flow doesn't new Function
|
||
|
fn.call(global, requireShim, moduleShim);
|
||
|
} catch (e) {
|
||
|
console.log(codeAfterBabel);
|
||
|
throw e;
|
||
|
}
|
||
|
return moduleShim.exports;
|
||
|
}
|
||
|
|
||
|
async function runTest(directory, name) {
|
||
|
let source = fs.readFileSync(path.join(reactTestRoot, directory, name)).toString();
|
||
|
let { compiledSource } = compileSourceWithPrepack(source);
|
||
|
|
||
|
let A = runSource(source);
|
||
|
expect(typeof A).toBe("function");
|
||
|
let B = runSource(compiledSource);
|
||
|
expect(typeof B).toBe("function");
|
||
|
|
||
|
let rendererA = ReactTestRenderer.create(null);
|
||
|
let rendererB = ReactTestRenderer.create(null);
|
||
|
|
||
|
if (A == null || B == null) {
|
||
|
throw new Error("React test runner issue");
|
||
|
}
|
||
|
// // Use the original version of the test in case transforming messes it up.
|
||
|
let { getTrials } = A;
|
||
|
// // Run tests that assert the rendered output matches.
|
||
|
let resultA = getTrials(rendererA, A);
|
||
|
let resultB = getTrials(rendererB, B);
|
||
|
|
||
|
// // the test has returned many values for us to check
|
||
|
for (let i = 0; i < resultA.length; i++) {
|
||
|
let [nameA, valueA] = resultA[i];
|
||
|
let [nameB, valueB] = resultB[i];
|
||
|
expect(mergeAdacentJSONTextNodes(valueB)).toEqual(mergeAdacentJSONTextNodes(valueA));
|
||
|
expect(nameB).toEqual(nameA);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Jest tests
|
||
|
let originalConsoleError = console.error;
|
||
|
|
||
|
describe("Test React", () => {
|
||
|
describe("Functional component folding", () => {
|
||
|
let directory = "functional-components";
|
||
|
|
||
|
it("Simple", async () => {
|
||
|
await runTest(directory, "simple.js");
|
||
|
});
|
||
|
|
||
|
it("Simple children", async () => {
|
||
|
await runTest(directory, "simple-children.js");
|
||
|
});
|
||
|
|
||
|
it("Simple refs", async () => {
|
||
|
await runTest(directory, "simple-refs.js");
|
||
|
});
|
||
|
|
||
|
it("Conditional", async () => {
|
||
|
await runTest(directory, "conditional.js");
|
||
|
});
|
||
|
|
||
|
it("Key nesting", async () => {
|
||
|
await runTest(directory, "key-nesting.js");
|
||
|
});
|
||
|
|
||
|
it("Key change", async () => {
|
||
|
await runTest(directory, "key-change.js");
|
||
|
});
|
||
|
|
||
|
it("Component type change", async () => {
|
||
|
await runTest(directory, "type-change.js");
|
||
|
});
|
||
|
|
||
|
it("Dynamic props", async () => {
|
||
|
await runTest(directory, "dynamic-props.js");
|
||
|
});
|
||
|
|
||
|
it("Dynamic context", async () => {
|
||
|
await runTest(directory, "dynamic-context.js");
|
||
|
});
|
||
|
|
||
|
it("React.cloneElement", async () => {
|
||
|
await runTest(directory, "clone-element.js");
|
||
|
});
|
||
|
|
||
|
it("Return text", async () => {
|
||
|
await runTest(directory, "return-text.js");
|
||
|
});
|
||
|
|
||
|
it("Return undefined", async () => {
|
||
|
// this test will cause a React console.error to show
|
||
|
// we monkey patch it to stop it polluting the test output
|
||
|
// with a false-negative error
|
||
|
global.console.error = () => {};
|
||
|
try {
|
||
|
await runTest(directory, "return-undefined.js");
|
||
|
} finally {
|
||
|
global.console.error = originalConsoleError;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|