mirror of
https://github.com/react/react-native.git
synced 2026-10-02 18:09:53 +08:00
Add snapshot validation to build-types (#51893)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51893 This diff adds `--validate` flag that runs snapshot validation to determine if the `ReactNativeApi.d.ts` rollup has been changed (if JS public API has been touched). There was also an issue with `sortProperties` that reordered some properties (ex. in ImagePropsBase) after removing one of them (ex. accessible) which had negative impact on the displayed result. ### Motivation Compare previous snapshot with the one built on the current revision to determine the impact of made changes on the public API surface. Display differences in human readable format using `diff` method from the `jest-diff` library. For now `--validate` flag is not useful on its own. It should be used with `--withSnapshot` flag (which will be removed shortly and generating snapshot will be a default mechanism). Changelog: [General][Added] - Add `--validate` flag to `build-types` script for JS API snapshot validation. Reviewed By: huntie Differential Revision: D76135158 fbshipit-source-id: 53f5b142c66e3e3931961f741c3f2fab8ccdc228
This commit is contained in:
committed by
Facebook GitHub Bot
parent
788c980c7c
commit
f529fd6ba5
@@ -23,9 +23,11 @@ const {
|
||||
} = require('@microsoft/api-extractor');
|
||||
const {promises: fs} = require('fs');
|
||||
const glob = require('glob');
|
||||
const {diff} = require('jest-diff');
|
||||
const path = require('path');
|
||||
const prettier = require('prettier');
|
||||
const osTempDir = require('temp-dir');
|
||||
const {styleText} = require('util');
|
||||
|
||||
const inputFilesPostTransforms: $ReadOnlyArray<PluginObj<mixed>> = [
|
||||
require('./transforms/renameDefaultExportedIdentifiers'),
|
||||
@@ -37,7 +39,7 @@ const postTransforms: $ReadOnlyArray<PluginObj<mixed>> = [
|
||||
require('./transforms/sortUnions'),
|
||||
];
|
||||
|
||||
async function buildAPISnapshot() {
|
||||
async function buildAPISnapshot(validate: boolean) {
|
||||
const tempDirectory = await createTempDir('react-native-js-api-snapshot');
|
||||
const packages = await findPackagesWithTypedef();
|
||||
|
||||
@@ -56,12 +58,23 @@ async function buildAPISnapshot() {
|
||||
if (extractorResult.succeeded) {
|
||||
const apiSnapshot = apiSnapshotTemplate(
|
||||
await getCleanedUpRollup(tempDirectory),
|
||||
);
|
||||
) as string;
|
||||
|
||||
await fs.writeFile(
|
||||
path.join(REACT_NATIVE_PACKAGE_DIR, 'ReactNativeApi.d.ts'),
|
||||
apiSnapshot,
|
||||
);
|
||||
if (validate) {
|
||||
const prevSnapshot = await fs.readFile(
|
||||
path.join(REACT_NATIVE_PACKAGE_DIR, 'ReactNativeApi.d.ts'),
|
||||
'utf-8',
|
||||
);
|
||||
const hasChanged = await validateSnapshots(prevSnapshot, apiSnapshot);
|
||||
if (hasChanged) {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
} else {
|
||||
await fs.writeFile(
|
||||
path.join(REACT_NATIVE_PACKAGE_DIR, 'ReactNativeApi.d.ts'),
|
||||
apiSnapshot,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
process.exitCode = 1;
|
||||
console.error(
|
||||
@@ -73,6 +86,32 @@ async function buildAPISnapshot() {
|
||||
await fs.rm(tempDirectory, {recursive: true});
|
||||
}
|
||||
|
||||
async function validateSnapshots(
|
||||
prevSnapshot: string,
|
||||
newSnapshot: string,
|
||||
): Promise<boolean> {
|
||||
const hasChanged = newSnapshot !== prevSnapshot;
|
||||
if (hasChanged) {
|
||||
const options = {
|
||||
aAnnotation: 'Previous Snapshot',
|
||||
bAnnotation: 'New Snapshot',
|
||||
expand: false,
|
||||
emptyFirstOrLastLinePlaceholder: '↵',
|
||||
includeChangeCounts: true,
|
||||
aColor: (line: string) => styleText(['red'], line),
|
||||
bColor: (line: string) => styleText(['green'], line),
|
||||
};
|
||||
|
||||
const diffResult = diff(prevSnapshot, newSnapshot, options);
|
||||
console.error(
|
||||
`\n${styleText(['inverse'], ' VALIDATE ')} ReactNativeApi.d.ts has changed. Please re-run \`yarn build-types\` and commit the updated snapshot.\n\n`,
|
||||
diffResult,
|
||||
);
|
||||
}
|
||||
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
async function findPackagesWithTypedef() {
|
||||
const packagesWithGeneratedTypes = glob
|
||||
.sync(`${PACKAGES_DIR}/**/types_generated`, {nodir: false})
|
||||
|
||||
@@ -20,12 +20,13 @@ const config = {
|
||||
debug: {type: 'boolean'},
|
||||
help: {type: 'boolean'},
|
||||
withSnapshot: {type: 'boolean'},
|
||||
validate: {type: 'boolean'},
|
||||
},
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const {
|
||||
values: {debug: debugEnabled, help, withSnapshot},
|
||||
values: {debug: debugEnabled, help, withSnapshot, validate},
|
||||
/* $FlowFixMe[incompatible-call] Natural Inference rollout. See
|
||||
* https://fburl.com/workplace/6291gfvu */
|
||||
} = parseArgs(config);
|
||||
@@ -68,7 +69,7 @@ async function main() {
|
||||
'\n',
|
||||
);
|
||||
|
||||
await buildApiSnapshot();
|
||||
await buildApiSnapshot(validate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user