/** * 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 */ 'use strict'; const _require = require('./CppHelpers'), getImports = _require.getImports; const _require2 = require('../Utils'), toSafeCppString = _require2.toSafeCppString; const FileTemplate = ({libraryName, imports, componentTests}) => ` /** * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). * * Do not edit this file as changes may cause incorrect behavior and will be lost * once the code is regenerated. * * ${'@'}generated by codegen project: GenerateTests.js * */ #include #include #include ${imports} using namespace facebook::react; ${componentTests} `.trim(); const TestTemplate = ({componentName, testName, propName, propValue}) => ` TEST(${componentName}_${testName}, etc) { auto propParser = RawPropsParser(); propParser.prepare<${componentName}>(); auto const &sourceProps = ${componentName}(); auto const &rawProps = RawProps(folly::dynamic::object("${propName}", ${propValue})); ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; rawProps.parse(propParser, parserContext); ${componentName}(parserContext, sourceProps, rawProps); } `; function getTestCasesForProp(propName, typeAnnotation) { const cases = []; if (typeAnnotation.type === 'StringEnumTypeAnnotation') { typeAnnotation.options.forEach(option => cases.push({ propName, testName: `${propName}_${toSafeCppString(option)}`, propValue: option, }), ); } else if (typeAnnotation.type === 'StringTypeAnnotation') { cases.push({ propName, propValue: typeAnnotation.default != null && typeAnnotation.default !== '' ? typeAnnotation.default : 'foo', }); } else if (typeAnnotation.type === 'BooleanTypeAnnotation') { cases.push({ propName: propName, propValue: typeAnnotation.default != null ? typeAnnotation.default : true, }); // $FlowFixMe[incompatible-type] } else if (typeAnnotation.type === 'IntegerTypeAnnotation') { cases.push({ propName, propValue: typeAnnotation.default || 10, }); } else if (typeAnnotation.type === 'FloatTypeAnnotation') { cases.push({ propName, propValue: typeAnnotation.default != null ? typeAnnotation.default : 0.1, }); } else if (typeAnnotation.type === 'ReservedPropTypeAnnotation') { if (typeAnnotation.name === 'ColorPrimitive') { cases.push({ propName, propValue: 1, }); } else if (typeAnnotation.name === 'PointPrimitive') { cases.push({ propName, propValue: 'folly::dynamic::object("x", 1)("y", 1)', raw: true, }); } else if (typeAnnotation.name === 'ImageSourcePrimitive') { cases.push({ propName, propValue: 'folly::dynamic::object("url", "testurl")', raw: true, }); } } return cases; } function generateTestsString(name, component) { function createTest({testName, propName, propValue, raw = false}) { const value = !raw && typeof propValue === 'string' ? `"${propValue}"` : propValue; return TestTemplate({ componentName: name, testName: testName != null ? testName : propName, propName, propValue: String(value), }); } const testCases = component.props.reduce((cases, prop) => { return cases.concat(getTestCasesForProp(prop.name, prop.typeAnnotation)); }, []); const baseTest = { testName: 'DoesNotDie', propName: 'xx_invalid_xx', propValue: 'xx_invalid_xx', }; return [baseTest, ...testCases].map(createTest).join(''); } module.exports = { generate(libraryName, schema, packageName, assumeNonnull = false) { const fileName = 'Tests.cpp'; const allImports = new Set([ '#include ', '#include ', '#include ', ]); const componentTests = Object.keys(schema.modules) .map(moduleName => { const module = schema.modules[moduleName]; if (module.type !== 'Component') { return; } const components = module.components; if (components == null) { return null; } return Object.keys(components) .map(componentName => { const component = components[componentName]; const name = `${componentName}Props`; const imports = getImports(component.props); // $FlowFixMe[method-unbinding] added when improving typing for this parameters imports.forEach(allImports.add, allImports); return generateTestsString(name, component); }) .join(''); }) .filter(Boolean) .join(''); const imports = Array.from(allImports).sort().join('\n').trim(); const replacedTemplate = FileTemplate({ imports, libraryName, componentTests, }); return new Map([[fileName, replacedTemplate]]); }, };