test(android): add tests for Gradle utility functions (#687)
This commit is contained in:
Родитель
44c9118f76
Коммит
2e42594099
|
@ -11,7 +11,6 @@ runs:
|
|||
with:
|
||||
node-version: 14
|
||||
- name: Set up JDK
|
||||
if: ${{ inputs.platform == 'android' }}
|
||||
uses: actions/setup-java@v2.5.0
|
||||
with:
|
||||
distribution: temurin
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
*.tgz
|
||||
*.xcworkspace/
|
||||
.DS_Store
|
||||
.android-test-*
|
||||
.gradle/
|
||||
.idea/
|
||||
.vs/
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
// @ts-check
|
||||
// istanbul ignore file
|
||||
|
||||
const { spawnSync } = require("child_process");
|
||||
const fs = require("fs/promises");
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const { version: targetVersion } = require("react-native/package.json");
|
||||
const { gatherConfig, writeAllFiles } = require("../../scripts/configure");
|
||||
|
||||
/**
|
||||
* Joins the strings if an array is passed, otherwise returns the string.
|
||||
* @param {string | string[]} strings
|
||||
* @returns
|
||||
*/
|
||||
function joinStrings(strings, separator = "") {
|
||||
return Array.isArray(strings) ? strings.join(separator) : strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns project path given name.
|
||||
* @param {string} name
|
||||
*/
|
||||
function projectPath(name) {
|
||||
return `.android-test-${name}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a React Native project.
|
||||
* @param {string} name
|
||||
* @param {import("../../scripts/configure").ConfigureParams["platforms"]} platforms
|
||||
* @param {Record<string, string | string[]>=} setupFiles
|
||||
*/
|
||||
async function makeProject(name, platforms, setupFiles = {}) {
|
||||
const packagePath = projectPath(name);
|
||||
const { files } = gatherConfig({
|
||||
name,
|
||||
packagePath,
|
||||
testAppPath: path.resolve(__dirname, "..", ".."),
|
||||
targetVersion,
|
||||
platforms,
|
||||
flatten: true,
|
||||
force: true,
|
||||
init: true,
|
||||
});
|
||||
|
||||
await writeAllFiles(files, packagePath);
|
||||
|
||||
try {
|
||||
await fs.symlink(
|
||||
path.resolve(__dirname, "..", "..", "example", "node_modules"),
|
||||
path.join(packagePath, "node_modules"),
|
||||
"dir"
|
||||
);
|
||||
} catch (e) {
|
||||
// @ts-ignore
|
||||
if (e.code !== "EEXIST") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
Object.entries(setupFiles).map(([filename, content]) => {
|
||||
const p = path.join(packagePath, filename);
|
||||
return fs
|
||||
.mkdir(path.dirname(p), { recursive: true })
|
||||
.then(() => fs.writeFile(p, joinStrings(content, "\n")));
|
||||
})
|
||||
);
|
||||
|
||||
return packagePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes specified project.
|
||||
* @param {string} name
|
||||
*/
|
||||
function removeProject(name) {
|
||||
fs.rm(projectPath(name), {
|
||||
maxRetries: 3,
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs Gradle in specified directory.
|
||||
* @param {string} cwd
|
||||
* @param {...string} args arguments
|
||||
* @returns
|
||||
*/
|
||||
function runGradle(cwd, ...args) {
|
||||
const gradlew = os.platform() === "win32" ? "gradlew.bat" : "./gradlew";
|
||||
return spawnSync(gradlew, args, { cwd, encoding: "utf-8" });
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new React Native project and runs Gradle.
|
||||
* @param {string} name
|
||||
* @param {import("../../scripts/configure").ConfigureParams["platforms"]} platforms
|
||||
* @param {Record<string, string | string[]>=} setupFiles
|
||||
*/
|
||||
async function runGradleWithProject(name, platforms, setupFiles = {}) {
|
||||
const projectPath = await makeProject(name, platforms, setupFiles);
|
||||
const result = runGradle(projectPath);
|
||||
const stdout = joinStrings(result.stdout);
|
||||
if (result.stderr) {
|
||||
console.log(stdout);
|
||||
console.error(joinStrings(result.stderr));
|
||||
}
|
||||
return { ...result, stdout };
|
||||
}
|
||||
|
||||
exports.removeProject = removeProject;
|
||||
exports.runGradleWithProject = runGradleWithProject;
|
|
@ -0,0 +1,236 @@
|
|||
// @ts-check
|
||||
"use strict";
|
||||
|
||||
describe("test-app-util", () => {
|
||||
const { removeProject, runGradleWithProject } = require("./gradle");
|
||||
|
||||
const buildGradle = [
|
||||
"buildscript {",
|
||||
' def androidTestAppDir = "node_modules/react-native-test-app/android"',
|
||||
' apply(from: "${androidTestAppDir}/dependencies.gradle")',
|
||||
' apply(from: "${androidTestAppDir}/test-app-util.gradle")',
|
||||
"",
|
||||
" repositories {",
|
||||
" mavenCentral()",
|
||||
" google()",
|
||||
" }",
|
||||
"",
|
||||
" dependencies {",
|
||||
' classpath "com.android.tools.build:gradle:$androidPluginVersion"',
|
||||
' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"',
|
||||
" }",
|
||||
"}",
|
||||
"",
|
||||
];
|
||||
|
||||
const defaultTestProject = "TestAppUtilTest";
|
||||
|
||||
/**
|
||||
* Runs Gradle in test project.
|
||||
* @param {Record<string, string | string[]>=} setupFiles
|
||||
*/
|
||||
function runGradle(setupFiles) {
|
||||
return runGradleWithProject(defaultTestProject, ["android"], setupFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns version number.
|
||||
* @param {string} version
|
||||
* @returns
|
||||
*/
|
||||
function toVersionNumber(version) {
|
||||
const [major, minor, patch] = version.split(".");
|
||||
return Number(major) * 10000 + Number(minor) * 100 + Number(patch);
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
removeProject(defaultTestProject);
|
||||
});
|
||||
|
||||
test("getAppName() returns `name` if `displayName` is omitted", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"app.json": JSON.stringify({
|
||||
name: "AppName",
|
||||
resources: ["dist/res", "dist/main.android.jsbundle"],
|
||||
}),
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getAppName() = " + ext.getAppName())',
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getAppName() = AppName");
|
||||
});
|
||||
|
||||
test("getAppName() returns `displayName` if set", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"app.json": JSON.stringify({
|
||||
name: "AppName",
|
||||
displayName: "AppDisplayName",
|
||||
resources: ["dist/res", "dist/main.android.jsbundle"],
|
||||
}),
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getAppName() = " + ext.getAppName())',
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getAppName() = AppDisplayName");
|
||||
});
|
||||
|
||||
test("getApplicationId() returns default id", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"app.json": JSON.stringify({
|
||||
name: "AppName",
|
||||
displayName: "AppDisplayName",
|
||||
resources: ["dist/res", "dist/main.android.jsbundle"],
|
||||
}),
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getApplicationId() = " + ext.getApplicationId())',
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getApplicationId() = com.microsoft.reacttestapp");
|
||||
});
|
||||
|
||||
test("getApplicationId() returns package name", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"app.json": JSON.stringify({
|
||||
name: "AppName",
|
||||
displayName: "AppDisplayName",
|
||||
android: {
|
||||
package: "com.contoso.application.id",
|
||||
},
|
||||
resources: ["dist/res", "dist/main.android.jsbundle"],
|
||||
}),
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getApplicationId() = " + ext.getApplicationId())',
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getApplicationId() = com.contoso.application.id");
|
||||
});
|
||||
|
||||
test("getFlipperRecommendedVersion() returns `null` if unsupported", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getFlipperRecommendedVersion() = " + ext.getFlipperRecommendedVersion(file("${rootDir}/no-flipper")))',
|
||||
],
|
||||
"no-flipper/node_modules/react-native/template/android/gradle.properties":
|
||||
"",
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getFlipperRecommendedVersion() = null");
|
||||
});
|
||||
|
||||
test("getFlipperRecommendedVersion() returns version number if supported", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getFlipperRecommendedVersion() = " + ext.getFlipperRecommendedVersion(rootDir))',
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toMatch(/getFlipperRecommendedVersion\(\) = \d+\.\d+\.\d+/);
|
||||
});
|
||||
|
||||
test("getFlipperVersion() returns `null` if unsupported", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getFlipperVersion() = " + ext.getFlipperVersion(file("${rootDir}/no-flipper")))',
|
||||
],
|
||||
"no-flipper/node_modules/react-native/template/android/gradle.properties":
|
||||
"",
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getFlipperVersion() = null");
|
||||
});
|
||||
|
||||
test("getFlipperVersion() returns recommended version if unset", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getFlipperVersion() = " + ext.getFlipperVersion(rootDir))',
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toMatch(/getFlipperVersion\(\) = \d+\.\d+\.\d+/);
|
||||
});
|
||||
|
||||
test("getFlipperVersion() returns user set version", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getFlipperVersion() = " + ext.getFlipperVersion(rootDir))',
|
||||
],
|
||||
"gradle.properties": [
|
||||
"android.useAndroidX=true",
|
||||
"android.enableJetifier=true",
|
||||
"FLIPPER_VERSION=0.0.0-test",
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getFlipperVersion() = 0.0.0-test");
|
||||
});
|
||||
|
||||
test("getFlipperVersion() returns null if disabled", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getFlipperVersion() = " + ext.getFlipperVersion(rootDir))',
|
||||
],
|
||||
"gradle.properties": [
|
||||
"android.useAndroidX=true",
|
||||
"android.enableJetifier=true",
|
||||
"FLIPPER_VERSION=false",
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain("getFlipperVersion() = null");
|
||||
});
|
||||
|
||||
test("getReactNativeVersionNumber() returns react-native version as a number", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getReactNativeVersionNumber() = " + ext.getReactNativeVersionNumber(rootDir))',
|
||||
],
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
|
||||
const { version } = require("react-native/package.json");
|
||||
|
||||
expect(stdout).toContain(
|
||||
`getReactNativeVersionNumber() = ${toVersionNumber(version)}`
|
||||
);
|
||||
});
|
||||
|
||||
test("getReactNativeVersionNumber() handles pre-release identifiers", async () => {
|
||||
const { status, stdout } = await runGradle({
|
||||
"build.gradle": [
|
||||
...buildGradle,
|
||||
'println("getReactNativeVersionNumber() = " + ext.getReactNativeVersionNumber(file("${rootDir}/pre-release-version")))',
|
||||
],
|
||||
"pre-release-version/node_modules/react-native/package.json":
|
||||
JSON.stringify({ name: "react-native", version: "1.2.3-053c2b4be" }),
|
||||
});
|
||||
|
||||
expect(status).toBe(0);
|
||||
expect(stdout).toContain(`getReactNativeVersionNumber() = 10203`);
|
||||
});
|
||||
});
|
Загрузка…
Ссылка в новой задаче