Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cli] Third party libraries can be configured into config.json #4535

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion cli/src/cli.js
@@ -1,6 +1,5 @@
#!/usr/bin/env node
// @flow

import yargs from 'yargs';
import {fs, path} from './lib/node';

Expand Down
2 changes: 2 additions & 0 deletions cli/src/commands/__tests__/runTests-test.js
Expand Up @@ -50,13 +50,15 @@ describe('run-tests (command)', () => {
const createFlowConfig = async (
version: string,
depPaths?: Array<string> = [],
npmDeps?: Array<string> = [],
) => {
await writeFlowConfig(
fixtureBasePath,
testDir,
path.join(fixtureBasePath, 'definitions/npm/def/'),
version,
depPaths,
npmDeps,
);

return fs.readFileSync(flowConfigFile, 'utf-8').split('\n');
Expand Down
76 changes: 66 additions & 10 deletions cli/src/commands/runTests.js
@@ -1,12 +1,13 @@
// @flow
import {execSync} from 'child_process';
import colors from 'colors';

import {child_process, fs, os, path} from '../lib/node.js';
import {copyFile, recursiveRmdir} from '../lib/fileUtils.js';
import {gitHubClient} from '../lib/github.js';
import {getNpmLibDefDirFromNested} from '../lib/npm/npmLibDefs';
import {getLibDefs, parseRepoDirItem} from '../lib/libDefs.js';
import {listItem, sectionHeader} from '../lib/logger';
import {listItem, sectionHeader, info} from '../lib/logger';
import isInFlowTypedRepo from '../lib/isInFlowTypedRepo';
import {
toSemverString as flowVerToSemverString,
Expand Down Expand Up @@ -76,6 +77,15 @@ type TestGroup = {
deps: {
[key: string]: Array<string>,
},
/**
* Object of dependency version pairs for dependencies to install
* and load for testing so that definitions can be tested against
* typed libraries they depend as they would when installed
* in a real project
*/
npmDeps: {
[key: string]: string,
},
};

/**
Expand Down Expand Up @@ -129,10 +139,12 @@ async function getTestGroups(
if (def.configPath) {
const deps = JSON.parse(fs.readFileSync(def.configPath, 'utf-8'))
.deps;
const isDependantOfChanged = Object.keys(deps).some(
dep => dep === d.name && deps[dep].some(s => s === d.version),
);
if (isDependantOfChanged) return true;
if (deps) {
const isDependantOfChanged = Object.keys(deps).some(
dep => dep === d.name && deps[dep].some(s => s === d.version),
);
if (isDependantOfChanged) return true;
}
}
return d.name === def.pkgName && d.version === def.pkgVersionStr;
});
Expand All @@ -141,16 +153,17 @@ async function getTestGroups(
return libDefs.map(libDef => {
const groupID = `${libDef.pkgName}_${libDef.pkgVersionStr}/${libDef.flowVersionStr}`;

const deps = libDef.configPath
? JSON.parse(fs.readFileSync(libDef.configPath, 'utf-8')).deps
const definitionConfig = libDef.configPath
? JSON.parse(fs.readFileSync(libDef.configPath, 'utf-8'))
: {};

return {
id: groupID,
testFilePaths: libDef.testFilePaths,
libDefPath: libDef.path,
flowVersion: libDef.flowVersion,
deps,
deps: definitionConfig.deps ?? {},
npmDeps: definitionConfig.npmDeps ?? {},
};
});
}
Expand Down Expand Up @@ -205,6 +218,12 @@ async function getOrderedFlowBinVersions(
}
} catch (e) {
console.error(e);
info(
`\nYou've exceeded the API rate limit, try adding GITHUB_TOKEN env variable before calling tests`,
);
info(
'You can generate a token here: https://github.com/settings/tokens',
);
foundAllFlowVersions = true;
}
}
Expand Down Expand Up @@ -382,6 +401,7 @@ export async function writeFlowConfig(
libDefPath: string,
version: string,
depPaths: Array<string>,
npmDeps: Array<string>,
) {
// /!\---------------------------------------------------------------------/!\
// Whenever you introduce a new difference depending on the version, don't
Expand All @@ -404,12 +424,26 @@ export async function writeFlowConfig(
semver.lt(version, '0.125.0')
? 'suppress_comment=\\\\(.\\\\|\\n\\\\)*\\\\$FlowExpectedError'
: '',
// ...npmDeps.map(
// dep =>
// `module.name_mapper='^${dep}$' -> '${path.join(
// testDirPath,
// 'node_modules',
// dep,
// )}'`,
// ),
`module.name_mapper='^react-native$' -> '${testDirPath}}/node_modules/react-native'`,
'',

// Be sure to ignore stuff in the node_modules directory of the flow-typed
// CLI repository!
'[ignore]',
path.join(testDirPath, '..', '..', 'node_modules'),
path.join(testDirPath, 'node_modules'),

// TODO under this config key is more correct
// '[declarations]',
...npmDeps.map(dep => `!${path.join(testDirPath, 'node_modules', dep)}`),
'',
'[lints]',
semver.gte(version, '0.104.0') && semver.lt(version, '0.201.0')
Expand Down Expand Up @@ -527,6 +561,7 @@ async function findLowestCapableFlowVersion(
testDirPath,
libDefPath,
depPaths,
npmDeps,
) {
let lowerFlowVersionsToRun = orderedFlowVersions.filter(flowVer => {
return semver.lt(flowVer, lowestFlowVersionRan);
Expand All @@ -538,6 +573,7 @@ async function findLowestCapableFlowVersion(
libDefPath,
lowestFlowVersionRan,
depPaths,
npmDeps,
);
return await testLowestCapableFlowVersion(
lowerFlowVersionsToRun,
Expand Down Expand Up @@ -684,6 +720,20 @@ function getDepTestGroups(testGroup) {
return depGroup;
}

function installNpmDependencies(testDirPath: string, testGroup: TestGroup) {
const {npmDeps} = testGroup;
const depKeys = Object.keys(npmDeps);
if (depKeys.length === 0) return;

execSync(`(cd ${testDirPath}; npm init -y)`);

depKeys.forEach(dep => {
info(`Installing ${dep}...`);
execSync(`(cd ${testDirPath}; npm i ${dep}@${npmDeps[dep]})`);
info(`${dep} has been installed for testing`);
});
}

/**
* Given a TestGroup structure determine all versions of Flow that match the
* FlowVersion specification and, for each, run `flow check` on the test
Expand Down Expand Up @@ -766,7 +816,11 @@ async function runTestGroup(
testGroup.libDefPath,
lowestFlowVersionRanInThisGroup,
depPaths,
Object.keys(testGroup.npmDeps),
);

installNpmDependencies(testDirPath, testGroup);

const flowErrorsForThisGroup = await runFlowTypeDefTests(
[...sublistOfFlowVersions],
testGroup.id,
Expand All @@ -783,6 +837,7 @@ async function runTestGroup(
testDirPath,
testGroup.libDefPath,
depPaths,
Object.keys(testGroup.npmDeps),
);

if (lowestCapableFlowVersion !== lowestFlowVersionRan) {
Expand All @@ -804,7 +859,7 @@ async function runTestGroup(
return flowErrors;
} finally {
if (await fs.exists(testDirPath)) {
await recursiveRmdir(testDirPath);
// await recursiveRmdir(testDirPath);
}
}
}
Expand Down Expand Up @@ -950,7 +1005,8 @@ async function runTests(
return results;
} finally {
if (await fs.exists(TEST_DIR)) {
await recursiveRmdir(TEST_DIR);
// TODO: Add a debug mode that won't delete this
// await recursiveRmdir(TEST_DIR);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions cli/src/lib/logger.js
Expand Up @@ -34,3 +34,7 @@ export const listItem = (...values: Array<string | void>): void => {
export const sectionHeader = (title: string): void => {
console.log(colors.green(`===> ${colors.bold(title)} <===`));
};

export const info = (message: string) => {
console.log(colors.green(colors.bold(message)));
};
@@ -0,0 +1,5 @@
{
"npmDeps": {
"react-native": "0"
}
}
@@ -1,6 +1,5 @@
declare module "react-native-vision-camera" {
// import type { ViewProps } from "react-native";
declare type ViewProps = {...};
import type { ViewProps } from "react-native";

/**
* Represents the camera device position.
Expand Down