Add `@react-native/codegen-typescript-test` to verify .d.ts files in `@react-native/codegen` (1) (#36562)
Summary: - Add a typescript project to test `CodegenSchema.d.ts`. More tests for other .d.ts files will be added in future pull requests. - The build script scans all snapshots from `react-native/codegen`'s typescript frontend and generates .ts files for each snapshot, but they are .gitignore-ed. - `npm run build` will build these .ts files against `CodegenSchema.d.ts` after generating them. - A failed jest case is included to ensure CI catch it, it will be removed before merged. bypass-github-export-checks ## Changelog: [General] [Added] - Add react-native/codegen-typescript-test to verify .d.ts files in react-native/codegen (1) Pull Request resolved: https://github.com/facebook/react-native/pull/36562 Test Plan: `npm run build` in `packages/react-native-codegen-typescript-test` and see all test files appear in `__generated__`. ## Screenshot ![Untitled](https://user-images.githubusercontent.com/53799235/226757755-cab4cb29-7d22-46a1-9ecb-d6732122ed38.png) Reviewed By: rshest Differential Revision: D44292277 Pulled By: cipolleschi fbshipit-source-id: 8d79fe913f9563d64c92aae7c4f4e97a24ae9a21
This commit is contained in:
Родитель
a248456d18
Коммит
9bb71650c9
|
@ -127,6 +127,8 @@ package-lock.json
|
|||
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec*
|
||||
/**/RCTThirdPartyFabricComponentsProvider.*
|
||||
|
||||
# @react-native/codegen-typescript-test
|
||||
/packages/react-native-codegen-typescript-test/lib
|
||||
|
||||
# Additional SDKs
|
||||
/packages/react-native/sdks/download
|
||||
|
|
1
packages/react-native-codegen-typescript-test/__generated__/.gitignore
сгенерированный
поставляемый
Normal file
1
packages/react-native-codegen-typescript-test/__generated__/.gitignore
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1 @@
|
|||
*.ts
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "@react-native/codegen-typescript-test",
|
||||
"version": "0.0.1",
|
||||
"description": "⚛️ TypeScript related unit test for @react-native/codegen",
|
||||
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-typescript-test",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:facebook/react-native.git",
|
||||
"directory": "packages/react-native-codegen-typescript-test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn clean && node scripts/build.js --verbose && tsc",
|
||||
"clean": "rimraf lib && rimraf __generated__/*.ts",
|
||||
"prepare": "yarn run build"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-native/codegen": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.0.0",
|
||||
"@babel/plugin-transform-destructuring": "^7.0.0",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.0.0",
|
||||
"@babel/preset-env": "^7.14.0",
|
||||
"@types/jest": "^24.0.17",
|
||||
"jest": "^24.0.17",
|
||||
"rimraf": "^3.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/preset-env": "^7.1.6"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const tsComponentFixturePath = path.join(__dirname, '../../react-native-codegen/src/parsers/typescript/components/__test_fixtures__/fixtures.js');
|
||||
const tsComponentSnapshotPath = path.join(__dirname, '../../react-native-codegen/src/parsers/typescript/components/__tests__/__snapshots__/typescript-component-parser-test.js.snap');
|
||||
const tsModuleFixturePath = path.join(__dirname, '../../react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js');
|
||||
const tsModuleSnapshotPath = path.join(__dirname, '../../react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap');
|
||||
const snapshotOutputPath = path.join(__dirname, '../__generated__');
|
||||
|
||||
function genereateSnapshotTestCases(name, fixturePath, snapshotPath, outputPath) {
|
||||
const fixtures = require(fixturePath);
|
||||
const snapshots = require(snapshotPath);
|
||||
for (const key of Object.keys(fixtures)) {
|
||||
const snapshotName = `RN Codegen TypeScript Parser can generate fixture ${key} 1`;
|
||||
const snapshotString = snapshots[snapshotName];
|
||||
const snapshot = snapshotString.substring(2, snapshotString.length - 2);
|
||||
const tsSourceCode = `
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* DO NOT MODIFY
|
||||
* Generated by src/build.js
|
||||
* From snapshot: ${name} - ${key}
|
||||
*/
|
||||
|
||||
import type { SchemaType } from '@react-native/codegen/lib/CodegenSchema';
|
||||
const snapshot : SchemaType = ${snapshot};
|
||||
export default snapshot;
|
||||
`;
|
||||
fs.writeFileSync(path.join(outputPath, `${name}_${key}.ts`), tsSourceCode, { encoding: 'utf-8' });
|
||||
}
|
||||
}
|
||||
|
||||
genereateSnapshotTestCases('component', tsComponentFixturePath, tsComponentSnapshotPath, snapshotOutputPath);
|
||||
genereateSnapshotTestCases('module', tsModuleFixturePath, tsModuleSnapshotPath, snapshotOutputPath);
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import type {SchemaType} from '@react-native/codegen/lib/CodegenSchema';
|
||||
import {TypeScriptParser} from '@react-native/codegen/lib/parsers/typescript/parser';
|
||||
|
||||
test(`@rn/codegen should parse an empty TypeScript module`, () => {
|
||||
const tsInput = `
|
||||
import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';
|
||||
import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry';
|
||||
|
||||
export interface Spec extends TurboModule {}
|
||||
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
|
||||
`;
|
||||
const parser = new TypeScriptParser();
|
||||
const actual = parser.parseString(tsInput, 'SampleTurboModule.ts');
|
||||
const expected: SchemaType = {
|
||||
modules: {
|
||||
SampleTurboModule: {
|
||||
aliasMap: {},
|
||||
enumMap: {},
|
||||
excludedPlatforms: undefined,
|
||||
moduleName: 'SampleTurboModule',
|
||||
spec: {
|
||||
properties: [],
|
||||
},
|
||||
type: 'NativeModule',
|
||||
},
|
||||
},
|
||||
};
|
||||
assert.deepStrictEqual(actual, expected);
|
||||
});
|
||||
|
||||
test(`@rn/codegen should parse an empty TypeScript component`, () => {
|
||||
const tsInput = `
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {HostComponent} from 'react-native';
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
export interface ModuleProps extends ViewProps {}
|
||||
export default codegenNativeComponent<ModuleProps>('Module', {
|
||||
interfaceOnly: true,
|
||||
paperComponentName: 'RCTModule',
|
||||
}) as HostComponent<ModuleProps>;
|
||||
`;
|
||||
const parser = new TypeScriptParser();
|
||||
const actual = parser.parseString(tsInput, 'SampleNativeComponent.ts');
|
||||
const expected: SchemaType = {
|
||||
modules: {
|
||||
Module: {
|
||||
components: {
|
||||
Module: {
|
||||
commands: [],
|
||||
events: [],
|
||||
extendsProps: [
|
||||
{
|
||||
knownTypeName: 'ReactNativeCoreViewProps',
|
||||
type: 'ReactNativeBuiltInType',
|
||||
},
|
||||
],
|
||||
interfaceOnly: true,
|
||||
paperComponentName: 'RCTModule',
|
||||
props: [],
|
||||
},
|
||||
},
|
||||
type: 'Component',
|
||||
},
|
||||
},
|
||||
};
|
||||
assert.deepStrictEqual(actual, expected);
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es5",
|
||||
"declaration": false,
|
||||
"sourceMap": false,
|
||||
"outDir": "./lib",
|
||||
"noEmitOnError": true,
|
||||
"noUnusedLocals": true,
|
||||
"strictNullChecks": true,
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"lib"
|
||||
]
|
||||
}
|
|
@ -50,6 +50,10 @@ export interface ObjectTypeAnnotation<T> {
|
|||
readonly baseTypes?: readonly string[] | undefined;
|
||||
}
|
||||
|
||||
export interface MixedTypeAnnotation {
|
||||
readonly type: 'MixedTypeAnnotation';
|
||||
}
|
||||
|
||||
export interface FunctionTypeAnnotation<P, R> {
|
||||
readonly type: 'FunctionTypeAnnotation';
|
||||
readonly params: readonly NamedShape<P>[];
|
||||
|
@ -74,6 +78,7 @@ export interface ComponentShape extends OptionsShape {
|
|||
readonly events: readonly EventTypeShape[];
|
||||
readonly props: readonly NamedShape<PropTypeAnnotation>[];
|
||||
readonly commands: readonly NamedShape<CommandTypeAnnotation>[];
|
||||
readonly deprecatedViewConfigName?: string | undefined;
|
||||
}
|
||||
|
||||
export interface OptionsShape {
|
||||
|
@ -168,7 +173,8 @@ export type PropTypeAnnotation =
|
|||
readonly type: 'ArrayTypeAnnotation';
|
||||
readonly elementType: ObjectTypeAnnotation<PropTypeAnnotation>;
|
||||
};
|
||||
};
|
||||
}
|
||||
| MixedTypeAnnotation;
|
||||
|
||||
export interface ReservedPropTypeAnnotation {
|
||||
readonly type: 'ReservedPropTypeAnnotation';
|
||||
|
@ -263,7 +269,7 @@ export interface NativeModuleBooleanTypeAnnotation {
|
|||
|
||||
export type NativeModuleEnumMembers = readonly {
|
||||
readonly name: string;
|
||||
readonly value: string;
|
||||
readonly value: string | number;
|
||||
}[];
|
||||
|
||||
export type NativeModuleEnumMemberType =
|
||||
|
@ -343,6 +349,7 @@ export type NativeModuleTypeAnnotation =
|
|||
export type NativeModuleParamOnlyTypeAnnotation = NativeModuleFunctionTypeAnnotation;
|
||||
|
||||
export type NativeModuleReturnOnlyTypeAnnotation =
|
||||
| NativeModuleFunctionTypeAnnotation
|
||||
| NativeModulePromiseTypeAnnotation
|
||||
| VoidTypeAnnotation;
|
||||
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type {Parser} from '../parser';
|
||||
import type { Parser } from '../parser';
|
||||
import type { SchemaType } from '../../CodegenSchema';
|
||||
import type { ParserType } from '../errors';
|
||||
|
||||
export declare class FlowParser implements Parser{}
|
||||
export declare class FlowParser implements Parser {
|
||||
language(): ParserType;
|
||||
parseFile(filename: string): SchemaType;
|
||||
parseString(contents: string, filename?: string): SchemaType;
|
||||
parseModuleFixture(filename: string): SchemaType;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type {Parser} from '../parser';
|
||||
import type { Parser } from '../parser';
|
||||
import type { SchemaType } from '../../CodegenSchema';
|
||||
import type { ParserType } from '../errors';
|
||||
|
||||
export declare class TypeScriptParser implements Parser{}
|
||||
export declare class TypeScriptParser implements Parser {
|
||||
language(): ParserType;
|
||||
parseFile(filename: string): SchemaType;
|
||||
parseString(contents: string, filename?: string): SchemaType;
|
||||
parseModuleFixture(filename: string): SchemaType;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,33 @@ try {
|
|||
throw Error(exitCode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build @react-native/codegen and @react-native/codegen-typescript-test
|
||||
*
|
||||
* The typescript-test project use TypeScript to write test cases
|
||||
* In order to make these tests discoverable to jest
|
||||
* *-test.ts must be compiled to *-test.js before running jest
|
||||
*/
|
||||
|
||||
describe('Test: Build @react-native/codegen');
|
||||
if (
|
||||
exec(`${YARN_BINARY} --cwd ./packages/react-native-codegen run build`).code
|
||||
) {
|
||||
echo('Failed to build @react-native/codegen.');
|
||||
exitCode = 1;
|
||||
throw Error(exitCode);
|
||||
}
|
||||
describe('Test: Build @react-native/codegen-typescript-test');
|
||||
if (
|
||||
exec(
|
||||
`${YARN_BINARY} --cwd ./packages/react-native-codegen-typescript-test run build`,
|
||||
).code
|
||||
) {
|
||||
echo('Failed to build @react-native/codegen-typescript-test.');
|
||||
exitCode = 1;
|
||||
throw Error(exitCode);
|
||||
}
|
||||
|
||||
describe('Test: Jest');
|
||||
if (
|
||||
exec(
|
||||
|
|
2265
yarn.lock
2265
yarn.lock
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче