зеркало из https://github.com/microsoft/rnx-kit.git
feat(dep-check): add migration message (#1941)
This commit is contained in:
Родитель
f7194964b1
Коммит
93b480ab8e
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@rnx-kit/dep-check": minor
|
||||
---
|
||||
|
||||
Tell users to migrate to `@rnx-kit/align-deps`
|
|
@ -1,3 +1,7 @@
|
|||
# `@rnx-kit/dep-check` has been renamed to `@rnx-kit/align-deps`
|
||||
|
||||
For more details, read the RFC: https://github.com/microsoft/rnx-kit/pull/1757
|
||||
|
||||
<!--remove-block start-->
|
||||
|
||||
# @rnx-kit/dep-check
|
||||
|
|
|
@ -21,11 +21,7 @@
|
|||
"scripts": {
|
||||
"build": "rnx-kit-scripts build",
|
||||
"bundle": "rnx-kit-scripts bundle",
|
||||
"format": "rnx-kit-scripts format",
|
||||
"lint": "rnx-kit-scripts lint",
|
||||
"test": "rnx-kit-scripts test",
|
||||
"update-profile": "node scripts/update-profile.mjs",
|
||||
"update-readme": "node scripts/update-readme.js"
|
||||
"format": "rnx-kit-scripts format"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rnx-kit/config": "*",
|
||||
|
@ -44,8 +40,6 @@
|
|||
"detect-indent": "^6.0.0",
|
||||
"jest-diff": "^26.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-table": "^2.0.0",
|
||||
"pacote": "^12.0.0",
|
||||
"prompts": "^2.4.0",
|
||||
"semver": "^7.0.0",
|
||||
"yargs": "^16.0.0"
|
||||
|
@ -55,8 +49,5 @@
|
|||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@rnx-kit/eslint-config"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@rnx-kit/scripts"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,399 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
// @ts-check
|
||||
|
||||
import { existsSync as fileExists } from "fs";
|
||||
import * as fs from "fs/promises";
|
||||
import markdownTable from "markdown-table";
|
||||
import pacote from "pacote";
|
||||
import * as path from "path";
|
||||
import semverCoerce from "semver/functions/coerce.js";
|
||||
import semverCompare from "semver/functions/compare.js";
|
||||
import { fileURLToPath } from "url";
|
||||
import { isMetaPackage } from "../lib/capabilities.js";
|
||||
|
||||
/**
|
||||
* @typedef {import("../src/types").MetaPackage} MetaPackage
|
||||
* @typedef {import("../src/types").Package} Package
|
||||
* @typedef {import("../src/types").Profile} Profile
|
||||
*
|
||||
* @typedef {{
|
||||
* name: string;
|
||||
* version: string;
|
||||
* latest: string;
|
||||
* homepage: string;
|
||||
* dependencies?: Record<string, string>;
|
||||
* peerDependencies?: Record<string, string>;
|
||||
* }} PackageInfo
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches package manifest from npm.
|
||||
* @param {MetaPackage | Package} pkg
|
||||
* @param {string=} defaultTag
|
||||
* @returns {Promise<PackageInfo | void>}
|
||||
*/
|
||||
async function fetchPackageInfo(pkg, defaultTag = "latest") {
|
||||
if (isMetaPackage(pkg)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const { name, version } = pkg;
|
||||
const manifest = await pacote.manifest(name, {
|
||||
defaultTag,
|
||||
fullMetadata: true,
|
||||
});
|
||||
return {
|
||||
name,
|
||||
version,
|
||||
latest: manifest.version,
|
||||
homepage: manifest.homepage,
|
||||
dependencies: manifest.dependencies,
|
||||
peerDependencies: manifest.peerDependencies,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} packageName
|
||||
* @param {Record<string, string>?} dependencies
|
||||
* @returns {string}
|
||||
*/
|
||||
function getPackageVersion(packageName, dependencies) {
|
||||
const packageVersion = dependencies?.[packageName];
|
||||
if (!packageVersion) {
|
||||
throw new Error(`Failed to get '${packageName}' version`);
|
||||
}
|
||||
return semverCoerce(packageVersion).version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to a profile.
|
||||
* @param {string} preset
|
||||
* @param {string} profileVersion
|
||||
* @returns {string}
|
||||
*/
|
||||
function getProfilePath(preset, profileVersion) {
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
return path.relative(
|
||||
process.cwd(),
|
||||
path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"src",
|
||||
"presets",
|
||||
preset,
|
||||
`profile-${profileVersion}.ts`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a profile.
|
||||
* @param {{
|
||||
* preset: string;
|
||||
* targetVersion: string;
|
||||
* reactVersion: string;
|
||||
* metroVersion: string;
|
||||
* }} versions
|
||||
* @returns {string}
|
||||
*/
|
||||
function generateFromTemplate({
|
||||
preset,
|
||||
targetVersion,
|
||||
reactVersion,
|
||||
metroVersion,
|
||||
}) {
|
||||
const nextVersionCoerced = semverCoerce(targetVersion);
|
||||
const currentVersion = `${nextVersionCoerced.major}.${
|
||||
nextVersionCoerced.minor - 1
|
||||
}`;
|
||||
|
||||
const currentProfile = getProfilePath(preset, currentVersion);
|
||||
if (!fileExists(currentProfile)) {
|
||||
throw new Error(`Could not find '${currentProfile}'`);
|
||||
}
|
||||
|
||||
const currentVersionVarName = `${nextVersionCoerced.major}_${
|
||||
nextVersionCoerced.minor - 1
|
||||
}`;
|
||||
return `import type { Profile, Package } from "../../types";
|
||||
import profile_${currentVersionVarName} from "./profile-${currentVersion}";
|
||||
|
||||
const reactNative: Package = {
|
||||
name: "react-native",
|
||||
version: "^${targetVersion}.0",
|
||||
capabilities: ["react"],
|
||||
};
|
||||
|
||||
const profile: Profile = {
|
||||
...profile_${currentVersionVarName},
|
||||
react: {
|
||||
name: "react",
|
||||
version: "${reactVersion}",
|
||||
},
|
||||
"react-dom": {
|
||||
name: "react-dom",
|
||||
version: "^${reactVersion}",
|
||||
capabilities: ["react"],
|
||||
},
|
||||
"react-test-renderer": {
|
||||
name: "react-test-renderer",
|
||||
version: "${reactVersion}",
|
||||
capabilities: ["react"],
|
||||
devOnly: true,
|
||||
},
|
||||
|
||||
core: reactNative,
|
||||
"core-android": reactNative,
|
||||
"core-ios": reactNative,
|
||||
"core-macos": {
|
||||
name: "react-native-macos",
|
||||
version: "^${targetVersion}.0",
|
||||
capabilities: ["react"],
|
||||
},
|
||||
"core-windows": {
|
||||
name: "react-native-windows",
|
||||
version: "^${targetVersion}.0",
|
||||
capabilities: ["core"],
|
||||
},
|
||||
|
||||
"babel-preset-react-native": {
|
||||
name: "metro-react-native-babel-preset",
|
||||
version: "^${metroVersion}",
|
||||
devOnly: true,
|
||||
},
|
||||
metro: {
|
||||
name: "metro",
|
||||
version: "^${metroVersion}",
|
||||
devOnly: true,
|
||||
},
|
||||
"metro-config": {
|
||||
name: "metro-config",
|
||||
version: "^${metroVersion}",
|
||||
devOnly: true,
|
||||
},
|
||||
"metro-core": {
|
||||
name: "metro-core",
|
||||
version: "^${metroVersion}",
|
||||
devOnly: true,
|
||||
},
|
||||
"metro-react-native-babel-transformer": {
|
||||
name: "metro-react-native-babel-transformer",
|
||||
version: "^${metroVersion}",
|
||||
devOnly: true,
|
||||
},
|
||||
"metro-resolver": {
|
||||
name: "metro-resolver",
|
||||
version: "^${metroVersion}",
|
||||
devOnly: true,
|
||||
},
|
||||
"metro-runtime": {
|
||||
name: "metro-runtime",
|
||||
version: "^${metroVersion}",
|
||||
devOnly: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default profile;
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches package versions for specified react-native version.
|
||||
* @param {string} preset
|
||||
* @param {string} targetVersion
|
||||
* @param {Profile} latestProfile
|
||||
* @returns {Promise<string | undefined>}
|
||||
*/
|
||||
async function makeProfile(preset, targetVersion, latestProfile) {
|
||||
const reactNativeInfo = await fetchPackageInfo(
|
||||
latestProfile["core"],
|
||||
`^${targetVersion}.0-0`
|
||||
);
|
||||
if (!reactNativeInfo) {
|
||||
throw new Error(`Failed to get manifest of 'react-native@${targetVersion}`);
|
||||
}
|
||||
|
||||
const { dependencies, peerDependencies } = reactNativeInfo;
|
||||
if (!dependencies) {
|
||||
throw new Error(
|
||||
`Failed to get dependencies of 'react-native@${targetVersion}`
|
||||
);
|
||||
}
|
||||
if (!peerDependencies) {
|
||||
throw new Error(
|
||||
`Failed to get peer dependencies of 'react-native@${targetVersion}`
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch `metro` version from `@react-native-community/cli-plugin-metro` > `@react-native-community/cli`
|
||||
const cliMetroPluginDependencies = await [
|
||||
"@react-native-community/cli",
|
||||
"@react-native-community/cli-plugin-metro",
|
||||
].reduce(async (dependencies, packageName) => {
|
||||
try {
|
||||
const packageInfo = await pacote.manifest(packageName, {
|
||||
defaultTag: getPackageVersion(packageName, await dependencies),
|
||||
fullMetadata: true,
|
||||
});
|
||||
return packageInfo.dependencies;
|
||||
} catch (e) {
|
||||
if (e.code === "ETARGET") {
|
||||
// Some packages, such as `@react-native-community/cli`, are still in
|
||||
// alpha or beta while react-native RCs. Try again with the `next` tag.
|
||||
const packageInfo = await pacote.manifest(packageName, {
|
||||
defaultTag: "next",
|
||||
fullMetadata: true,
|
||||
});
|
||||
return packageInfo.dependencies;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}, Promise.resolve(dependencies));
|
||||
|
||||
return generateFromTemplate({
|
||||
preset,
|
||||
targetVersion,
|
||||
reactVersion: getPackageVersion("react", peerDependencies),
|
||||
metroVersion: getPackageVersion("metro", cliMetroPluginDependencies),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a table of all capabilities that resolve to a package, its current
|
||||
* version, and the latest available version.
|
||||
*
|
||||
* If `targetVersion` is specified, also generates a profile.
|
||||
*
|
||||
* Note that this script spawns a new process for each capability in parallel.
|
||||
* It currently does not honor throttling hints of any kind.
|
||||
*
|
||||
* @param {{ preset?: string; targetVersion?: string; force?: boolean; }} options
|
||||
*/
|
||||
async function main({
|
||||
preset: presetName = "microsoft",
|
||||
targetVersion = "",
|
||||
force,
|
||||
}) {
|
||||
const { preset } = await import(`../lib/presets/${presetName}/index.js`);
|
||||
const allVersions = /** @type {import("../src/types").ProfileVersion[]} */ (
|
||||
Object.keys(preset)
|
||||
.sort((lhs, rhs) => semverCompare(semverCoerce(lhs), semverCoerce(rhs)))
|
||||
.reverse()
|
||||
);
|
||||
|
||||
const latestProfile = preset[allVersions[0]];
|
||||
|
||||
if (targetVersion) {
|
||||
if (!force && preset[targetVersion]) {
|
||||
console.error(
|
||||
`Profile for '${targetVersion}' already exists. To overwrite it anyway, re-run with '--force'.`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
const newProfile = await makeProfile(
|
||||
presetName,
|
||||
targetVersion,
|
||||
latestProfile
|
||||
);
|
||||
if (newProfile) {
|
||||
const dst = getProfilePath(presetName, targetVersion);
|
||||
fs.writeFile(dst, newProfile).then(() => {
|
||||
console.log(`Wrote to '${dst}'`);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.distTags) {
|
||||
console.error(
|
||||
[
|
||||
e.message,
|
||||
"Available tags:",
|
||||
...Object.entries(e.distTags).map(
|
||||
([tag, version]) => ` - ${tag}: ${version}`
|
||||
),
|
||||
].join("\n")
|
||||
);
|
||||
} else {
|
||||
console.error(e);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const ignoredCapabilities = [
|
||||
"babel-preset-react-native",
|
||||
"core",
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"core-macos",
|
||||
"core-windows",
|
||||
"hermes",
|
||||
"metro",
|
||||
"metro-config",
|
||||
"metro-core",
|
||||
"metro-react-native-babel-transformer",
|
||||
"metro-resolver",
|
||||
"metro-runtime",
|
||||
"react",
|
||||
"react-dom",
|
||||
"react-test-renderer",
|
||||
];
|
||||
|
||||
/** @type {Record<string, PackageInfo>} */
|
||||
const delta = {};
|
||||
await Promise.all(
|
||||
Object.entries(latestProfile)
|
||||
.filter(([capability]) => {
|
||||
return !ignoredCapabilities.includes(capability);
|
||||
})
|
||||
.map(async ([capability, pkg]) => {
|
||||
await fetchPackageInfo(pkg).then((info) => {
|
||||
if (info) {
|
||||
delta[capability] = info;
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const table = markdownTable([
|
||||
["Capability", "Name", "Version", "Latest", "Homepage"],
|
||||
...Object.keys(delta)
|
||||
.sort()
|
||||
.map((capability) => {
|
||||
const { name, version, latest, homepage } = delta[capability];
|
||||
return [
|
||||
capability,
|
||||
name,
|
||||
version,
|
||||
version.endsWith(latest) ? "=" : latest,
|
||||
homepage,
|
||||
];
|
||||
}),
|
||||
]);
|
||||
console.log(table);
|
||||
}
|
||||
|
||||
const options = (() => {
|
||||
const options = {};
|
||||
process.argv.slice(2).forEach((arg) => {
|
||||
switch (arg) {
|
||||
case "--force":
|
||||
options.force = true;
|
||||
break;
|
||||
default:
|
||||
if (!/^\d+\.\d+$/.test(arg)) {
|
||||
console.error(
|
||||
`Expected version in the format '<major>.<minor>', got: ${arg}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
options.targetVersion = arg;
|
||||
break;
|
||||
}
|
||||
});
|
||||
return options;
|
||||
})();
|
||||
|
||||
main(options);
|
|
@ -1,78 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
// @ts-check
|
||||
|
||||
const fs = require("fs");
|
||||
const markdownTable = require("markdown-table");
|
||||
const { preset } = require("../lib/presets/microsoft");
|
||||
|
||||
const README = "README.md";
|
||||
const TOKEN_START = "<!-- @rnx-kit/dep-check/capabilities start -->";
|
||||
const TOKEN_END = "<!-- @rnx-kit/dep-check/capabilities end -->";
|
||||
|
||||
/**
|
||||
* Returns whether specified capability is a core capability.
|
||||
* @param capability {string}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isCoreCapability(capability) {
|
||||
return capability === "core" || capability.startsWith("core-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare function that places core capabilities first.
|
||||
* @param lhs {string}
|
||||
* @param rhs {string}
|
||||
* @returns {number}
|
||||
*/
|
||||
function sortCoreFirst(lhs, rhs) {
|
||||
if (isCoreCapability(lhs)) {
|
||||
if (!isCoreCapability(rhs)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (isCoreCapability(rhs)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lhs === rhs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return lhs < rhs ? -1 : 1;
|
||||
}
|
||||
|
||||
const allVersions = /** @type {import("../src/types").ProfileVersion[]} */ (
|
||||
Object.keys(preset).reverse()
|
||||
);
|
||||
const allCapabilities = /** @type {import("@rnx-kit/config").Capability[]} */ (
|
||||
Object.keys(preset[allVersions[0]]).sort(sortCoreFirst)
|
||||
);
|
||||
|
||||
const table = markdownTable([
|
||||
["Capability", ...allVersions],
|
||||
...allCapabilities.map((capability) => {
|
||||
return [
|
||||
capability,
|
||||
...allVersions.map((profileVersion) => {
|
||||
const pkg = preset[profileVersion][capability];
|
||||
if ("version" in pkg) {
|
||||
const { name, version } = pkg;
|
||||
return `${name}@${version}`;
|
||||
} else {
|
||||
return `Meta package for installing ${pkg.capabilities
|
||||
.map((name) => `\`${name}\``)
|
||||
.join(", ")}`;
|
||||
}
|
||||
}),
|
||||
];
|
||||
}),
|
||||
]);
|
||||
|
||||
const readme = fs.readFileSync(README, { encoding: "utf-8" });
|
||||
const updatedReadme = readme.replace(
|
||||
new RegExp(`${TOKEN_START}([^]+)${TOKEN_END}`),
|
||||
`${TOKEN_START}\n\n${table}\n\n${TOKEN_END}`
|
||||
);
|
||||
|
||||
if (updatedReadme !== readme) {
|
||||
fs.writeFileSync(README, updatedReadme);
|
||||
}
|
|
@ -6,7 +6,7 @@ import { diffLinesUnified } from "jest-diff";
|
|||
import path from "path";
|
||||
import { getRequirements } from "./dependencies";
|
||||
import { findBadPackages } from "./findBadPackages";
|
||||
import { modifyManifest } from "./helpers";
|
||||
import { modifyManifest, printMigrationMessage } from "./helpers";
|
||||
import { updatePackageManifest } from "./manifest";
|
||||
import { getProfilesFor, resolveCustomProfiles } from "./profiles";
|
||||
import type { CheckConfig, CheckOptions, Command } from "./types";
|
||||
|
@ -144,10 +144,14 @@ export function checkPackageManifest(
|
|||
const url = chalk.bold("https://aka.ms/dep-check");
|
||||
info(`Visit ${url} for more information about dep-check.`);
|
||||
|
||||
printMigrationMessage();
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printMigrationMessage();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { warn } from "@rnx-kit/console";
|
||||
import type { PackageManifest } from "@rnx-kit/tools-node/package";
|
||||
import { writePackage } from "@rnx-kit/tools-node/package";
|
||||
import detectIndent from "detect-indent";
|
||||
|
@ -40,3 +41,18 @@ export function omitEmptySections(manifest: PackageManifest): PackageManifest {
|
|||
}
|
||||
return manifest;
|
||||
}
|
||||
|
||||
export function printMigrationMessage(): void {
|
||||
const banner =
|
||||
"⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️";
|
||||
|
||||
warn(banner);
|
||||
warn("'@rnx-kit/dep-check' has been renamed to '@rnx-kit/align-deps'!");
|
||||
warn(
|
||||
"You can replace '@rnx-kit/dep-check' with '@rnx-kit/align-deps' in your 'package.json' and your configurations will be automatically upgraded."
|
||||
);
|
||||
warn(
|
||||
"For reasoning and more details, you can read the RFC: https://github.com/microsoft/rnx-kit/pull/1757"
|
||||
);
|
||||
warn(banner);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { readPackage } from "@rnx-kit/tools-node/package";
|
||||
import { capabilitiesFor } from "./capabilities";
|
||||
import { modifyManifest } from "./helpers";
|
||||
import { modifyManifest, printMigrationMessage } from "./helpers";
|
||||
import type { CapabilitiesOptions } from "./types";
|
||||
|
||||
export function initializeConfig(
|
||||
|
@ -28,4 +28,6 @@ export function initializeConfig(
|
|||
},
|
||||
};
|
||||
modifyManifest(packageManifest, updatedManifest);
|
||||
|
||||
printMigrationMessage();
|
||||
}
|
||||
|
|
14
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/conan/package.json
сгенерированный
поставляемый
14
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/conan/package.json
сгенерированный
поставляемый
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"name": "conan",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"t-800": "1.0.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios"
|
||||
]
|
||||
}
|
||||
}
|
16
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/dutch/package.json
сгенерированный
поставляемый
16
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/dutch/package.json
сгенерированный
поставляемый
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "dutch",
|
||||
"version": "1.0.0",
|
||||
"peerDependencies": {
|
||||
"react": "17.0.1",
|
||||
"react-native": "0.64.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"netinfo"
|
||||
]
|
||||
}
|
||||
}
|
15
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/john/package.json
сгенерированный
поставляемый
15
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/john/package.json
сгенерированный
поставляемый
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "john",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"dutch": "1.0.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"storage"
|
||||
]
|
||||
}
|
||||
}
|
16
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/quaid/package.json
сгенерированный
поставляемый
16
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/quaid/package.json
сгенерированный
поставляемый
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "quaid",
|
||||
"version": "1.0.0",
|
||||
"peerDependencies": {
|
||||
"react": "17.0.1",
|
||||
"react-native": "0.64.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"webview"
|
||||
]
|
||||
}
|
||||
}
|
7
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/react-native/package.json
сгенерированный
поставляемый
7
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/react-native/package.json
сгенерированный
поставляемый
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"name": "react-native",
|
||||
"version": "0.64.0",
|
||||
"dependencies": {
|
||||
"react": "17.0.1"
|
||||
}
|
||||
}
|
4
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/react/package.json
сгенерированный
поставляемый
4
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/react/package.json
сгенерированный
поставляемый
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"name": "react",
|
||||
"version": "17.0.1"
|
||||
}
|
18
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/t-800/package.json
сгенерированный
поставляемый
18
packages/dep-check/test/__fixtures__/awesome-repo-extended/node_modules/t-800/package.json
сгенерированный
поставляемый
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"name": "t-800",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"john": "1.0.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"animation",
|
||||
"cyberdyne",
|
||||
"skynet",
|
||||
"test-app"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"name": "awesome-repo-extended",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"conan": "1.0.0",
|
||||
"quaid": "1.0.0",
|
||||
"react": "17.0.1",
|
||||
"react-native": "0.64.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"kitType": "app",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"hermes",
|
||||
"lazy-index"
|
||||
]
|
||||
}
|
||||
}
|
14
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/conan/package.json
сгенерированный
поставляемый
14
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/conan/package.json
сгенерированный
поставляемый
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"name": "conan",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"t-800": "1.0.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios"
|
||||
]
|
||||
}
|
||||
}
|
16
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/dutch/package.json
сгенерированный
поставляемый
16
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/dutch/package.json
сгенерированный
поставляемый
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "dutch",
|
||||
"version": "1.0.0",
|
||||
"peerDependencies": {
|
||||
"react": "17.0.1",
|
||||
"react-native": "0.64.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"netinfo"
|
||||
]
|
||||
}
|
||||
}
|
15
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/john/package.json
сгенерированный
поставляемый
15
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/john/package.json
сгенерированный
поставляемый
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "john",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"dutch": "1.0.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"storage"
|
||||
]
|
||||
}
|
||||
}
|
16
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/quaid/package.json
сгенерированный
поставляемый
16
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/quaid/package.json
сгенерированный
поставляемый
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "quaid",
|
||||
"version": "1.0.0",
|
||||
"peerDependencies": {
|
||||
"react": "17.0.1",
|
||||
"react-native": "0.64.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"webview"
|
||||
]
|
||||
}
|
||||
}
|
7
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/react-native/package.json
сгенерированный
поставляемый
7
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/react-native/package.json
сгенерированный
поставляемый
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"name": "react-native",
|
||||
"version": "0.64.0",
|
||||
"dependencies": {
|
||||
"react": "17.0.1"
|
||||
}
|
||||
}
|
4
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/react/package.json
сгенерированный
поставляемый
4
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/react/package.json
сгенерированный
поставляемый
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"name": "react",
|
||||
"version": "17.0.1"
|
||||
}
|
16
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/t-800/package.json
сгенерированный
поставляемый
16
packages/dep-check/test/__fixtures__/awesome-repo/node_modules/t-800/package.json
сгенерированный
поставляемый
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "t-800",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"john": "1.0.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"animation",
|
||||
"test-app"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"name": "awesome-repo",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"conan": "1.0.0",
|
||||
"quaid": "1.0.0",
|
||||
"react": "17.0.1",
|
||||
"react-native": "0.64.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"kitType": "app",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"hermes",
|
||||
"lazy-index"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
module.exports = {
|
||||
0.64: {
|
||||
core: {
|
||||
name: "react-native",
|
||||
version: "0.64.3",
|
||||
},
|
||||
react: {
|
||||
name: "react",
|
||||
version: "17.0.2",
|
||||
},
|
||||
},
|
||||
0.65: {
|
||||
core: {
|
||||
name: "react-native",
|
||||
version: "0.65.2",
|
||||
},
|
||||
react: {
|
||||
name: "react",
|
||||
version: "17.0.2",
|
||||
},
|
||||
},
|
||||
};
|
0
packages/dep-check/test/__fixtures__/custom-profiles/node_modules/custom-profiles-package/index.js
сгенерированный
поставляемый
0
packages/dep-check/test/__fixtures__/custom-profiles/node_modules/custom-profiles-package/index.js
сгенерированный
поставляемый
5
packages/dep-check/test/__fixtures__/custom-profiles/node_modules/custom-profiles-package/package.json
сгенерированный
поставляемый
5
packages/dep-check/test/__fixtures__/custom-profiles/node_modules/custom-profiles-package/package.json
сгенерированный
поставляемый
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"name": "custom-profiles-package",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js"
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
module.exports = {
|
||||
format: {
|
||||
name: "prettier",
|
||||
version: "^2.5.1",
|
||||
devOnly: true,
|
||||
},
|
||||
0.66: {
|
||||
test: {
|
||||
name: "jest",
|
||||
version: "26.0",
|
||||
devOnly: true,
|
||||
},
|
||||
},
|
||||
0.67: {
|
||||
format: {
|
||||
name: "prettier",
|
||||
version: "3.0",
|
||||
devOnly: true,
|
||||
},
|
||||
test: {
|
||||
name: "jest",
|
||||
version: "27.0",
|
||||
devOnly: true,
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
module.exports = {
|
||||
0.65: {
|
||||
format: {
|
||||
name: "prettier",
|
||||
version: "^2.5.1",
|
||||
devOnly: true,
|
||||
},
|
||||
},
|
||||
0.66: {
|
||||
format: {
|
||||
name: "prettier",
|
||||
version: "^2.5.1",
|
||||
devOnly: true,
|
||||
},
|
||||
},
|
||||
0.67: {
|
||||
format: {
|
||||
name: "prettier",
|
||||
version: "^2.5.1",
|
||||
devOnly: true,
|
||||
},
|
||||
},
|
||||
};
|
17
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/conan/package.json
сгенерированный
поставляемый
17
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/conan/package.json
сгенерированный
поставляемый
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"name": "conan",
|
||||
"version": "1.0.0",
|
||||
"peerDependencies": {
|
||||
"react-native": "^0.63.2 || ^0.64.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-native": "^0.63.2"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63 || ^0.64",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios"
|
||||
]
|
||||
}
|
||||
}
|
7
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/react-native/package.json
сгенерированный
поставляемый
7
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/react-native/package.json
сгенерированный
поставляемый
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"name": "react-native",
|
||||
"version": "0.64.2",
|
||||
"dependencies": {
|
||||
"react": "17.0.1"
|
||||
}
|
||||
}
|
4
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/react/package.json
сгенерированный
поставляемый
4
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/react/package.json
сгенерированный
поставляемый
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"name": "react",
|
||||
"version": "17.0.1"
|
||||
}
|
17
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/t-800/package.json
сгенерированный
поставляемый
17
packages/dep-check/test/__fixtures__/no-profile-satisfying-deps/node_modules/t-800/package.json
сгенерированный
поставляемый
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"name": "t-800",
|
||||
"version": "1.0.0",
|
||||
"peerDependencies": {
|
||||
"react-native": "^0.63.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-native": "^0.63.2"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.63",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"name": "no-profile-satisfying-deps",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"conan": "1.0.0",
|
||||
"react": "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
"t-800": "1.0.0"
|
||||
},
|
||||
"rnx-kit": {
|
||||
"reactNativeVersion": "^0.64",
|
||||
"kitType": "app",
|
||||
"capabilities": [
|
||||
"core-android",
|
||||
"core-ios"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
const rnxKitConfig = jest.createMockFromModule("@rnx-kit/config");
|
||||
const actualKitConfig = jest.requireActual("@rnx-kit/config");
|
||||
|
||||
let kitConfig = "";
|
||||
|
||||
rnxKitConfig.__setMockConfig = (config) => {
|
||||
kitConfig = config;
|
||||
};
|
||||
|
||||
rnxKitConfig.getKitCapabilities = actualKitConfig.getKitCapabilities;
|
||||
rnxKitConfig.getKitConfig = () => kitConfig;
|
||||
|
||||
module.exports = rnxKitConfig;
|
|
@ -1,16 +0,0 @@
|
|||
const chalk = jest.createMockFromModule("chalk");
|
||||
|
||||
function passthrough(s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
chalk.bold = passthrough;
|
||||
chalk.cyan = passthrough;
|
||||
chalk.cyan.bold = passthrough;
|
||||
chalk.dim = passthrough;
|
||||
chalk.green = passthrough;
|
||||
chalk.red = passthrough;
|
||||
chalk.red.bold = passthrough;
|
||||
chalk.yellow = passthrough;
|
||||
|
||||
module.exports = chalk;
|
|
@ -1,19 +0,0 @@
|
|||
const fs = jest.createMockFromModule("fs");
|
||||
const actualFs = jest.requireActual("fs");
|
||||
|
||||
let data = "";
|
||||
|
||||
fs.__setMockContent = (content, space = 2) => {
|
||||
data = JSON.stringify(content, undefined, space) + "\n";
|
||||
};
|
||||
|
||||
fs.__setMockFileWriter = (writer) => {
|
||||
fs.writeFileSync = writer;
|
||||
};
|
||||
|
||||
fs.lstatSync = (...args) => actualFs.lstatSync(...args);
|
||||
fs.readFileSync = (...args) => data || actualFs.readFileSync(...args);
|
||||
fs.statSync = actualFs.statSync; // used by cosmiconfig
|
||||
fs.writeFileSync = undefined;
|
||||
|
||||
module.exports = fs;
|
|
@ -1,31 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`checkPackageManifest({ kitType: 'app' }) adds required dependencies 1`] = `
|
||||
"{
|
||||
\\"name\\": \\"awesome-repo\\",
|
||||
\\"version\\": \\"1.0.0\\",
|
||||
\\"dependencies\\": {
|
||||
\\"@react-native-async-storage/async-storage\\": \\"^1.15.8\\",
|
||||
\\"@react-native-community/async-storage\\": \\"^1.12.1\\",
|
||||
\\"@react-native-community/netinfo\\": \\"^6.0.2\\",
|
||||
\\"conan\\": \\"1.0.0\\",
|
||||
\\"hermes-engine\\": \\"~0.7.0\\",
|
||||
\\"quaid\\": \\"1.0.0\\",
|
||||
\\"react\\": \\"17.0.1\\",
|
||||
\\"react-native\\": \\"^0.64.2\\",
|
||||
\\"react-native-lazy-index\\": \\"^2.1.1\\",
|
||||
\\"react-native-reanimated\\": \\"^2.1.0\\",
|
||||
\\"react-native-webview\\": \\"^11.4.2\\"
|
||||
},
|
||||
\\"rnx-kit\\": {
|
||||
\\"reactNativeVersion\\": \\"^0.63 || ^0.64\\",
|
||||
\\"kitType\\": \\"app\\",
|
||||
\\"capabilities\\": [
|
||||
\\"core-android\\",
|
||||
\\"hermes\\",
|
||||
\\"lazy-index\\"
|
||||
]
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
|
@ -1,37 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`checkPackageManifest({ kitType: 'library' }) preserves indentation in 'package.json' 1`] = `
|
||||
"{
|
||||
\\"name\\": \\"@rnx-kit/dep-check\\",
|
||||
\\"version\\": \\"0.0.1\\",
|
||||
\\"peerDependencies\\": {
|
||||
\\"react\\": \\"17.0.1\\",
|
||||
\\"react-native\\": \\"^0.64.2\\"
|
||||
},
|
||||
\\"devDependencies\\": {
|
||||
\\"react\\": \\"17.0.1\\",
|
||||
\\"react-native\\": \\"^0.64.2\\"
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`checkPackageManifest({ kitType: 'library' }) prints warnings when detecting bad packages (with version range) 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
"warn",
|
||||
"Known bad packages are found in '@rnx-kit/dep-check':
|
||||
react-native-linear-gradient@<2.6.0: This package causes significant degradation in app start up time prior to 2.6.0.",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`checkPackageManifest({ kitType: 'library' }) prints warnings when detecting bad packages 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
"warn",
|
||||
"Known bad packages are found in '@rnx-kit/dep-check':
|
||||
react-native-linear-gradient@<2.6.0: This package causes significant degradation in app start up time prior to 2.6.0.",
|
||||
],
|
||||
]
|
||||
`;
|
|
@ -1,112 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`loadCustomProfiles() loads valid custom profiles 1`] = `
|
||||
Object {
|
||||
"0.65": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.66": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.67": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`loadCustomProfiles() prepends root-level capabilities to all profiles 1`] = `
|
||||
Object {
|
||||
"0.61": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.62": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.63": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.64": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.65": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.66": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
"test": Object {
|
||||
"devOnly": true,
|
||||
"name": "jest",
|
||||
"version": "26.0",
|
||||
},
|
||||
},
|
||||
"0.67": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "3.0",
|
||||
},
|
||||
"test": Object {
|
||||
"devOnly": true,
|
||||
"name": "jest",
|
||||
"version": "27.0",
|
||||
},
|
||||
},
|
||||
"0.68": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.69": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
"0.70": Object {
|
||||
"format": Object {
|
||||
"devOnly": true,
|
||||
"name": "prettier",
|
||||
"version": "^2.5.1",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
|
@ -1,249 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`buildManifestProfile() builds a package manifest for a single profile version 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
"@react-native-async-storage/async-storage": "^1.15.8",
|
||||
"@react-native-clipboard/clipboard": "^1.8.3",
|
||||
"@react-native-community/checkbox": "^0.5.8",
|
||||
"@react-native-community/datetimepicker": "^3.4.6",
|
||||
"@react-native-community/hooks": "^2.6.0",
|
||||
"@react-native-community/netinfo": "^6.0.2",
|
||||
"@react-native-masked-view/masked-view": "^0.2.4",
|
||||
"@react-navigation/native": "^5.9.8",
|
||||
"@react-navigation/stack": "^5.14.9",
|
||||
"hermes-engine": "~0.7.0",
|
||||
"jest": "^26.5.2",
|
||||
"metro": "^0.64.0",
|
||||
"metro-config": "^0.64.0",
|
||||
"metro-core": "^0.64.0",
|
||||
"metro-react-native-babel-preset": "^0.64.0",
|
||||
"metro-react-native-babel-transformer": "^0.64.0",
|
||||
"metro-resolver": "^0.64.0",
|
||||
"metro-runtime": "^0.64.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
"react-native-base64": "^0.2.1",
|
||||
"react-native-floating-action": "^1.21.0",
|
||||
"react-native-fs": "^2.17.0",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-lazy-index": "^2.1.1",
|
||||
"react-native-macos": "^0.64.0",
|
||||
"react-native-modal": "^11.10.0",
|
||||
"react-native-popover-view": "^4.0.3",
|
||||
"react-native-reanimated": "^2.1.0",
|
||||
"react-native-render-html": "^5.1.1",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.1.1",
|
||||
"react-native-shimmer": "^0.5.0",
|
||||
"react-native-sqlite-storage": "^5.0.0",
|
||||
"react-native-svg": "^12.1.1",
|
||||
"react-native-test-app": "^0.11.4",
|
||||
"react-native-webview": "^11.4.2",
|
||||
"react-native-windows": "^0.64.0",
|
||||
"react-test-renderer": "17.0.1",
|
||||
},
|
||||
"devDependencies": Object {
|
||||
"@react-native-async-storage/async-storage": "^1.15.8",
|
||||
"@react-native-clipboard/clipboard": "^1.8.3",
|
||||
"@react-native-community/checkbox": "^0.5.8",
|
||||
"@react-native-community/datetimepicker": "^3.4.6",
|
||||
"@react-native-community/hooks": "^2.6.0",
|
||||
"@react-native-community/netinfo": "^6.0.2",
|
||||
"@react-native-masked-view/masked-view": "^0.2.4",
|
||||
"@react-navigation/native": "^5.9.8",
|
||||
"@react-navigation/stack": "^5.14.9",
|
||||
"hermes-engine": "~0.7.0",
|
||||
"jest": "^26.5.2",
|
||||
"metro": "^0.64.0",
|
||||
"metro-config": "^0.64.0",
|
||||
"metro-core": "^0.64.0",
|
||||
"metro-react-native-babel-preset": "^0.64.0",
|
||||
"metro-react-native-babel-transformer": "^0.64.0",
|
||||
"metro-resolver": "^0.64.0",
|
||||
"metro-runtime": "^0.64.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
"react-native-base64": "^0.2.1",
|
||||
"react-native-floating-action": "^1.21.0",
|
||||
"react-native-fs": "^2.17.0",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-lazy-index": "^2.1.1",
|
||||
"react-native-macos": "^0.64.0",
|
||||
"react-native-modal": "^11.10.0",
|
||||
"react-native-popover-view": "^4.0.3",
|
||||
"react-native-reanimated": "^2.1.0",
|
||||
"react-native-render-html": "^5.1.1",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.1.1",
|
||||
"react-native-shimmer": "^0.5.0",
|
||||
"react-native-sqlite-storage": "^5.0.0",
|
||||
"react-native-svg": "^12.1.1",
|
||||
"react-native-test-app": "^0.11.4",
|
||||
"react-native-webview": "^11.4.2",
|
||||
"react-native-windows": "^0.64.0",
|
||||
"react-test-renderer": "17.0.1",
|
||||
},
|
||||
"name": "@rnx-kit/dep-check",
|
||||
"peerDependencies": Object {
|
||||
"@react-native-async-storage/async-storage": "^1.15.8",
|
||||
"@react-native-clipboard/clipboard": "^1.8.3",
|
||||
"@react-native-community/checkbox": "^0.5.8",
|
||||
"@react-native-community/datetimepicker": "^3.4.6",
|
||||
"@react-native-community/hooks": "^2.6.0",
|
||||
"@react-native-community/netinfo": "^6.0.2",
|
||||
"@react-native-masked-view/masked-view": "^0.2.4",
|
||||
"@react-navigation/native": "^5.9.8",
|
||||
"@react-navigation/stack": "^5.14.9",
|
||||
"hermes-engine": "~0.7.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
"react-native-base64": "^0.2.1",
|
||||
"react-native-floating-action": "^1.21.0",
|
||||
"react-native-fs": "^2.17.0",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-lazy-index": "^2.1.1",
|
||||
"react-native-macos": "^0.64.0",
|
||||
"react-native-modal": "^11.10.0",
|
||||
"react-native-popover-view": "^4.0.3",
|
||||
"react-native-reanimated": "^2.1.0",
|
||||
"react-native-render-html": "^5.1.1",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.1.1",
|
||||
"react-native-shimmer": "^0.5.0",
|
||||
"react-native-sqlite-storage": "^5.0.0",
|
||||
"react-native-svg": "^12.1.1",
|
||||
"react-native-webview": "^11.4.2",
|
||||
"react-native-windows": "^0.64.0",
|
||||
},
|
||||
"version": "1.0.0-test",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`buildManifestProfile() builds a package manifest for multiple profile versions 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
"@react-native-async-storage/async-storage": "^1.15.8",
|
||||
"@react-native-clipboard/clipboard": "^1.8.3",
|
||||
"@react-native-community/checkbox": "^0.5.8",
|
||||
"@react-native-community/datetimepicker": "^3.4.6",
|
||||
"@react-native-community/hooks": "^2.6.0",
|
||||
"@react-native-community/netinfo": "^6.0.2",
|
||||
"@react-native-masked-view/masked-view": "^0.2.4",
|
||||
"@react-navigation/native": "^5.9.8",
|
||||
"@react-navigation/stack": "^5.14.9",
|
||||
"hermes-engine": "~0.7.0",
|
||||
"jest": "^26.5.2",
|
||||
"metro": "^0.64.0",
|
||||
"metro-config": "^0.64.0",
|
||||
"metro-core": "^0.64.0",
|
||||
"metro-react-native-babel-preset": "^0.64.0",
|
||||
"metro-react-native-babel-transformer": "^0.64.0",
|
||||
"metro-resolver": "^0.64.0",
|
||||
"metro-runtime": "^0.64.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
"react-native-base64": "^0.2.1",
|
||||
"react-native-floating-action": "^1.21.0",
|
||||
"react-native-fs": "^2.17.0",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-lazy-index": "^2.1.1",
|
||||
"react-native-macos": "^0.64.0",
|
||||
"react-native-modal": "^11.10.0",
|
||||
"react-native-popover-view": "^4.0.3",
|
||||
"react-native-reanimated": "^2.1.0",
|
||||
"react-native-render-html": "^5.1.1",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.1.1",
|
||||
"react-native-shimmer": "^0.5.0",
|
||||
"react-native-sqlite-storage": "^5.0.0",
|
||||
"react-native-svg": "^12.1.1",
|
||||
"react-native-test-app": "^0.11.4",
|
||||
"react-native-webview": "^11.4.2",
|
||||
"react-native-windows": "^0.64.0",
|
||||
"react-test-renderer": "17.0.1",
|
||||
},
|
||||
"devDependencies": Object {
|
||||
"@react-native-async-storage/async-storage": "^1.15.8",
|
||||
"@react-native-clipboard/clipboard": "^1.8.3",
|
||||
"@react-native-community/checkbox": "^0.5.8",
|
||||
"@react-native-community/datetimepicker": "^3.4.6",
|
||||
"@react-native-community/hooks": "^2.6.0",
|
||||
"@react-native-community/netinfo": "^6.0.2",
|
||||
"@react-native-masked-view/masked-view": "^0.2.4",
|
||||
"@react-navigation/native": "^5.9.8",
|
||||
"@react-navigation/stack": "^5.14.9",
|
||||
"hermes-engine": "~0.7.0",
|
||||
"jest": "^26.5.2",
|
||||
"metro": "^0.64.0",
|
||||
"metro-config": "^0.64.0",
|
||||
"metro-core": "^0.64.0",
|
||||
"metro-react-native-babel-preset": "^0.64.0",
|
||||
"metro-react-native-babel-transformer": "^0.64.0",
|
||||
"metro-resolver": "^0.64.0",
|
||||
"metro-runtime": "^0.64.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
"react-native-base64": "^0.2.1",
|
||||
"react-native-floating-action": "^1.21.0",
|
||||
"react-native-fs": "^2.17.0",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-lazy-index": "^2.1.1",
|
||||
"react-native-macos": "^0.64.0",
|
||||
"react-native-modal": "^11.10.0",
|
||||
"react-native-popover-view": "^4.0.3",
|
||||
"react-native-reanimated": "^2.1.0",
|
||||
"react-native-render-html": "^5.1.1",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.1.1",
|
||||
"react-native-shimmer": "^0.5.0",
|
||||
"react-native-sqlite-storage": "^5.0.0",
|
||||
"react-native-svg": "^12.1.1",
|
||||
"react-native-test-app": "^0.11.4",
|
||||
"react-native-webview": "^11.4.2",
|
||||
"react-native-windows": "^0.64.0",
|
||||
"react-test-renderer": "17.0.1",
|
||||
},
|
||||
"name": "@rnx-kit/dep-check",
|
||||
"peerDependencies": Object {
|
||||
"@react-native-async-storage/async-storage": "^1.15.8",
|
||||
"@react-native-clipboard/clipboard": "^1.8.3",
|
||||
"@react-native-community/async-storage": "^1.12.1",
|
||||
"@react-native-community/checkbox": "^0.5.7 || ^0.5.8",
|
||||
"@react-native-community/clipboard": "^1.5.1",
|
||||
"@react-native-community/datetimepicker": "^3.0.9 || ^3.4.6",
|
||||
"@react-native-community/hooks": "^2.6.0",
|
||||
"@react-native-community/netinfo": "^5.9.10 || ^6.0.2",
|
||||
"@react-native-masked-view/masked-view": "^0.2.4",
|
||||
"@react-navigation/native": "^5.9.4 || ^5.9.8",
|
||||
"@react-navigation/stack": "^5.14.4 || ^5.14.9",
|
||||
"hermes-engine": "~0.5.0 || ~0.7.0",
|
||||
"react": "16.13.1 || 17.0.1",
|
||||
"react-dom": "16.13.1 || 17.0.1",
|
||||
"react-native": "^0.63.2 || ^0.64.2",
|
||||
"react-native-base64": "^0.2.1",
|
||||
"react-native-floating-action": "^1.21.0",
|
||||
"react-native-fs": "^2.16.6 || ^2.17.0",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-lazy-index": "^2.1.1",
|
||||
"react-native-macos": "^0.63.0 || ^0.64.0",
|
||||
"react-native-modal": "^11.5.6 || ^11.10.0",
|
||||
"react-native-popover-view": "^3.1.1 || ^4.0.3",
|
||||
"react-native-reanimated": "^1.13.3 || ^2.1.0",
|
||||
"react-native-render-html": "^5.1.0 || ^5.1.1",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^2.18.1 || ^3.1.1",
|
||||
"react-native-shimmer": "^0.5.0",
|
||||
"react-native-sqlite-storage": "^3.3.11 || ^5.0.0",
|
||||
"react-native-svg": "^12.1.1",
|
||||
"react-native-webview": "^11.4.2",
|
||||
"react-native-windows": "^0.63.0 || ^0.64.0",
|
||||
},
|
||||
"version": "1.0.0-test",
|
||||
}
|
||||
`;
|
|
@ -1,276 +0,0 @@
|
|||
import type { Capability } from "@rnx-kit/config";
|
||||
import { capabilitiesFor, resolveCapabilities } from "../src/capabilities";
|
||||
import profile_0_62 from "../src/presets/microsoft/profile-0.62";
|
||||
import profile_0_63 from "../src/presets/microsoft/profile-0.63";
|
||||
import profile_0_64 from "../src/presets/microsoft/profile-0.64";
|
||||
import { getProfilesFor } from "../src/profiles";
|
||||
import { pickPackage } from "./helpers";
|
||||
|
||||
describe("capabilitiesFor()", () => {
|
||||
test("returns `undefined` when react-native is not a dependency", () => {
|
||||
expect(
|
||||
capabilitiesFor({ name: "@rnx-kit/dep-check", version: "1.0.0" })
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
capabilitiesFor({
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
react: "^17.0.1",
|
||||
},
|
||||
})
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
test("returns capabilities when react-native is under dependencies", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"react-native": "^0.64.1",
|
||||
},
|
||||
};
|
||||
expect(capabilitiesFor(manifest)).toEqual({
|
||||
reactNativeVersion: "^0.64",
|
||||
reactNativeDevVersion: "0.64.0",
|
||||
kitType: "library",
|
||||
capabilities: ["core", "core-android", "core-ios"],
|
||||
});
|
||||
});
|
||||
|
||||
test("returns capabilities when react-native is under peerDependencies", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
peerDependencies: {
|
||||
"react-native": "^0.64.1",
|
||||
},
|
||||
};
|
||||
expect(capabilitiesFor(manifest)).toEqual({
|
||||
reactNativeVersion: "^0.64",
|
||||
reactNativeDevVersion: "0.64.0",
|
||||
kitType: "library",
|
||||
capabilities: ["core", "core-android", "core-ios"],
|
||||
});
|
||||
});
|
||||
|
||||
test("returns capabilities when react-native is under devDependencies", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
devDependencies: {
|
||||
"react-native": "^0.64.1",
|
||||
},
|
||||
};
|
||||
expect(capabilitiesFor(manifest)).toEqual({
|
||||
reactNativeVersion: "^0.64",
|
||||
reactNativeDevVersion: "^0.64.1",
|
||||
kitType: "library",
|
||||
capabilities: ["core", "core-android", "core-ios"],
|
||||
});
|
||||
});
|
||||
|
||||
test("returns kit config with app type instead of dev version", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
peerDependencies: {
|
||||
"react-native": "^0.64.1",
|
||||
},
|
||||
};
|
||||
expect(capabilitiesFor(manifest, { kitType: "app" })).toEqual({
|
||||
reactNativeVersion: "^0.64",
|
||||
kitType: "app",
|
||||
capabilities: ["core", "core-android", "core-ios"],
|
||||
});
|
||||
});
|
||||
|
||||
test("ignores packages that are not managed by dep-check", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
peerDependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "^0.64.1",
|
||||
},
|
||||
devDependencies: {
|
||||
"@rnx-kit/babel-preset-metro-react-native": "*",
|
||||
"@rnx-kit/cli": "*",
|
||||
},
|
||||
};
|
||||
expect(capabilitiesFor(manifest, { kitType: "app" })).toEqual({
|
||||
reactNativeVersion: "^0.64",
|
||||
kitType: "app",
|
||||
capabilities: ["core", "core-android", "core-ios", "react"],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveCapabilities()", () => {
|
||||
const consoleWarnSpy = jest.spyOn(global.console, "warn");
|
||||
|
||||
beforeEach(() => {
|
||||
consoleWarnSpy.mockReset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("dedupes packages", () => {
|
||||
const packages = resolveCapabilities(
|
||||
["core", "core", "test-app"],
|
||||
[profile_0_64]
|
||||
);
|
||||
|
||||
const { name } = profile_0_64["core"];
|
||||
const { name: reactName } = profile_0_64["react"];
|
||||
const { name: testAppName } = profile_0_64["test-app"];
|
||||
expect(packages).toEqual({
|
||||
[name]: [profile_0_64["core"]],
|
||||
[reactName]: [profile_0_64["react"]],
|
||||
[testAppName]: [profile_0_64["test-app"]],
|
||||
});
|
||||
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("dedupes package versions", () => {
|
||||
const packages = resolveCapabilities(
|
||||
["webview"],
|
||||
[profile_0_62, profile_0_63, profile_0_64]
|
||||
);
|
||||
|
||||
const { name } = profile_0_64["webview"];
|
||||
expect(packages).toEqual({
|
||||
[name]: [profile_0_62["webview"], profile_0_64["webview"]],
|
||||
});
|
||||
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("ignores missing/unknown capabilities", () => {
|
||||
const packages = resolveCapabilities(
|
||||
["skynet" as Capability, "svg"],
|
||||
[profile_0_62, profile_0_63, profile_0_64]
|
||||
);
|
||||
|
||||
const { name } = profile_0_64["svg"];
|
||||
expect(packages).toEqual({ [name]: [profile_0_64["svg"]] });
|
||||
expect(consoleWarnSpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test("resolves custom capabilities", () => {
|
||||
const skynet = { name: "skynet", version: "1.0.0" };
|
||||
jest.mock(
|
||||
"mock-custom-profiles-module",
|
||||
() => ({ "0.62": { [skynet.name]: skynet } }),
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
const profiles = getProfilesFor(
|
||||
"^0.62 || ^0.63 || ^0.64",
|
||||
"mock-custom-profiles-module"
|
||||
);
|
||||
|
||||
const packages = resolveCapabilities(
|
||||
["skynet" as Capability, "svg"],
|
||||
profiles
|
||||
);
|
||||
|
||||
const { name } = profile_0_64["svg"];
|
||||
expect(packages).toEqual({
|
||||
[name]: [profile_0_64["svg"]],
|
||||
[skynet.name]: [skynet],
|
||||
});
|
||||
});
|
||||
|
||||
test("resolves capabilities required by capabilities", () => {
|
||||
const packages = resolveCapabilities(
|
||||
["core-windows"],
|
||||
[profile_0_63, profile_0_64]
|
||||
);
|
||||
|
||||
expect(packages).toEqual({
|
||||
react: [
|
||||
pickPackage(profile_0_63, "react"),
|
||||
pickPackage(profile_0_64, "react"),
|
||||
],
|
||||
"react-native": [
|
||||
pickPackage(profile_0_63, "core"),
|
||||
pickPackage(profile_0_64, "core"),
|
||||
],
|
||||
"react-native-windows": [
|
||||
pickPackage(profile_0_63, "core-windows"),
|
||||
pickPackage(profile_0_64, "core-windows"),
|
||||
],
|
||||
});
|
||||
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("resolves meta packages", () => {
|
||||
jest.mock(
|
||||
"mock-meta-package",
|
||||
() => ({
|
||||
"0.64": {
|
||||
"core/all": {
|
||||
name: "#meta",
|
||||
capabilities: [
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"core-macos",
|
||||
"core-windows",
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
const packages = resolveCapabilities(
|
||||
["core/all" as Capability],
|
||||
getProfilesFor("^0.64", "mock-meta-package")
|
||||
);
|
||||
|
||||
expect(packages).toEqual({
|
||||
react: [pickPackage(profile_0_64, "react")],
|
||||
"react-native": [pickPackage(profile_0_64, "core")],
|
||||
"react-native-macos": [pickPackage(profile_0_64, "core-macos")],
|
||||
"react-native-windows": [pickPackage(profile_0_64, "core-windows")],
|
||||
});
|
||||
});
|
||||
|
||||
test("resolves meta packages with loops", () => {
|
||||
jest.mock(
|
||||
"mock-meta-package-loop",
|
||||
() => ({
|
||||
"0.64": {
|
||||
connor: {
|
||||
name: "#meta",
|
||||
capabilities: ["core", "reese"],
|
||||
},
|
||||
reese: {
|
||||
name: "#meta",
|
||||
capabilities: ["t-800"],
|
||||
},
|
||||
"t-800": {
|
||||
name: "#meta",
|
||||
capabilities: ["connor"],
|
||||
},
|
||||
},
|
||||
}),
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
const packages = resolveCapabilities(
|
||||
["reese" as Capability],
|
||||
getProfilesFor("^0.64", "mock-meta-package-loop")
|
||||
);
|
||||
|
||||
expect(packages).toEqual({
|
||||
react: [pickPackage(profile_0_64, "react")],
|
||||
"react-native": [pickPackage(profile_0_64, "core")],
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,40 +0,0 @@
|
|||
import path from "path";
|
||||
import { checkPackageManifest } from "../src/check";
|
||||
|
||||
jest.mock("fs");
|
||||
jest.unmock("@rnx-kit/config");
|
||||
|
||||
function fixturePath(name: string) {
|
||||
return path.join(process.cwd(), "test", "__fixtures__", name);
|
||||
}
|
||||
|
||||
describe("checkPackageManifest({ kitType: 'app' })", () => {
|
||||
const fs = require("fs");
|
||||
const consoleWarnSpy = jest.spyOn(global.console, "warn");
|
||||
|
||||
beforeEach(() => {
|
||||
consoleWarnSpy.mockReset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("adds required dependencies", () => {
|
||||
const manifestPath = path.join(fixturePath("awesome-repo"), "package.json");
|
||||
|
||||
let destination = "";
|
||||
let updatedManifest = "";
|
||||
fs.__setMockFileWriter((dest, content) => {
|
||||
destination = dest;
|
||||
updatedManifest = content;
|
||||
});
|
||||
|
||||
expect(
|
||||
checkPackageManifest(manifestPath, { loose: false, write: true })
|
||||
).toBe(0);
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
expect(destination).toBe(manifestPath);
|
||||
expect(updatedManifest).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -1,359 +0,0 @@
|
|||
import semverCoerce from "semver/functions/coerce";
|
||||
import { checkPackageManifest, getCheckConfig } from "../src/check";
|
||||
import profile_0_62 from "../src/presets/microsoft/profile-0.62";
|
||||
import profile_0_63 from "../src/presets/microsoft/profile-0.63";
|
||||
import profile_0_64 from "../src/presets/microsoft/profile-0.64";
|
||||
import { packageVersion } from "./helpers";
|
||||
|
||||
jest.mock("fs");
|
||||
|
||||
describe("checkPackageManifest({ kitType: 'library' })", () => {
|
||||
const rnxKitConfig = require("@rnx-kit/config");
|
||||
const fs = require("fs");
|
||||
|
||||
const consoleErrorSpy = jest.spyOn(global.console, "error");
|
||||
const consoleLogSpy = jest.spyOn(global.console, "log");
|
||||
const consoleWarnSpy = jest.spyOn(global.console, "warn");
|
||||
|
||||
const defaultOptions = { loose: false, write: false };
|
||||
|
||||
const mockManifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "0.0.1",
|
||||
};
|
||||
|
||||
const react_v62_v63_v64 = [
|
||||
packageVersion(profile_0_62, "react"),
|
||||
packageVersion(profile_0_63, "react"),
|
||||
packageVersion(profile_0_64, "react"),
|
||||
].join(" || ");
|
||||
|
||||
const v62_v63_v64 = [
|
||||
packageVersion(profile_0_62, "core"),
|
||||
packageVersion(profile_0_63, "core"),
|
||||
packageVersion(profile_0_64, "core"),
|
||||
].join(" || ");
|
||||
|
||||
beforeEach(() => {
|
||||
consoleErrorSpy.mockReset();
|
||||
consoleLogSpy.mockReset();
|
||||
consoleWarnSpy.mockReset();
|
||||
fs.__setMockContent({});
|
||||
rnxKitConfig.__setMockConfig();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns error code when reading invalid manifests", () => {
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).not.toBe(0);
|
||||
expect(consoleErrorSpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test("returns early if 'rnx-kit' is missing from the manifest", () => {
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
dependencies: { "react-native-linear-gradient": "0.0.0" },
|
||||
});
|
||||
|
||||
const options = { ...defaultOptions, uncheckedReturnCode: -1 };
|
||||
expect(checkPackageManifest("package.json", options)).toBe(-1);
|
||||
expect(consoleWarnSpy).toBeCalled();
|
||||
});
|
||||
|
||||
test("prints warnings when detecting bad packages", () => {
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
dependencies: { "react-native-linear-gradient": "0.0.0" },
|
||||
peerDependencies: {
|
||||
"react-native": profile_0_64["core"],
|
||||
},
|
||||
devDependencies: {
|
||||
"react-native": profile_0_64["core"],
|
||||
},
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({ reactNativeVersion: "0.64.0" });
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("prints warnings when detecting bad packages (with version range)", () => {
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
dependencies: { "react-native-linear-gradient": "0.0.0" },
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({ reactNativeVersion: "^0.63.0 || ^0.64.0" });
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("returns early if no capabilities are defined", () => {
|
||||
fs.__setMockContent(mockManifest);
|
||||
rnxKitConfig.__setMockConfig({ reactNativeVersion: "0.64.0" });
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("returns if no changes are needed", () => {
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
peerDependencies: {
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
},
|
||||
devDependencies: {
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
},
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "0.64.0",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("returns if no changes are needed (write: true)", () => {
|
||||
let didWriteToPath = false;
|
||||
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
peerDependencies: {
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
},
|
||||
devDependencies: {
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
},
|
||||
});
|
||||
fs.__setMockFileWriter((p, _content) => {
|
||||
didWriteToPath = p;
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "0.64.0",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(
|
||||
checkPackageManifest("package.json", { loose: false, write: true })
|
||||
).toBe(0);
|
||||
expect(didWriteToPath).toBe(false);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("returns error code if changes are needed", () => {
|
||||
fs.__setMockContent(mockManifest);
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "0.64.0",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).not.toBe(0);
|
||||
expect(consoleErrorSpy).toBeCalledTimes(1);
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).toBeCalledTimes(2);
|
||||
});
|
||||
|
||||
test("writes changes back to 'package.json'", () => {
|
||||
let didWriteToPath = false;
|
||||
|
||||
fs.__setMockContent(mockManifest);
|
||||
fs.__setMockFileWriter((p, _content) => {
|
||||
didWriteToPath = p;
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "0.64.0",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(
|
||||
checkPackageManifest("package.json", { loose: false, write: true })
|
||||
).toBe(0);
|
||||
expect(didWriteToPath).toBe("package.json");
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("preserves indentation in 'package.json'", () => {
|
||||
let output = "";
|
||||
|
||||
fs.__setMockContent(mockManifest, "\t");
|
||||
fs.__setMockFileWriter((_, content) => {
|
||||
output = content;
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "0.64.0",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(
|
||||
checkPackageManifest("package.json", { loose: false, write: true })
|
||||
).toBe(0);
|
||||
expect(output).toMatchSnapshot();
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("uses minimum supported version as development version", () => {
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
peerDependencies: {
|
||||
react: react_v62_v63_v64,
|
||||
"react-native": v62_v63_v64,
|
||||
},
|
||||
devDependencies: {
|
||||
react: packageVersion(profile_0_62, "react"),
|
||||
"react-native": packageVersion(profile_0_62, "core"),
|
||||
},
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "^0.62 || ^0.63 || ^0.64",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("uses declared development version", () => {
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
peerDependencies: {
|
||||
react: react_v62_v63_v64,
|
||||
"react-native": v62_v63_v64,
|
||||
},
|
||||
devDependencies: {
|
||||
react: packageVersion(profile_0_63, "react"),
|
||||
"react-native": packageVersion(profile_0_63, "core"),
|
||||
},
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "^0.62 || ^0.63 || ^0.64",
|
||||
reactNativeDevVersion: "0.63.4",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("handles development version ranges", () => {
|
||||
fs.__setMockContent({
|
||||
...mockManifest,
|
||||
peerDependencies: {
|
||||
react: react_v62_v63_v64,
|
||||
"react-native": v62_v63_v64,
|
||||
},
|
||||
devDependencies: {
|
||||
react: packageVersion(profile_0_63, "react"),
|
||||
"react-native": packageVersion(profile_0_63, "core"),
|
||||
},
|
||||
});
|
||||
rnxKitConfig.__setMockConfig({
|
||||
reactNativeVersion: "^0.62 || ^0.63 || ^0.64",
|
||||
reactNativeDevVersion: "^0.63.4",
|
||||
capabilities: ["core-ios"],
|
||||
});
|
||||
|
||||
expect(checkPackageManifest("package.json", defaultOptions)).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleLogSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getCheckConfig", () => {
|
||||
const rnxKitConfig = require("@rnx-kit/config");
|
||||
const fs = require("fs");
|
||||
|
||||
const mockManifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "0.0.1",
|
||||
};
|
||||
|
||||
const defaultOptions = { loose: false, write: false };
|
||||
|
||||
beforeEach(() => {
|
||||
fs.__setMockContent(mockManifest);
|
||||
rnxKitConfig.__setMockConfig();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns early if the package is unconfigured", () => {
|
||||
expect(getCheckConfig("package.json", defaultOptions)).toBe(0);
|
||||
});
|
||||
|
||||
test("returns default values given react-native version", () => {
|
||||
const reactNativeVersion = "^0.64";
|
||||
rnxKitConfig.__setMockConfig({ reactNativeVersion });
|
||||
|
||||
expect(getCheckConfig("package.json", defaultOptions)).toEqual({
|
||||
capabilities: [],
|
||||
kitType: "library",
|
||||
manifest: mockManifest,
|
||||
reactNativeVersion,
|
||||
reactNativeDevVersion: semverCoerce(reactNativeVersion).version,
|
||||
});
|
||||
});
|
||||
|
||||
test("uses react-native version provided by vigilant flag if unspecified", () => {
|
||||
const reactNativeVersion = "^0.64";
|
||||
rnxKitConfig.__setMockConfig({ customProfiles: "" });
|
||||
|
||||
expect(
|
||||
getCheckConfig("package.json", {
|
||||
...defaultOptions,
|
||||
supportedVersions: reactNativeVersion,
|
||||
targetVersion: reactNativeVersion,
|
||||
})
|
||||
).toEqual({
|
||||
capabilities: [],
|
||||
kitType: "library",
|
||||
manifest: mockManifest,
|
||||
reactNativeVersion,
|
||||
reactNativeDevVersion: reactNativeVersion,
|
||||
});
|
||||
});
|
||||
|
||||
test("does not overwrite existing config with the version provided by vigilant flag", () => {
|
||||
const reactNativeVersion = "^0.64";
|
||||
rnxKitConfig.__setMockConfig({ reactNativeVersion });
|
||||
|
||||
expect(
|
||||
getCheckConfig("package.json", {
|
||||
...defaultOptions,
|
||||
supportedVersions: "1000.0",
|
||||
targetVersion: "1000.0",
|
||||
})
|
||||
).toEqual({
|
||||
capabilities: [],
|
||||
kitType: "library",
|
||||
manifest: mockManifest,
|
||||
reactNativeVersion,
|
||||
reactNativeDevVersion: semverCoerce(reactNativeVersion).version,
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,239 +0,0 @@
|
|||
import { PackageManifest, readPackage } from "@rnx-kit/tools-node/package";
|
||||
import path from "path";
|
||||
import { getRequirements, visitDependencies } from "../src/dependencies";
|
||||
|
||||
jest.unmock("@rnx-kit/config");
|
||||
|
||||
function fixturePath(name: string) {
|
||||
return path.join(process.cwd(), "test", "__fixtures__", name);
|
||||
}
|
||||
|
||||
function useFixture(name: string): [string, PackageManifest] {
|
||||
const fixture = fixturePath(name);
|
||||
return [fixture, readPackage(fixture)];
|
||||
}
|
||||
|
||||
describe("visitDependencies()", () => {
|
||||
const consoleWarnSpy = jest.spyOn(global.console, "warn");
|
||||
const currentWorkingDir = process.cwd();
|
||||
|
||||
beforeEach(() => {
|
||||
consoleWarnSpy.mockReset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.chdir(currentWorkingDir);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns if there are no direct dependencies", () => {
|
||||
const visited = new Set<string>();
|
||||
|
||||
visitDependencies(
|
||||
{ name: "@rnx-kit/dep-check", version: "1.0.0" },
|
||||
process.cwd(),
|
||||
() => 0,
|
||||
visited
|
||||
);
|
||||
expect(visited.size).toBe(0);
|
||||
|
||||
const dependencies = { "react-native": "1000.0.0" };
|
||||
|
||||
visitDependencies(
|
||||
{
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
peerDependencies: dependencies,
|
||||
devDependencies: dependencies,
|
||||
},
|
||||
process.cwd(),
|
||||
() => 0,
|
||||
visited
|
||||
);
|
||||
expect(visited.size).toBe(0);
|
||||
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("traverse transitive dependencies", () => {
|
||||
const fixture = fixturePath("awesome-repo");
|
||||
process.chdir(fixture);
|
||||
|
||||
const visited: string[] = [];
|
||||
visitDependencies(
|
||||
require(path.join(fixture, "package.json")),
|
||||
process.cwd(),
|
||||
(module) => {
|
||||
visited.push(module);
|
||||
}
|
||||
);
|
||||
|
||||
expect(visited.sort()).toEqual([
|
||||
"conan",
|
||||
"dutch",
|
||||
"john",
|
||||
"quaid",
|
||||
"react",
|
||||
"react-native",
|
||||
"t-800",
|
||||
]);
|
||||
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("skips unresolved packages", () => {
|
||||
const visited: string[] = [];
|
||||
visitDependencies(
|
||||
{
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"this-does-not-exist": "1.0.0",
|
||||
},
|
||||
},
|
||||
process.cwd(),
|
||||
(module) => visited.push(module)
|
||||
);
|
||||
|
||||
expect(visited.length).toBe(0);
|
||||
expect(consoleWarnSpy).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getRequirements()", () => {
|
||||
const consoleErrorSpy = jest.spyOn(global.console, "error");
|
||||
const consoleWarnSpy = jest.spyOn(global.console, "warn");
|
||||
const defaultOptions = { loose: false };
|
||||
|
||||
afterEach(() => {
|
||||
consoleErrorSpy.mockReset();
|
||||
consoleWarnSpy.mockReset();
|
||||
});
|
||||
|
||||
test("gets requirements from all dependencies", () => {
|
||||
const [fixture, manifest] = useFixture("awesome-repo");
|
||||
const { reactNativeVersion, capabilities } = getRequirements(
|
||||
"^0.63 || ^0.64",
|
||||
"app",
|
||||
manifest,
|
||||
fixture,
|
||||
undefined,
|
||||
defaultOptions
|
||||
);
|
||||
|
||||
expect(reactNativeVersion).toBe("^0.63 || ^0.64");
|
||||
|
||||
expect(capabilities.sort()).toEqual([
|
||||
"animation",
|
||||
"netinfo",
|
||||
"storage",
|
||||
"webview",
|
||||
]);
|
||||
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("gets requirements from all dependencies with custom profiles", () => {
|
||||
const cyberdyne = { name: "cyberdyne", version: "1.0.0", devOnly: true };
|
||||
const skynet = { name: "skynet", version: "1.0.0" };
|
||||
jest.mock(
|
||||
"awesome-dep-check-profiles",
|
||||
() => ({
|
||||
"0.63": {
|
||||
[cyberdyne.name]: cyberdyne,
|
||||
[skynet.name]: skynet,
|
||||
},
|
||||
"0.64": {
|
||||
[cyberdyne.name]: cyberdyne,
|
||||
[skynet.name]: skynet,
|
||||
},
|
||||
}),
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
const [fixture, manifest] = useFixture("awesome-repo-extended");
|
||||
const { reactNativeVersion, capabilities } = getRequirements(
|
||||
"^0.63 || ^0.64",
|
||||
"app",
|
||||
manifest,
|
||||
fixture,
|
||||
"awesome-dep-check-profiles",
|
||||
defaultOptions
|
||||
);
|
||||
|
||||
expect(reactNativeVersion).toBe("^0.63 || ^0.64");
|
||||
|
||||
expect(capabilities.sort()).toEqual([
|
||||
"animation",
|
||||
"netinfo",
|
||||
"skynet",
|
||||
"storage",
|
||||
"webview",
|
||||
]);
|
||||
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("throws if no profiles can satisfy required React Native version", () => {
|
||||
expect(() =>
|
||||
getRequirements(
|
||||
"0.60.6",
|
||||
"app",
|
||||
{
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
},
|
||||
"",
|
||||
undefined,
|
||||
defaultOptions
|
||||
)
|
||||
).toThrow();
|
||||
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("throws if no profiles can satisfy requirement of dependencies", () => {
|
||||
const [fixture, manifest] = useFixture("no-profile-satisfying-deps");
|
||||
expect(() =>
|
||||
getRequirements(
|
||||
"^0.64",
|
||||
"app",
|
||||
manifest,
|
||||
fixture,
|
||||
undefined,
|
||||
defaultOptions
|
||||
)
|
||||
).toThrowError("No React Native profile could satisfy all dependencies");
|
||||
|
||||
expect(consoleErrorSpy).toBeCalledWith(
|
||||
"error",
|
||||
expect.stringContaining(
|
||||
"No React Native profile could satisfy all dependencies"
|
||||
)
|
||||
);
|
||||
expect(consoleWarnSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("does not throw if no profiles can satisfy requirement of dependencies in loose mode", () => {
|
||||
const [fixture, manifest] = useFixture("no-profile-satisfying-deps");
|
||||
expect(() =>
|
||||
getRequirements("^0.64", "app", manifest, fixture, undefined, {
|
||||
loose: true,
|
||||
})
|
||||
).not.toThrow();
|
||||
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(consoleWarnSpy).toBeCalledWith(
|
||||
"warn",
|
||||
expect.stringContaining(
|
||||
"No React Native profile could satisfy all dependencies"
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,115 +0,0 @@
|
|||
import { findBadPackages } from "../src/findBadPackages";
|
||||
|
||||
describe("findBadPackages()", () => {
|
||||
const dependenciesWithOneBadPackage = {
|
||||
"react-native": "0.0.0",
|
||||
"react-native-linear-gradient": "0.0.0",
|
||||
};
|
||||
|
||||
const dependenciesWithMoreBadPackages = {
|
||||
"react-native": "0.0.0",
|
||||
"react-native-linear-gradient": "0.0.0",
|
||||
"react-native-netinfo": "0.0.0",
|
||||
};
|
||||
|
||||
test("finds bad packages in all dependencies", () => {
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
})
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: dependenciesWithOneBadPackage,
|
||||
})?.length
|
||||
).toBe(1);
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
peerDependencies: dependenciesWithOneBadPackage,
|
||||
})?.length
|
||||
).toBe(1);
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
devDependencies: dependenciesWithOneBadPackage,
|
||||
})?.length
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test("dedupes bad packages", () => {
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: dependenciesWithOneBadPackage,
|
||||
peerDependencies: dependenciesWithOneBadPackage,
|
||||
})?.length
|
||||
).toBe(1);
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: dependenciesWithOneBadPackage,
|
||||
devDependencies: dependenciesWithOneBadPackage,
|
||||
})?.length
|
||||
).toBe(1);
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
peerDependencies: dependenciesWithOneBadPackage,
|
||||
devDependencies: dependenciesWithOneBadPackage,
|
||||
})?.length
|
||||
).toBe(1);
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: dependenciesWithOneBadPackage,
|
||||
peerDependencies: dependenciesWithOneBadPackage,
|
||||
devDependencies: dependenciesWithOneBadPackage,
|
||||
})?.length
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
test("finds all bad packages", () => {
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: dependenciesWithMoreBadPackages,
|
||||
})?.length
|
||||
).toBe(2);
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: dependenciesWithOneBadPackage,
|
||||
peerDependencies: dependenciesWithMoreBadPackages,
|
||||
})?.length
|
||||
).toBe(2);
|
||||
|
||||
expect(
|
||||
findBadPackages({
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: dependenciesWithOneBadPackage,
|
||||
peerDependencies: dependenciesWithMoreBadPackages,
|
||||
devDependencies: dependenciesWithMoreBadPackages,
|
||||
})?.length
|
||||
).toBe(2);
|
||||
});
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
import { compare } from "../src/helpers";
|
||||
|
||||
describe("compare", () => {
|
||||
test("compares values", () => {
|
||||
expect(compare(0, 0)).toBe(0);
|
||||
expect(compare(0, 1)).toBe(-1);
|
||||
expect(compare(1, 0)).toBe(1);
|
||||
|
||||
expect(compare("dutch", "dutch")).toBe(0);
|
||||
expect(compare("dutch", "quaid")).toBe(-1);
|
||||
expect(compare("quaid", "dutch")).toBe(1);
|
||||
expect(compare("dutch", "dutchess")).toBe(-1);
|
||||
expect(compare("dutchess", "dutch")).toBe(1);
|
||||
|
||||
expect(compare("hyphen-before-lowbar", "hyphen_before_lowbar")).toBe(-1);
|
||||
});
|
||||
});
|
|
@ -1,20 +0,0 @@
|
|||
import type { Capability } from "@rnx-kit/config";
|
||||
import type { Profile, Package } from "../src/types";
|
||||
|
||||
export function pickPackage(profile: Profile, capability: string): Package {
|
||||
const pkg = profile[capability];
|
||||
if (!pkg) {
|
||||
throw new Error(`Could not resolve '${capability}'`);
|
||||
} else if (!("version" in pkg)) {
|
||||
throw new Error(`'${capability}' is a meta package`);
|
||||
}
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
export function packageVersion(
|
||||
profile: Profile,
|
||||
capability: Capability
|
||||
): string {
|
||||
return pickPackage(profile, capability).version;
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
import { initializeConfig } from "../src/initialize";
|
||||
|
||||
jest.mock("fs");
|
||||
|
||||
describe("initializeConfig()", () => {
|
||||
const fs = require("fs");
|
||||
|
||||
const bundle = {
|
||||
entryPath: "src/index.ts",
|
||||
distPath: "dist",
|
||||
assetsPath: "dist",
|
||||
bundlePrefix: "main",
|
||||
targets: ["ios", "android", "macos", "windows"],
|
||||
platforms: {
|
||||
android: {
|
||||
assetsPath: "dist/res",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockManifest = {
|
||||
dependencies: {
|
||||
"react-native": "^0.64.1",
|
||||
},
|
||||
peerDependencies: {
|
||||
"@react-native-community/netinfo": "^5.9.10",
|
||||
"react-native-webview": "^10.10.2",
|
||||
},
|
||||
"rnx-kit": {
|
||||
bundle,
|
||||
},
|
||||
};
|
||||
|
||||
const mockCapabilities = [
|
||||
"core",
|
||||
"core-android",
|
||||
"core-ios",
|
||||
"netinfo",
|
||||
"webview",
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
const unset = () => {
|
||||
throw new Error("unset");
|
||||
};
|
||||
fs.__setMockContent(unset);
|
||||
fs.__setMockFileWriter(unset);
|
||||
});
|
||||
|
||||
test("returns early if capabilities are declared", () => {
|
||||
fs.__setMockContent({ "rnx-kit": { capabilities: [] } });
|
||||
|
||||
let didWrite = false;
|
||||
fs.__setMockFileWriter(() => {
|
||||
didWrite = true;
|
||||
});
|
||||
|
||||
initializeConfig("package.json", {});
|
||||
expect(didWrite).toBe(false);
|
||||
});
|
||||
|
||||
test("returns early if no capabilities are found", () => {
|
||||
fs.__setMockContent({ name: "@rnx-kit/dep-check", version: "1.0.0-test" });
|
||||
|
||||
let didWrite = false;
|
||||
fs.__setMockFileWriter(() => {
|
||||
didWrite = true;
|
||||
});
|
||||
|
||||
initializeConfig("package.json", {});
|
||||
expect(didWrite).toBe(false);
|
||||
});
|
||||
|
||||
test("keeps existing config", () => {
|
||||
fs.__setMockContent({
|
||||
dependencies: {
|
||||
"react-native": "^0.64.1",
|
||||
},
|
||||
"rnx-kit": {
|
||||
platformBundle: false,
|
||||
bundle,
|
||||
},
|
||||
});
|
||||
|
||||
let content = {};
|
||||
fs.__setMockFileWriter((_: string, data: string) => {
|
||||
content = JSON.parse(data);
|
||||
});
|
||||
|
||||
initializeConfig("package.json", {});
|
||||
|
||||
const kitConfig = content["rnx-kit"];
|
||||
if (!kitConfig) {
|
||||
fail();
|
||||
}
|
||||
|
||||
expect(kitConfig["platformBundle"]).toBe(false);
|
||||
expect(kitConfig["bundle"]).toEqual(bundle);
|
||||
});
|
||||
|
||||
test('adds config with type "app"', () => {
|
||||
fs.__setMockContent(mockManifest);
|
||||
|
||||
let content = {};
|
||||
fs.__setMockFileWriter((_: string, data: string) => {
|
||||
content = JSON.parse(data);
|
||||
});
|
||||
|
||||
initializeConfig("package.json", { kitType: "app" });
|
||||
|
||||
const kitConfig = content["rnx-kit"];
|
||||
if (!kitConfig) {
|
||||
fail();
|
||||
}
|
||||
|
||||
expect(kitConfig["bundle"]).toEqual(bundle);
|
||||
expect(kitConfig["reactNativeVersion"]).toEqual("^0.64");
|
||||
expect(kitConfig["reactNativeDevVersion"]).toBeUndefined();
|
||||
expect(kitConfig["kitType"]).toEqual("app");
|
||||
expect(kitConfig["capabilities"]).toEqual(mockCapabilities);
|
||||
expect(kitConfig["customProfiles"]).toBeUndefined();
|
||||
});
|
||||
|
||||
test('adds config with type "library"', () => {
|
||||
fs.__setMockContent(mockManifest);
|
||||
|
||||
let content = {};
|
||||
fs.__setMockFileWriter((_: string, data: string) => {
|
||||
content = JSON.parse(data);
|
||||
});
|
||||
|
||||
initializeConfig("package.json", { kitType: "library" });
|
||||
|
||||
const kitConfig = content["rnx-kit"];
|
||||
if (!kitConfig) {
|
||||
fail();
|
||||
}
|
||||
|
||||
expect(kitConfig["bundle"]).toEqual(bundle);
|
||||
expect(kitConfig["reactNativeVersion"]).toEqual("^0.64");
|
||||
expect(kitConfig["reactNativeDevVersion"]).toEqual("0.64.0");
|
||||
expect(kitConfig["kitType"]).toEqual("library");
|
||||
expect(kitConfig["capabilities"]).toEqual(mockCapabilities);
|
||||
expect(kitConfig["customProfiles"]).toBeUndefined();
|
||||
});
|
||||
|
||||
// Test disabled because custom profile now depends on align-deps
|
||||
xtest("adds config with custom profiles", () => {
|
||||
fs.__setMockContent(mockManifest);
|
||||
|
||||
let content = {};
|
||||
fs.__setMockFileWriter((_: string, data: string) => {
|
||||
content = JSON.parse(data);
|
||||
});
|
||||
|
||||
initializeConfig("package.json", {
|
||||
kitType: "library",
|
||||
customProfilesPath: "@rnx-kit/scripts/align-deps-preset.js",
|
||||
});
|
||||
|
||||
const kitConfig = content["rnx-kit"];
|
||||
if (!kitConfig) {
|
||||
fail();
|
||||
}
|
||||
|
||||
expect(kitConfig["customProfiles"]).toEqual(
|
||||
"@rnx-kit/scripts/align-deps-preset.js"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,312 +0,0 @@
|
|||
import {
|
||||
removeKeys,
|
||||
updateDependencies,
|
||||
updatePackageManifest,
|
||||
} from "../src/manifest";
|
||||
import profile_0_63 from "../src/presets/microsoft/profile-0.63";
|
||||
import profile_0_64 from "../src/presets/microsoft/profile-0.64";
|
||||
import type { Package } from "../src/types";
|
||||
import { packageVersion, pickPackage } from "./helpers";
|
||||
|
||||
const mockDependencies = {
|
||||
typescript: "0.0.0",
|
||||
react: "0.0.0",
|
||||
"react-native-test-app": "0.0.0",
|
||||
"react-native": "0.0.0",
|
||||
};
|
||||
|
||||
describe("removeKeys()", () => {
|
||||
test("returns a new copy of object with specified keys removed", () => {
|
||||
const original = { x: "1", y: "2", z: "3" };
|
||||
const originalKeys = Object.keys(original);
|
||||
const modified = removeKeys(original, ["x", "z"]);
|
||||
expect(modified).not.toBe(original);
|
||||
expect(Object.keys(original)).toEqual(originalKeys);
|
||||
expect(modified).toEqual({ y: original.y });
|
||||
});
|
||||
|
||||
test("returns a new copy of object even if no keys are removed", () => {
|
||||
const original = { x: "1", y: "2", z: "3" };
|
||||
const originalKeys = Object.keys(original);
|
||||
const modified = removeKeys(original, ["a", "b"]);
|
||||
expect(modified).not.toBe(original);
|
||||
expect(Object.keys(original)).toEqual(originalKeys);
|
||||
expect(modified).toEqual(original);
|
||||
});
|
||||
|
||||
test("handles undefined objects", () => {
|
||||
expect(removeKeys(undefined, ["x", "y"])).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("updateDependencies()", () => {
|
||||
const resolvedPackages: Record<string, Package[]> = {
|
||||
react: [
|
||||
pickPackage(profile_0_63, "react"),
|
||||
pickPackage(profile_0_64, "react"),
|
||||
],
|
||||
"react-native": [
|
||||
pickPackage(profile_0_63, "core"),
|
||||
pickPackage(profile_0_64, "core"),
|
||||
],
|
||||
"react-native-macos": [
|
||||
pickPackage(profile_0_63, "core-macos"),
|
||||
pickPackage(profile_0_64, "core-macos"),
|
||||
],
|
||||
"react-native-test-app": [pickPackage(profile_0_64, "test-app")],
|
||||
"react-native-windows": [
|
||||
pickPackage(profile_0_63, "core-windows"),
|
||||
pickPackage(profile_0_64, "core-windows"),
|
||||
],
|
||||
};
|
||||
|
||||
test("bumps dependencies to maximum supported version", () => {
|
||||
const updated = updateDependencies(
|
||||
mockDependencies,
|
||||
resolvedPackages,
|
||||
"direct"
|
||||
);
|
||||
expect(updated).toEqual({
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
"react-native-macos": packageVersion(profile_0_64, "core-macos"),
|
||||
"react-native-test-app": "0.0.0",
|
||||
"react-native-windows": packageVersion(profile_0_64, "core-windows"),
|
||||
typescript: "0.0.0",
|
||||
});
|
||||
});
|
||||
|
||||
test("bumps dependencies to minimum supported version", () => {
|
||||
const updated = updateDependencies(
|
||||
mockDependencies,
|
||||
resolvedPackages,
|
||||
"development"
|
||||
);
|
||||
expect(updated).toEqual({
|
||||
react: packageVersion(profile_0_63, "react"),
|
||||
"react-native": packageVersion(profile_0_63, "core"),
|
||||
"react-native-macos": packageVersion(profile_0_63, "core-macos"),
|
||||
"react-native-test-app": packageVersion(profile_0_63, "test-app"),
|
||||
"react-native-windows": packageVersion(profile_0_63, "core-windows"),
|
||||
typescript: "0.0.0",
|
||||
});
|
||||
});
|
||||
|
||||
test("bumps dependencies to widest possible version range", () => {
|
||||
const updated = updateDependencies(
|
||||
mockDependencies,
|
||||
resolvedPackages,
|
||||
"peer"
|
||||
);
|
||||
expect(updated).toEqual({
|
||||
react: `${packageVersion(profile_0_63, "react")} || ${packageVersion(
|
||||
profile_0_64,
|
||||
"react"
|
||||
)}`,
|
||||
"react-native": `${packageVersion(
|
||||
profile_0_63,
|
||||
"core"
|
||||
)} || ${packageVersion(profile_0_64, "core")}`,
|
||||
"react-native-macos": `${packageVersion(
|
||||
profile_0_63,
|
||||
"core-macos"
|
||||
)} || ${packageVersion(profile_0_64, "core-macos")}`,
|
||||
"react-native-test-app": "0.0.0",
|
||||
"react-native-windows": `${packageVersion(
|
||||
profile_0_63,
|
||||
"core-windows"
|
||||
)} || ${packageVersion(profile_0_64, "core-windows")}`,
|
||||
typescript: "0.0.0",
|
||||
});
|
||||
});
|
||||
|
||||
test("sorts keys", () => {
|
||||
const updated = updateDependencies(
|
||||
mockDependencies,
|
||||
resolvedPackages,
|
||||
"development"
|
||||
);
|
||||
const updatedKeys = Object.keys(updated);
|
||||
const originalKeys = Object.keys(mockDependencies);
|
||||
expect(updatedKeys).not.toEqual(originalKeys);
|
||||
expect(updatedKeys.sort()).not.toEqual(originalKeys);
|
||||
});
|
||||
|
||||
test("sets undefined dependencies", () => {
|
||||
expect(
|
||||
updateDependencies(undefined, resolvedPackages, "development")
|
||||
).toEqual({
|
||||
react: packageVersion(profile_0_63, "react"),
|
||||
"react-native": packageVersion(profile_0_63, "core"),
|
||||
"react-native-macos": packageVersion(profile_0_63, "core-macos"),
|
||||
"react-native-test-app": packageVersion(profile_0_63, "test-app"),
|
||||
"react-native-windows": packageVersion(profile_0_63, "core-windows"),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("updatePackageManifest()", () => {
|
||||
test("sets direct dependencies for apps", () => {
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
updatePackageManifest(
|
||||
{
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: mockDependencies,
|
||||
peerDependencies: {},
|
||||
devDependencies: {},
|
||||
},
|
||||
["core-android", "core-ios"],
|
||||
[profile_0_63, profile_0_64],
|
||||
[profile_0_64],
|
||||
"app"
|
||||
);
|
||||
expect(dependencies).toEqual({
|
||||
...mockDependencies,
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
});
|
||||
expect(peerDependencies).toBeUndefined();
|
||||
expect(devDependencies).toBeUndefined();
|
||||
});
|
||||
|
||||
test("removes dependencies from devDependencies for apps", () => {
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
updatePackageManifest(
|
||||
{
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: {},
|
||||
peerDependencies: {},
|
||||
devDependencies: mockDependencies,
|
||||
},
|
||||
["core-android", "core-ios", "react"],
|
||||
[profile_0_63, profile_0_64],
|
||||
[profile_0_64],
|
||||
"app"
|
||||
);
|
||||
expect(dependencies).toEqual({
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
});
|
||||
expect(peerDependencies).toBeUndefined();
|
||||
expect(devDependencies).toEqual({
|
||||
"react-native-test-app": "0.0.0",
|
||||
typescript: "0.0.0",
|
||||
});
|
||||
});
|
||||
|
||||
test("removes dependencies from peerDependencies for apps", () => {
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
updatePackageManifest(
|
||||
{
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: {},
|
||||
peerDependencies: mockDependencies,
|
||||
devDependencies: {},
|
||||
},
|
||||
["core-android", "core-ios", "react"],
|
||||
[profile_0_63, profile_0_64],
|
||||
[profile_0_64],
|
||||
"app"
|
||||
);
|
||||
expect(dependencies).toEqual({
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
});
|
||||
expect(peerDependencies).toEqual({
|
||||
"react-native-test-app": "0.0.0",
|
||||
typescript: "0.0.0",
|
||||
});
|
||||
expect(devDependencies).toBeUndefined();
|
||||
});
|
||||
|
||||
test("sets dev/peer dependencies for libraries", () => {
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
updatePackageManifest(
|
||||
{
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: { "@rnx-kit/dep-check": "^1.0.0" },
|
||||
peerDependencies: mockDependencies,
|
||||
},
|
||||
["core-android", "core-ios"],
|
||||
[profile_0_63, profile_0_64],
|
||||
[profile_0_64],
|
||||
"library"
|
||||
);
|
||||
expect(dependencies).toEqual({ "@rnx-kit/dep-check": "^1.0.0" });
|
||||
expect(peerDependencies).toEqual({
|
||||
...mockDependencies,
|
||||
react: [
|
||||
packageVersion(profile_0_63, "react"),
|
||||
packageVersion(profile_0_64, "react"),
|
||||
].join(" || "),
|
||||
"react-native": [
|
||||
packageVersion(profile_0_63, "core"),
|
||||
packageVersion(profile_0_64, "core"),
|
||||
].join(" || "),
|
||||
});
|
||||
expect(devDependencies).toEqual({
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
});
|
||||
});
|
||||
|
||||
test("removes dependencies from direct dependencies for libraries", () => {
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
updatePackageManifest(
|
||||
{
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: {
|
||||
"@rnx-kit/dep-check": "^1.0.0",
|
||||
"react-native": "0.0.0",
|
||||
},
|
||||
peerDependencies: mockDependencies,
|
||||
devDependencies: {},
|
||||
},
|
||||
["core-android", "core-ios"],
|
||||
[profile_0_64],
|
||||
[profile_0_64],
|
||||
"library"
|
||||
);
|
||||
expect(dependencies).toEqual({ "@rnx-kit/dep-check": "^1.0.0" });
|
||||
expect(peerDependencies).toEqual({
|
||||
...mockDependencies,
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
});
|
||||
expect(devDependencies).toEqual({
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
});
|
||||
});
|
||||
|
||||
test("always sets dev-only dependencies", () => {
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
updatePackageManifest(
|
||||
{
|
||||
name: "Test",
|
||||
version: "0.0.1",
|
||||
dependencies: mockDependencies,
|
||||
peerDependencies: {},
|
||||
devDependencies: {},
|
||||
},
|
||||
["core-android", "core-ios", "test-app"],
|
||||
[profile_0_63, profile_0_64],
|
||||
[profile_0_64],
|
||||
"app"
|
||||
);
|
||||
expect(dependencies).toEqual({
|
||||
...mockDependencies,
|
||||
react: packageVersion(profile_0_64, "react"),
|
||||
"react-native": packageVersion(profile_0_64, "core"),
|
||||
});
|
||||
expect(peerDependencies).toBeUndefined();
|
||||
expect(devDependencies).toEqual({
|
||||
"react-native-test-app": packageVersion(profile_0_64, "test-app"),
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,265 +0,0 @@
|
|||
import * as path from "path";
|
||||
import semver from "semver";
|
||||
import preset from "../src/presets/microsoft";
|
||||
import profile_0_62 from "../src/presets/microsoft/profile-0.62";
|
||||
import profile_0_63 from "../src/presets/microsoft/profile-0.63";
|
||||
import profile_0_64 from "../src/presets/microsoft/profile-0.64";
|
||||
import {
|
||||
getProfilesFor,
|
||||
getProfileVersionsFor,
|
||||
loadCustomProfiles,
|
||||
profilesSatisfying,
|
||||
resolveCustomProfiles,
|
||||
} from "../src/profiles";
|
||||
import { ProfileVersion } from "../src/types";
|
||||
|
||||
describe("Microsoft preset", () => {
|
||||
test("matches react-native versions", () => {
|
||||
const includePrerelease = {
|
||||
includePrerelease: true,
|
||||
};
|
||||
Object.entries(preset).forEach(([version, capabilities]) => {
|
||||
const versionRange = "^" + version;
|
||||
Object.entries(capabilities).forEach(([capability, pkg]) => {
|
||||
if (capability === "core") {
|
||||
expect(
|
||||
"version" in pkg &&
|
||||
semver.subset(pkg.version, versionRange, includePrerelease)
|
||||
).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("getProfileVersionsFor()", () => {
|
||||
test("returns profile versions for specific version", () => {
|
||||
expect(getProfileVersionsFor("0.61.5")).toEqual(["0.61"]);
|
||||
expect(getProfileVersionsFor("0.62.2")).toEqual(["0.62"]);
|
||||
expect(getProfileVersionsFor("0.63.4")).toEqual(["0.63"]);
|
||||
expect(getProfileVersionsFor("0.64.0")).toEqual(["0.64"]);
|
||||
});
|
||||
|
||||
test("returns profile for one version range", () => {
|
||||
expect(getProfileVersionsFor("^0.62.2")).toEqual(["0.62"]);
|
||||
expect(getProfileVersionsFor("^0.63.4")).toEqual(["0.63"]);
|
||||
expect(getProfileVersionsFor("^0.64.0")).toEqual(["0.64"]);
|
||||
});
|
||||
|
||||
test("returns profiles for bigger version ranges", () => {
|
||||
const profiles = getProfileVersionsFor(">=0.66.4");
|
||||
expect(profiles).toEqual(["0.66", "0.67", "0.68", "0.69", "0.70"]);
|
||||
});
|
||||
|
||||
test("returns profiles for multiple version ranges", () => {
|
||||
const profiles = getProfileVersionsFor("^0.63.0 || ^0.64.0");
|
||||
expect(profiles).toEqual(["0.63", "0.64"]);
|
||||
});
|
||||
|
||||
test("returns an empty array when an unsupported version is provided", () => {
|
||||
expect(getProfileVersionsFor("^0.60.6")).toEqual([]);
|
||||
});
|
||||
|
||||
test("throws when an invalid version is provided", () => {
|
||||
expect(() => getProfileVersionsFor("invalid")).toThrowError(
|
||||
"Invalid 'react-native' version"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getProfilesFor()", () => {
|
||||
const consoleErrorSpy = jest.spyOn(global.console, "error");
|
||||
|
||||
beforeEach(() => {
|
||||
consoleErrorSpy.mockReset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns profile for specific version", () => {
|
||||
const profiles = getProfilesFor("0.64.0", undefined);
|
||||
expect(profiles).toEqual([profile_0_64]);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("returns profile for one version range", () => {
|
||||
expect(getProfilesFor("^0.62.2", undefined)).toEqual([profile_0_62]);
|
||||
expect(getProfilesFor("^0.63.4", undefined)).toEqual([profile_0_63]);
|
||||
expect(getProfilesFor("^0.64.0", undefined)).toEqual([profile_0_64]);
|
||||
});
|
||||
|
||||
test("returns profiles for bigger version ranges", () => {
|
||||
const profiles = getProfilesFor(">=0.62.2", undefined);
|
||||
expect(profiles.slice(0, 3)).toEqual([
|
||||
profile_0_62,
|
||||
profile_0_63,
|
||||
profile_0_64,
|
||||
]);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("returns profiles for multiple version ranges", () => {
|
||||
const profiles = getProfilesFor("^0.63.0 || ^0.64.0", undefined);
|
||||
expect(profiles).toEqual([profile_0_63, profile_0_64]);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("throws when an unsupported version is provided", () => {
|
||||
expect(() => getProfilesFor("^0.60.6", undefined)).toThrowError(
|
||||
"Unsupported 'react-native' version"
|
||||
);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("throws when an invalid version is provided", () => {
|
||||
expect(() => getProfilesFor("invalid", undefined)).toThrowError(
|
||||
"Invalid 'react-native' version"
|
||||
);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("throws if custom profiles module does not exist", () => {
|
||||
expect(() =>
|
||||
getProfilesFor("^0.59", "non-existent-profiles-module")
|
||||
).toThrow(`Cannot find module 'non-existent-profiles-module'`);
|
||||
});
|
||||
|
||||
test("throws if custom profiles module does not default export an object", () => {
|
||||
jest.mock("bad-profiles-module", () => null, { virtual: true });
|
||||
|
||||
expect(() => getProfilesFor("^0.59", "bad-profiles-module")).toThrow(
|
||||
"'bad-profiles-module' doesn't default export profiles"
|
||||
);
|
||||
|
||||
expect(consoleErrorSpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test("appends custom profiles", () => {
|
||||
const skynet = { name: "skynet", version: "1.0.0" };
|
||||
jest.mock(
|
||||
"good-profiles-module",
|
||||
() => ({ "0.62": { [skynet.name]: skynet } }),
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
const [profile_0_62, profile_0_63] = getProfilesFor(
|
||||
"^0.62 || ^0.63",
|
||||
"good-profiles-module"
|
||||
);
|
||||
|
||||
expect(skynet.name in profile_0_62).toBe(true);
|
||||
expect(skynet.name in profile_0_63).toBe(false);
|
||||
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadCustomProfiles()", () => {
|
||||
test("returns any empty object if no custom profiles are specified", () => {
|
||||
expect(loadCustomProfiles(undefined)).toEqual({});
|
||||
});
|
||||
|
||||
test("throws if custom profiles are not the right shape", () => {
|
||||
expect(() =>
|
||||
loadCustomProfiles(
|
||||
path.join(
|
||||
__dirname,
|
||||
"__fixtures__",
|
||||
"custom-profiles",
|
||||
"local-profiles.js"
|
||||
)
|
||||
)
|
||||
).toThrow("doesn't default export profiles");
|
||||
});
|
||||
|
||||
test("loads valid custom profiles", () => {
|
||||
expect(
|
||||
loadCustomProfiles(
|
||||
path.join(
|
||||
__dirname,
|
||||
"__fixtures__",
|
||||
"custom-profiles",
|
||||
"valid-profiles.js"
|
||||
)
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("prepends root-level capabilities to all profiles", () => {
|
||||
expect(
|
||||
loadCustomProfiles(
|
||||
path.join(
|
||||
__dirname,
|
||||
"__fixtures__",
|
||||
"custom-profiles",
|
||||
"root-level-profiles.js"
|
||||
)
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("profilesSatisfying()", () => {
|
||||
const profileVersions: ProfileVersion[] = ["0.61", "0.62", "0.63", "0.64"];
|
||||
|
||||
test("returns an empty array when no profiles can satisfy requirements", () => {
|
||||
expect(profilesSatisfying([], "^0.63.0 || ^0.64.0")).toEqual([]);
|
||||
expect(profilesSatisfying(["0.61"], "^0.63.0 || ^0.64.0")).toEqual([]);
|
||||
});
|
||||
|
||||
test("returns all profiles satisfying version", () => {
|
||||
expect(profilesSatisfying(profileVersions, "0.63.2")).toEqual(["0.63"]);
|
||||
expect(profilesSatisfying(profileVersions, "0.64.0-rc1")).toEqual(["0.64"]);
|
||||
expect(profilesSatisfying(profileVersions, "0.64.0")).toEqual(["0.64"]);
|
||||
});
|
||||
|
||||
test("returns all profiles satisfying version range", () => {
|
||||
expect(
|
||||
profilesSatisfying(profileVersions, "^0.63.0-0 || ^0.64.0-0")
|
||||
).toEqual(["0.63", "0.64"]);
|
||||
expect(profilesSatisfying(profileVersions, "^0.63.0 || ^0.64.0")).toEqual([
|
||||
"0.63",
|
||||
"0.64",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveCustomProfiles()", () => {
|
||||
const projectRoot = `${__dirname}/__fixtures__/custom-profiles`;
|
||||
|
||||
test("handles undefined and empty strings", () => {
|
||||
expect(resolveCustomProfiles(projectRoot, undefined)).toBeUndefined();
|
||||
expect(resolveCustomProfiles(projectRoot, "")).toBeUndefined();
|
||||
});
|
||||
|
||||
test("throws if the module cannot be resolved", () => {
|
||||
expect(() =>
|
||||
resolveCustomProfiles(projectRoot, "non-existent-custom-profiles")
|
||||
).toThrow("Cannot resolve module");
|
||||
});
|
||||
|
||||
test("returns absolute path for module ids", () => {
|
||||
const profilesPkg = "custom-profiles-package";
|
||||
expect(resolveCustomProfiles(projectRoot, profilesPkg)).toEqual(
|
||||
expect.stringContaining(
|
||||
path.join(
|
||||
"__fixtures__",
|
||||
"custom-profiles",
|
||||
"node_modules",
|
||||
profilesPkg,
|
||||
"index.js"
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test("returns absolute path for relative paths", () => {
|
||||
expect(resolveCustomProfiles(projectRoot, "./local-profiles.js")).toEqual(
|
||||
expect.stringContaining(
|
||||
path.join("__fixtures__", "custom-profiles", "local-profiles.js")
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,204 +0,0 @@
|
|||
import type { PackageManifest } from "@rnx-kit/tools-node/package";
|
||||
import prompts from "prompts";
|
||||
import { makeSetVersionCommand } from "../src/setVersion";
|
||||
|
||||
jest.mock("fs");
|
||||
|
||||
type Result = {
|
||||
didWrite: boolean;
|
||||
manifest: Record<string, unknown>;
|
||||
};
|
||||
|
||||
describe("makeSetVersionCommand()", () => {
|
||||
const rnxKitConfig = require("@rnx-kit/config");
|
||||
const fs = require("fs");
|
||||
|
||||
function setupMocks(manifest: PackageManifest): Result {
|
||||
fs.__setMockContent(manifest);
|
||||
|
||||
const result: Result = { didWrite: false, manifest: {} };
|
||||
fs.__setMockFileWriter((_: string, content: string) => {
|
||||
const updatedManifest = JSON.parse(content);
|
||||
fs.__setMockContent(updatedManifest);
|
||||
rnxKitConfig.__setMockConfig(updatedManifest["rnx-kit"]);
|
||||
|
||||
result.didWrite = true;
|
||||
result.manifest = updatedManifest;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const mockManifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0-test",
|
||||
dependencies: {
|
||||
react: "16.13.1",
|
||||
"react-native": "^0.63.2",
|
||||
},
|
||||
devDependencies: {},
|
||||
"rnx-kit": {
|
||||
reactNativeVersion: "^0.63",
|
||||
kitType: "app",
|
||||
capabilities: ["core"],
|
||||
},
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
fs.__setMockContent({});
|
||||
rnxKitConfig.__setMockConfig();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("rejects unsupported versions `react-native`", async () => {
|
||||
expect(makeSetVersionCommand("0.59")).rejects.toEqual(
|
||||
expect.objectContaining({
|
||||
message: expect.stringContaining(
|
||||
"Unsupported 'react-native' version/range:"
|
||||
),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("updates dependencies", async () => {
|
||||
const result = setupMocks({
|
||||
...mockManifest,
|
||||
"rnx-kit": {
|
||||
...mockManifest["rnx-kit"],
|
||||
kitType: "library",
|
||||
reactNativeDevVersion: "^0.63.0",
|
||||
},
|
||||
});
|
||||
|
||||
const command = await makeSetVersionCommand("0.64,0.63");
|
||||
expect(typeof command).toBe("function");
|
||||
expect(command("package.json")).toBe(0);
|
||||
expect(result.manifest).toEqual({
|
||||
...mockManifest,
|
||||
dependencies: undefined,
|
||||
devDependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
},
|
||||
peerDependencies: {
|
||||
react: "16.13.1 || 17.0.1",
|
||||
"react-native": "^0.63.2 || ^0.64.2",
|
||||
},
|
||||
"rnx-kit": {
|
||||
...mockManifest["rnx-kit"],
|
||||
kitType: "library",
|
||||
reactNativeVersion: "^0.63.0 || ^0.64.0",
|
||||
reactNativeDevVersion: "^0.64.0",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("removes `reactNativeDevVersion` if `kitType` is `app`", async () => {
|
||||
const result = setupMocks({
|
||||
...mockManifest,
|
||||
"rnx-kit": {
|
||||
...mockManifest["rnx-kit"],
|
||||
reactNativeDevVersion: "^0.63.0",
|
||||
},
|
||||
});
|
||||
|
||||
const command = await makeSetVersionCommand("0.64,0.63");
|
||||
expect(typeof command).toBe("function");
|
||||
expect(command("package.json")).toBe(0);
|
||||
expect(result.manifest).toEqual({
|
||||
...mockManifest,
|
||||
dependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
},
|
||||
devDependencies: undefined,
|
||||
"rnx-kit": {
|
||||
...mockManifest["rnx-kit"],
|
||||
reactNativeVersion: "^0.63.0 || ^0.64.0",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("prompts the user if no version is specified", async () => {
|
||||
const result = setupMocks(mockManifest);
|
||||
|
||||
prompts.inject([["0.63", "0.64"], "0.64"]);
|
||||
|
||||
const command = await makeSetVersionCommand("");
|
||||
expect(typeof command).toBe("function");
|
||||
expect(command("package.json")).toBe(0);
|
||||
expect(result.manifest).toEqual({
|
||||
...mockManifest,
|
||||
dependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
},
|
||||
devDependencies: undefined,
|
||||
"rnx-kit": {
|
||||
...mockManifest["rnx-kit"],
|
||||
reactNativeVersion: "^0.63 || ^0.64",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("skips the second prompt if only one version is supported", async () => {
|
||||
const result = setupMocks(mockManifest);
|
||||
|
||||
prompts.inject([["0.64"]]);
|
||||
|
||||
const command = await makeSetVersionCommand("");
|
||||
expect(typeof command).toBe("function");
|
||||
expect(command("package.json")).toBe(0);
|
||||
expect(result.manifest).toEqual({
|
||||
...mockManifest,
|
||||
dependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "^0.64.2",
|
||||
},
|
||||
devDependencies: undefined,
|
||||
"rnx-kit": {
|
||||
...mockManifest["rnx-kit"],
|
||||
reactNativeVersion: "^0.64",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('skips "dirty" packages', async () => {
|
||||
rnxKitConfig.__setMockConfig(mockManifest["rnx-kit"]);
|
||||
const result = setupMocks({
|
||||
...mockManifest,
|
||||
dependencies: {
|
||||
"react-native": "^0.62.3",
|
||||
},
|
||||
});
|
||||
|
||||
prompts.inject([["0.64"]]);
|
||||
|
||||
const command = await makeSetVersionCommand("");
|
||||
expect(typeof command).toBe("function");
|
||||
expect(command("package.json")).not.toBe(0);
|
||||
expect(result.didWrite).toBe(false);
|
||||
});
|
||||
|
||||
test("skips unconfigured packages", async () => {
|
||||
const result = setupMocks({
|
||||
...mockManifest,
|
||||
"rnx-kit": undefined,
|
||||
} as PackageManifest);
|
||||
|
||||
prompts.inject([["0.64"]]);
|
||||
|
||||
const command = await makeSetVersionCommand("");
|
||||
expect(typeof command).toBe("function");
|
||||
expect(command("package.json")).toBe(0);
|
||||
expect(result.didWrite).toBe(false);
|
||||
});
|
||||
|
||||
test("exits if the user cancels during prompts", async () => {
|
||||
prompts.inject([undefined]);
|
||||
expect(await makeSetVersionCommand("")).toBeUndefined();
|
||||
|
||||
prompts.inject([["0.63", "0.64"], undefined]);
|
||||
expect(await makeSetVersionCommand("")).toBeUndefined();
|
||||
});
|
||||
});
|
|
@ -1,477 +0,0 @@
|
|||
import { parseProfilesString } from "../src/profiles";
|
||||
import {
|
||||
buildManifestProfile,
|
||||
buildProfileFromConfig,
|
||||
inspect,
|
||||
makeVigilantCommand,
|
||||
} from "../src/vigilant";
|
||||
|
||||
jest.mock("fs");
|
||||
|
||||
describe("buildManifestProfile()", () => {
|
||||
const testVersion = "1.0.0-test";
|
||||
|
||||
test("builds a package manifest for a single profile version", () => {
|
||||
const profiles = parseProfilesString("0.64", undefined);
|
||||
const profile = buildManifestProfile(profiles);
|
||||
profile.version = testVersion;
|
||||
expect(profile).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("builds a package manifest for multiple profile versions", () => {
|
||||
const profiles = parseProfilesString("0.64,0.63", undefined);
|
||||
const profile = buildManifestProfile(profiles);
|
||||
profile.version = testVersion;
|
||||
expect(profile).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("includes devOnly packages under `dependencies`", () => {
|
||||
const profiles = parseProfilesString("0.64", undefined);
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
buildManifestProfile(profiles);
|
||||
|
||||
expect("react-native-test-app" in dependencies).toBe(true);
|
||||
expect("react-native-test-app" in peerDependencies).toBe(false);
|
||||
expect("react-native-test-app" in devDependencies).toBe(true);
|
||||
});
|
||||
|
||||
test("includes custom profiles", () => {
|
||||
const skynet = { name: "skynet", version: "1.0.0" };
|
||||
jest.mock(
|
||||
"vigilant-custom-profiles",
|
||||
() => ({ "0.64": { [skynet.name]: skynet } }),
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
const profiles = parseProfilesString("0.64", "vigilant-custom-profiles");
|
||||
const { dependencies, devDependencies, peerDependencies } =
|
||||
buildManifestProfile(profiles);
|
||||
|
||||
expect(skynet.name in dependencies).toBe(true);
|
||||
expect(skynet.name in peerDependencies).toBe(true);
|
||||
expect(skynet.name in devDependencies).toBe(true);
|
||||
});
|
||||
|
||||
test("throws when no profiles match the requested versions", () => {
|
||||
expect(() => parseProfilesString("0.59", undefined)).toThrow();
|
||||
expect(() => parseProfilesString("0.59,0.64", undefined)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildProfileFromConfig()", () => {
|
||||
const profiles = parseProfilesString("0.64", undefined);
|
||||
const defaultProfile = buildManifestProfile(profiles);
|
||||
|
||||
test("returns default profile if there is no config", () => {
|
||||
expect(buildProfileFromConfig(0, defaultProfile)).toBe(defaultProfile);
|
||||
});
|
||||
|
||||
test("filters out managed capabilities", () => {
|
||||
const dependencies = [
|
||||
"dependencies",
|
||||
"peerDependencies",
|
||||
"devDependencies",
|
||||
] as const;
|
||||
const config = {
|
||||
kitType: "library" as const,
|
||||
reactNativeVersion: "0.64",
|
||||
reactNativeDevVersion: "0.64",
|
||||
capabilities: [],
|
||||
manifest: {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"react-native": "^0.64.0",
|
||||
},
|
||||
},
|
||||
};
|
||||
const profile = buildProfileFromConfig(config, defaultProfile);
|
||||
dependencies.forEach((section) => {
|
||||
expect(Object.keys(profile[section])).toContain("react");
|
||||
expect(Object.keys(profile[section])).toContain("react-native");
|
||||
});
|
||||
|
||||
const withCapabilities = buildProfileFromConfig(
|
||||
{
|
||||
...config,
|
||||
capabilities: ["core-android", "core-ios"],
|
||||
},
|
||||
defaultProfile
|
||||
);
|
||||
|
||||
dependencies.forEach((section) => {
|
||||
expect(Object.keys(withCapabilities[section])).not.toContain("react");
|
||||
expect(Object.keys(withCapabilities[section])).not.toContain(
|
||||
"react-native"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("inspect()", () => {
|
||||
const mockManifestProfile = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"react-native": "^0.63.2",
|
||||
},
|
||||
peerDependencies: {
|
||||
"react-native": "^0.63 || ^0.64",
|
||||
},
|
||||
devDependencies: {
|
||||
"react-native": "^0.63.2",
|
||||
},
|
||||
};
|
||||
|
||||
test("handles empty dependencies", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
};
|
||||
expect(inspect(manifest, mockManifestProfile, false)).toEqual([]);
|
||||
expect(inspect(manifest, mockManifestProfile, true)).toEqual([]);
|
||||
});
|
||||
|
||||
test("ignores unmanaged dependencies", () => {
|
||||
const dependencies = {
|
||||
"@babel/core": "^7.0.0",
|
||||
"react-native": "0.63.2",
|
||||
};
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies,
|
||||
};
|
||||
|
||||
const expectedChanges = [
|
||||
{
|
||||
name: "react-native",
|
||||
from: manifest.dependencies["react-native"],
|
||||
to: mockManifestProfile.dependencies["react-native"],
|
||||
section: "dependencies",
|
||||
},
|
||||
];
|
||||
|
||||
expect(inspect(manifest, mockManifestProfile, false)).toEqual(
|
||||
expectedChanges
|
||||
);
|
||||
expect(manifest.dependencies).toEqual(dependencies);
|
||||
});
|
||||
|
||||
test("inspects all dependency types", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"@babel/core": "^7.0.0",
|
||||
},
|
||||
peerDependencies: {
|
||||
"react-native": "0.63.2",
|
||||
},
|
||||
devDependencies: {
|
||||
"react-native": "0.63.2",
|
||||
},
|
||||
};
|
||||
|
||||
const expectedChanges = [
|
||||
{
|
||||
name: "react-native",
|
||||
from: manifest.peerDependencies["react-native"],
|
||||
to: mockManifestProfile.peerDependencies["react-native"],
|
||||
section: "peerDependencies",
|
||||
},
|
||||
{
|
||||
name: "react-native",
|
||||
from: manifest.devDependencies["react-native"],
|
||||
to: mockManifestProfile.devDependencies["react-native"],
|
||||
section: "devDependencies",
|
||||
},
|
||||
];
|
||||
|
||||
expect(inspect(manifest, mockManifestProfile, false)).toEqual(
|
||||
expectedChanges
|
||||
);
|
||||
});
|
||||
|
||||
test("modifies the manifest when `write: true`", () => {
|
||||
const dependencies = {
|
||||
"@babel/core": "^7.0.0",
|
||||
"react-native": "0.63.2",
|
||||
};
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: { ...dependencies },
|
||||
};
|
||||
|
||||
const expectedChanges = [
|
||||
{
|
||||
name: "react-native",
|
||||
from: manifest.dependencies["react-native"],
|
||||
to: mockManifestProfile.dependencies["react-native"],
|
||||
section: "dependencies",
|
||||
},
|
||||
];
|
||||
|
||||
expect(inspect(manifest, mockManifestProfile, true)).toEqual(
|
||||
expectedChanges
|
||||
);
|
||||
expect(manifest.dependencies).not.toEqual(dependencies);
|
||||
});
|
||||
|
||||
test("does not rewrite peerDependencies if superset", () => {
|
||||
const manifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
react: "^16.8.1",
|
||||
},
|
||||
peerDependencies: {
|
||||
metro: "*",
|
||||
react: ">=16.8.0 <18.0.0",
|
||||
"react-native": ">=0.64",
|
||||
},
|
||||
devDependencies: {},
|
||||
};
|
||||
const profile = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
react: "~17.0.1",
|
||||
},
|
||||
peerDependencies: {
|
||||
metro: "^0.66.2",
|
||||
react: "~17.0.1",
|
||||
"react-native": "^0.66.0-0",
|
||||
},
|
||||
devDependencies: {},
|
||||
};
|
||||
const expectedChanges = [
|
||||
{
|
||||
name: "react",
|
||||
from: manifest.dependencies["react"],
|
||||
to: profile.dependencies["react"],
|
||||
section: "dependencies",
|
||||
},
|
||||
];
|
||||
|
||||
expect(inspect(manifest, profile, false)).toEqual(expectedChanges);
|
||||
});
|
||||
});
|
||||
|
||||
describe("makeVigilantCommand()", () => {
|
||||
const rnxKitConfig = require("@rnx-kit/config");
|
||||
const fs = require("fs");
|
||||
|
||||
const consoleErrorSpy = jest.spyOn(global.console, "error");
|
||||
|
||||
beforeEach(() => {
|
||||
consoleErrorSpy.mockReset();
|
||||
fs.__setMockContent({});
|
||||
fs.__setMockFileWriter(() => {
|
||||
throw new Error("mock for fs.writeFileSync is not set");
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test("returns no command if no versions are specified", () => {
|
||||
expect(
|
||||
makeVigilantCommand({ versions: "", loose: false, write: false })
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
test("returns exit code 0 when there are no violations", () => {
|
||||
fs.__setMockContent({
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"react-native": "^0.63.2",
|
||||
},
|
||||
});
|
||||
|
||||
let didWrite = false;
|
||||
fs.__setMockFileWriter(() => {
|
||||
didWrite = true;
|
||||
});
|
||||
|
||||
const result = makeVigilantCommand({
|
||||
versions: "0.63",
|
||||
loose: false,
|
||||
write: false,
|
||||
})("package.json");
|
||||
expect(result).toBe(0);
|
||||
expect(didWrite).toBe(false);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("returns non-zero exit code when there are violations", () => {
|
||||
fs.__setMockContent({
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"react-native": "0.63.2",
|
||||
},
|
||||
});
|
||||
|
||||
let didWrite = false;
|
||||
fs.__setMockFileWriter(() => {
|
||||
didWrite = true;
|
||||
});
|
||||
|
||||
const result = makeVigilantCommand({
|
||||
versions: "0.63",
|
||||
loose: false,
|
||||
write: false,
|
||||
})("package.json");
|
||||
expect(result).not.toBe(0);
|
||||
expect(didWrite).toBe(false);
|
||||
expect(consoleErrorSpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
test("returns exit code 0 when writing", () => {
|
||||
fs.__setMockContent({
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"react-native": "0.63.2",
|
||||
},
|
||||
});
|
||||
|
||||
let didWrite = false;
|
||||
fs.__setMockFileWriter(() => {
|
||||
didWrite = true;
|
||||
});
|
||||
|
||||
const result = makeVigilantCommand({
|
||||
versions: "0.63",
|
||||
loose: false,
|
||||
write: true,
|
||||
})("package.json");
|
||||
expect(result).toBe(0);
|
||||
expect(didWrite).toBe(true);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("excludes specified packages", () => {
|
||||
fs.__setMockContent({
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"react-native": "0.59.10",
|
||||
},
|
||||
});
|
||||
|
||||
let didWrite = false;
|
||||
fs.__setMockFileWriter(() => {
|
||||
didWrite = true;
|
||||
});
|
||||
|
||||
const result = makeVigilantCommand({
|
||||
versions: "0.63",
|
||||
write: false,
|
||||
excludePackages: "@rnx-kit/dep-check",
|
||||
loose: false,
|
||||
})("package.json");
|
||||
expect(result).toBe(0);
|
||||
expect(didWrite).toBe(false);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test("uses package-specific custom profiles", () => {
|
||||
const fixture = `${__dirname}/__fixtures__/config-custom-profiles-only`;
|
||||
const kitConfig = {
|
||||
customProfiles: `${fixture}/packageSpecificProfiles.js`,
|
||||
};
|
||||
const inputManifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
peerDependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "0.64.0",
|
||||
},
|
||||
devDependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "0.64.0",
|
||||
},
|
||||
"rnx-kit": kitConfig,
|
||||
};
|
||||
|
||||
rnxKitConfig.__setMockConfig(kitConfig);
|
||||
fs.__setMockContent(inputManifest);
|
||||
|
||||
let manifest = undefined;
|
||||
fs.__setMockFileWriter((_, content) => {
|
||||
manifest = JSON.parse(content);
|
||||
});
|
||||
|
||||
const result = makeVigilantCommand({
|
||||
versions: "0.64,0.65",
|
||||
loose: false,
|
||||
write: true,
|
||||
})("package.json");
|
||||
expect(result).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(manifest).toEqual({
|
||||
...inputManifest,
|
||||
devDependencies: {
|
||||
react: "17.0.2",
|
||||
"react-native": "0.64.3",
|
||||
},
|
||||
peerDependencies: {
|
||||
react: "17.0.2",
|
||||
"react-native": "0.64.3 || 0.65.2 || ^0.64.2 || ^0.65.0",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("prefers package-specific React Native versions", () => {
|
||||
const fixture = `${__dirname}/__fixtures__/config-custom-profiles-only`;
|
||||
const kitConfig = {
|
||||
reactNativeVersion: "0.64",
|
||||
customProfiles: `${fixture}/packageSpecificProfiles.js`,
|
||||
};
|
||||
const inputManifest = {
|
||||
name: "@rnx-kit/dep-check",
|
||||
version: "1.0.0",
|
||||
peerDependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "0.64.0",
|
||||
},
|
||||
devDependencies: {
|
||||
react: "17.0.1",
|
||||
"react-native": "0.64.0",
|
||||
},
|
||||
"rnx-kit": kitConfig,
|
||||
};
|
||||
|
||||
rnxKitConfig.__setMockConfig(kitConfig);
|
||||
fs.__setMockContent(inputManifest);
|
||||
|
||||
let manifest = undefined;
|
||||
fs.__setMockFileWriter((_, content) => {
|
||||
manifest = JSON.parse(content);
|
||||
});
|
||||
|
||||
const result = makeVigilantCommand({
|
||||
versions: "0.64,0.65",
|
||||
loose: false,
|
||||
write: true,
|
||||
})("package.json");
|
||||
expect(result).toBe(0);
|
||||
expect(consoleErrorSpy).not.toBeCalled();
|
||||
expect(manifest).toEqual({
|
||||
...inputManifest,
|
||||
devDependencies: {
|
||||
react: "17.0.2",
|
||||
"react-native": "0.64.3",
|
||||
},
|
||||
peerDependencies: {
|
||||
react: "17.0.2",
|
||||
"react-native": "0.64.3 || ^0.64.2",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
Загрузка…
Ссылка в новой задаче