Skip to content

Commit

Permalink
fix: invalid output from config command (react-native-community#1131)
Browse files Browse the repository at this point in the history
* Moved disabling logger at the top when user used config command

* Added e2e tests for config command

* Added config command output snapshot

* Updated config test snapshot

* Added project root replacement helper

* Removed default terminal program from snapshots

* Moved tests to jest folder and removed additional snapshot

* less snapshots; use raw serializer

* strip unnecessary parts of the snapshot

* Added tmp directory to regex which replaces project root before snapshot

* Added slash before passing testFolder for project root replacing helper

* Fixed problem with windows paths replacing

* CR fixes

Co-authored-by: Michał Pierzchała <[email protected]>
  • Loading branch information
TMaszko and thymikee authored Apr 29, 2020
1 parent cbcdf20 commit 9e44835
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 7 deletions.
70 changes: 70 additions & 0 deletions __e2e__/__snapshots__/config.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`shows up current config without unnecessary output 1`] = `
{
"root": "<<REPLACED_ROOT>>/TestProject",
"reactNativePath": "<<REPLACED_ROOT>>/TestProject/node_modules/react-native",
"dependencies": {},
"commands": [
{
"name": "log-ios",
"description": "starts iOS device syslog tail"
},
{
"name": "run-ios",
"description": "builds your app and starts it on iOS simulator",
"examples": [
"<<REPLACED>>"
],
"options": [
"<<REPLACED>>"
]
},
{
"name": "log-android",
"description": "starts logkitty"
},
{
"name": "run-android",
"description": "builds your app and starts it on a connected Android emulator or device",
"options": [
"<<REPLACED>>"
]
}
],
"assets": [],
"platforms": {
"ios": {},
"android": {}
},
"project": {
"ios": {
"sourceDir": "<<REPLACED_ROOT>>/TestProject/ios",
"folder": "<<REPLACED_ROOT>>/TestProject",
"pbxprojPath": "<<REPLACED_ROOT>>/TestProject/ios/TestProject.xcodeproj/project.pbxproj",
"podfile": "<<REPLACED_ROOT>>/TestProject/ios/Podfile",
"podspecPath": null,
"projectPath": "<<REPLACED_ROOT>>/TestProject/ios/TestProject.xcodeproj",
"projectName": "TestProject.xcodeproj",
"libraryFolder": "Libraries",
"sharedLibraries": [],
"plist": [],
"scriptPhases": []
},
"android": {
"sourceDir": "<<REPLACED_ROOT>>/TestProject/android",
"isFlat": true,
"folder": "<<REPLACED_ROOT>>/TestProject",
"stringsPath": "<<REPLACED_ROOT>>/TestProject/android/app/src/main/res/values/strings.xml",
"manifestPath": "<<REPLACED_ROOT>>/TestProject/android/app/src/main/AndroidManifest.xml",
"buildGradlePath": "<<REPLACED_ROOT>>/TestProject/android/build.gradle",
"settingsGradlePath": "<<REPLACED_ROOT>>/TestProject/android/settings.gradle",
"assetsPath": "<<REPLACED_ROOT>>/TestProject/android/app/src/main/assets",
"mainFilePath": "<<REPLACED_ROOT>>/TestProject/android/app/src/main/java/com/testproject/MainApplication.java",
"packageName": "com.testproject",
"packageFolder": "com/testproject",
"appName": "app"
}
}
}
`;
93 changes: 93 additions & 0 deletions __e2e__/config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import path from 'path';
import fs from 'fs';
import {wrap} from 'jest-snapshot-serializer-raw';
import {
runCLI,
getTempDirectory,
cleanup,
writeFiles,
spawnScript,
replaceProjectRootInOutput,
} from '../jest/helpers';

const DIR = getTempDirectory('test_root');

function isValidJSON(text: string) {
try {
JSON.parse(text);
return true;
} catch {
return false;
}
}

// We have to check whether setup_env script fails, if it does then we shouldn't log any info to the console
function createCorruptedSetupEnvScript() {
const originalSetupEnvPath = path.join(
__dirname,
'../packages/cli/setup_env.sh',
);
const originalSetupEnv = fs.readFileSync(originalSetupEnvPath);
const corruptedScript = '#!/bin/sh\n exit 1;';
fs.writeFileSync(originalSetupEnvPath, corruptedScript);
return () => {
fs.writeFileSync(originalSetupEnvPath, originalSetupEnv);
};
}

beforeAll(() => {
// Register all packages to be linked
for (const pkg of ['platform-ios', 'platform-android']) {
spawnScript('yarn', ['link'], {
cwd: path.join(__dirname, `../packages/${pkg}`),
});
}

// Clean up folder and re-create a new project
cleanup(DIR);
writeFiles(DIR, {});

// Initialise React Native project

runCLI(DIR, ['init', 'TestProject']);

// Link CLI to the project
const pkgs = [
'@react-native-community/cli-platform-ios',
'@react-native-community/cli-platform-android',
];

spawnScript('yarn', ['link', ...pkgs], {
cwd: path.join(DIR, 'TestProject'),
});
});

