/** * 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 fs from 'node:fs/promises'; import {format} from 'node:util'; import {parse, dirname} from 'path'; import * as process from 'node:process'; import {Builder, logging} from 'selenium-webdriver'; import {Options} from 'selenium-webdriver/chrome.js'; import {fileURLToPath} from 'url'; import {stdin, stdout} from 'node:process'; import minimist from 'minimist'; import readline from 'node:readline/promises'; import signedsource from 'signedsource'; function addSignatureToSourceCode(sourceCode: string): string { const codeWithToken = sourceCode.replace( 'MAGIC_PLACEHOLDER', signedsource.getSigningToken(), ); return signedsource.signFile(codeWithToken); } const argv = minimist(process.argv.slice(2)); const specificFixture = argv.f || argv.fixture; const suspend = argv.s || argv.suspend; const headless = argv.h || argv.headless; const gentestDir = dirname(fileURLToPath(import.meta.url)); const yogaDir = dirname(gentestDir); let fixtures = await fs.readdir(`${gentestDir}/fixtures`); try { if (specificFixture != null) { await fs.access(`fixtures/${specificFixture}.html`, fs.constants.F_OK); fixtures = [specificFixture + '.html']; } } catch (e) { const errorMessage = e instanceof Error ? e.message : ''; console.log( `Trying to access ${specificFixture}.html threw an exception. Executing against all fixtures. ${errorMessage}`, ); } const options = new Options(); options.addArguments( '--force-device-scale-factor=1', '--window-position=0,0', '--hide-scrollbars', ); headless && options.addArguments('--headless'); options.setLoggingPrefs({ browser: 'ALL', performance: 'ALL', }); const driver = await new Builder() .forBrowser('chrome') .setChromeOptions(options) .build(); for (const fileName of fixtures) { const fixture = await fs.readFile( `${gentestDir}/fixtures/${fileName}`, 'utf8', ); const fileNameNoExtension = parse(fileName).name; console.log('Generate', fileNameNoExtension); // TODO: replace this with something more robust than just blindly replacing // start/end in the entire fixture const ltrFixture = fixture .replaceAll('start', 'left') .replaceAll('end', 'right') .replaceAll('flex-left', 'flex-start') .replaceAll('flex-right', 'flex-end'); const rtlFixture = fixture .replaceAll('start', 'right') .replaceAll('end', 'left') .replaceAll('flex-right', 'flex-start') .replaceAll('flex-left', 'flex-end'); const template = await fs.readFile( `${gentestDir}/test-template.html`, 'utf8', ); const f = await fs.open(`${gentestDir}/test.html`, 'w'); await f.write( format(template, fileNameNoExtension, ltrFixture, rtlFixture, fixture), ); await f.close(); await driver.get('file://' + process.cwd() + '/test.html'); const logs = await driver.manage().logs().get(logging.Type.BROWSER); await fs.writeFile( `${yogaDir}/tests/generated/${fileNameNoExtension}.cpp`, addSignatureToSourceCode(JSON.parse(logs[0].message.replace(/^[^"]*/, ''))), ); await fs.writeFile( `${yogaDir}/java/tests/com/facebook/yoga/${fileNameNoExtension}.java`, addSignatureToSourceCode( JSON.parse(logs[1].message.replace(/^[^"]*/, '')).replace( 'YogaTest', fileNameNoExtension, ), ), ); await fs.writeFile( `${yogaDir}/javascript/tests/generated/${fileNameNoExtension}.test.ts`, addSignatureToSourceCode( JSON.parse(logs[2].message.replace(/^[^"]*/, '')).replace( 'YogaTest', fileNameNoExtension, ), ), ); if (suspend) { const rl = readline.createInterface({input: stdin, output: stdout}); await rl.question(''); rl.close(); } } await fs.unlink(`${gentestDir}/test.html`); await driver.quit();