afterAll(() => {
cleanup(DIR);
});

test('shows up current config without unnecessary output', () => {
const {stdout} = runCLI(path.join(DIR, 'TestProject'), ['config']);
const parsedStdout = JSON.parse(stdout);
// Strip unnecessary parts
parsedStdout.commands = parsedStdout.commands.map((command: any) => ({
...command,
examples: command.examples && ['<<REPLACED>>'],
options: command.options && ['<<REPLACED>>'],
}));

const configWithReplacedProjectRoots = replaceProjectRootInOutput(
JSON.stringify(parsedStdout, null, 2).replace(/\\\\/g, '\\'),
DIR,
);
expect(wrap(configWithReplacedProjectRoots)).toMatchSnapshot();
});

test('should log only valid JSON config if setting up env throws an error', () => {
const restoreOriginalSetupEnvScript = createCorruptedSetupEnvScript();
const {stdout, stderr} = runCLI(path.join(DIR, 'TestProject'), ['config']);

restoreOriginalSetupEnvScript();
expect(isValidJSON(stdout)).toBe(true);
expect(stderr).toBe('');
});
5 changes: 4 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
const common = {testEnvironment: 'node'};
const common = {
testEnvironment: 'node',
snapshotSerializers: [require.resolve('jest-snapshot-serializer-raw')],
};

module.exports = {
projects: [
Expand Down
14 changes: 14 additions & 0 deletions jest/__tests__/replaceProjectRootInOutput.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {replaceProjectRootInOutput} from '../helpers';

test('should replace project root in output with <<REPLACED_ROOT>> value', () => {
const cwd = '/var/folders/zt/917v0jxx6lg3p_zfh9s_02bm0000gn/T/';
const output = `{
"root": "/private${cwd}/test_root/TestProject",
}`;
const outputWithReplacedProjectRoot = `{
"root": "<<REPLACED_ROOT>>/test_root/TestProject",
}`;
expect(replaceProjectRootInOutput(output, cwd)).toBe(
outputWithReplacedProjectRoot,
);
});
6 changes: 6 additions & 0 deletions jest/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {createDirectory} from 'jest-util';
import rimraf from 'rimraf';
import execa from 'execa';
import chalk from 'chalk';
import slash from 'slash';
// @ts-ignore jsfile
import {Writable} from 'readable-stream';

Expand Down Expand Up @@ -196,3 +197,8 @@ ${chalk.bold('stdout:')} ${result.stdout}
${chalk.bold('code:')} ${result.code}`);
}
}

export function replaceProjectRootInOutput(output: string, testFolder: string) {
const regex = new RegExp(`(:\\s").*(${slash(testFolder)})`, 'g');
return slash(output).replace(regex, '$1<<REPLACED_ROOT>>');
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@
"execa": "^1.0.0",
"glob": "^7.1.3",
"jest": "^25.2.4",
"jest-snapshot-serializer-raw": "^1.1.0",
"lerna": "^3.18.4",
"metro-memory-fs": "^0.58.0",
"micromatch": "^3.1.10",
"mkdirp": "^0.5.3",
"rimraf": "^3.0.2",
"slash": "^3.0.0",
"string-length": "^2.0.0",
"typescript": "^3.8.0"
},
Expand Down
13 changes: 7 additions & 6 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ async function run() {

async function setupAndRun() {
// Commander is not available yet

// when we run `config`, we don't want to output anything to the console. We
// expect it to return valid JSON
if (process.argv.includes('config')) {
logger.disable();
}

logger.setVerbose(process.argv.includes('--verbose'));

// We only have a setup script for UNIX envs currently
Expand All @@ -206,12 +213,6 @@ async function setupAndRun() {
}

try {
// when we run `config`, we don't want to output anything to the console. We
// expect it to return valid JSON
if (process.argv.includes('config')) {
logger.disable();
}

const ctx = loadConfig();

logger.enable();
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6861,6 +6861,11 @@ jest-serializer@^25.2.1:
resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-25.2.1.tgz#51727a5fc04256f461abe0fa024a022ba165877a"
integrity sha512-fibDi7M5ffx6c/P66IkvR4FKkjG5ldePAK1WlbNoaU4GZmIAkS9Le/frAwRUFEX0KdnisSPWf+b1RC5jU7EYJQ==

jest-snapshot-serializer-raw@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/jest-snapshot-serializer-raw/-/jest-snapshot-serializer-raw-1.1.0.tgz#1d7f09c02f3dbbc3ae70b5b7598fb2f45e37d6c8"
integrity sha512-OL3bXRCnSn7Kur3YTGYj+A3Hwh2eyb5QL5VLQ9OSsPBOva7r3sCB0Jf1rOT/KN3ypzH42hrkDz96lpbiMo+AlQ==

jest-snapshot@^25.1.0, jest-snapshot@^25.2.4:
version "25.2.4"
resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-25.2.4.tgz#08d4517579c864df4280bcc948ceea34327a4ded"
Expand Down

0 comments on commit 9e44835

Please sign in to comment.