react-native-integrate
Version:
Automate integration of additional code into React Native projects
467 lines (466 loc) • 19.4 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable @typescript-eslint/no-unsafe-call */
const { mockFs, writeMockAppDelegate, writeMockLock, } = require('../mocks/mockAll');
const mockSpawn = jest.spyOn(require('child_process'), 'spawn');
const mockRunTask = jest.spyOn(require('../../utils/runTask'), 'runTask');
const mockParseConfig = jest.spyOn(require('../../utils/parseConfig'), 'parseConfig');
const path_1 = __importDefault(require("path"));
const constants_1 = require("../../constants");
const integrate_1 = require("../../integrate");
const options_1 = require("../../options");
const mockAll_1 = require("../mocks/mockAll");
describe('integrate', () => {
beforeEach(() => {
mockSpawn.mockImplementationOnce(() => ({
on: (_event, cb) => {
cb(0);
},
stdout: {
on: (_event, cb) => {
cb('stdout');
},
},
stderr: {
on: (_event, cb) => {
cb('stderr');
},
},
}));
});
it('should not run tasks when lock does not exist (first run)', async () => {
const spinner = mockAll_1.mockPrompter.spinner();
spinner.stop.mockReset();
const appDelegatePath = writeMockAppDelegate();
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(appDelegatePath);
expect(content).not.toContain('[FIRApp configure];');
expect(spinner.stop).toHaveBeenCalledWith(expect.stringContaining('first run'));
});
it('should run tasks when lock exists', async () => {
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
const appDelegatePath = writeMockAppDelegate();
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(appDelegatePath);
expect(content).toContain('[FIRApp configure];');
const lockContent = mockFs.readFileSync(lockPath);
const lockData = JSON.parse(lockContent);
expect(lockData.packages['mock-package']).toEqual({
version: '^1.2.3',
integrated: true,
});
});
it('should run tasks for a package when lock does not exist', async () => {
const lockPath = path_1.default.resolve(__dirname, `../mock-project/${constants_1.Constants.LOCK_FILE_NAME}`);
const appDelegatePath = writeMockAppDelegate();
await (0, integrate_1.integrate)('mock-package');
const content = mockFs.readFileSync(appDelegatePath);
expect(content).toContain('[FIRApp configure];');
const lockContent = mockFs.readFileSync(lockPath);
const lockData = JSON.parse(lockContent);
expect(lockData.packages['mock-package']).toEqual({
version: '^1.2.3',
integrated: true,
});
});
it('should run tasks for a package when lock exist', async () => {
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
const appDelegatePath = writeMockAppDelegate();
await (0, integrate_1.integrate)('mock-package');
const content = mockFs.readFileSync(appDelegatePath);
expect(content).toContain('[FIRApp configure];');
const lockContent = mockFs.readFileSync(lockPath);
const lockData = JSON.parse(lockContent);
expect(lockData.packages['mock-package']).toEqual({
version: '^1.2.3',
integrated: true,
});
});
it('should handle package that doesnt exist', async () => {
const appDelegatePath = writeMockAppDelegate();
await (0, integrate_1.integrate)('random-package');
const content = mockFs.readFileSync(appDelegatePath);
expect(content).not.toContain('[FIRApp configure];');
});
it('should handle package that doesnt have config', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-fail': '^1.2.3',
},
});
const appDelegatePath = writeMockAppDelegate();
await (0, integrate_1.integrate)('mock-package-fail');
const content = mockFs.readFileSync(appDelegatePath);
expect(content).not.toContain('[FIRApp configure];');
});
it('should handle deleted packages', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {},
});
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {
'deleted-package': {
version: '1.2.3',
integrated: true,
},
},
});
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(lockPath);
const lockData = JSON.parse(content);
expect(lockData.packages).toEqual({});
});
it('should handle no changes', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package': '^1.2.3',
},
});
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {
'mock-package': {
version: '1.2.3',
integrated: true,
},
},
});
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(lockPath);
const lockData = JSON.parse(content);
expect(lockData.packages['mock-package']).toEqual({
version: '1.2.3',
integrated: true,
});
});
it('should handle packages with no config', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-fail': '^1.2.3',
},
});
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(lockPath);
const lockData = JSON.parse(content);
// console.log('mockFs',mockFs.getStore());
expect(lockData.packages['mock-package']).toEqual(undefined);
});
it('should handle user rejecting to integrate', async () => {
options_1.options.get().interactive = true;
mockAll_1.mockPrompter.confirm.mockImplementationOnce(() => false);
mockAll_1.mockPrompter.log.step.mockReset();
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(lockPath);
expect(mockAll_1.mockPrompter.log.step).toHaveBeenCalledWith(expect.stringContaining('skipped package integration'));
expect(content).not.toContain('[FIRApp configure];');
});
it('should handle task errors', async () => {
mockRunTask.mockImplementationOnce(() => {
throw new Error('test error');
});
mockAll_1.mockPrompter.log.error.mockReset();
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(lockPath);
expect(mockAll_1.mockPrompter.log.error).toHaveBeenCalledWith(expect.stringContaining('test error'));
expect(content).not.toContain('[FIRApp configure];');
});
it('should handle parse error', async () => {
mockParseConfig.mockImplementationOnce(() => {
throw new Error('test error');
});
mockAll_1.mockPrompter.log.error.mockReset();
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(lockPath);
expect(mockAll_1.mockPrompter.log.error).toHaveBeenCalledWith(expect.stringContaining('test error'));
expect(content).not.toContain('[FIRApp configure];');
});
it('should add dependencies to integration queue', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-deps': '^1.2.3',
'react-native': '^0.0.0',
'dep-package': '^1.2.3',
'dep-package-2': '^1.2.3',
},
});
const appDelegatePath = writeMockAppDelegate();
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
let content = mockFs.readFileSync(appDelegatePath);
expect(content).not.toContain('[FIRApp configure];');
await (0, integrate_1.integrate)();
content = mockFs.readFileSync(appDelegatePath);
expect(content).toContain('[FIRApp configure];');
expect(content).toContain('// with-deps');
});
it('should skip dependencies when already integrated', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-deps': '^1.2.3',
'react-native': '^0.0.0',
'dep-package': '^1.2.3',
'dep-package-2': '^1.2.3',
},
});
const appDelegatePath = writeMockAppDelegate();
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {
'dep-package': {
version: '1.2.3',
integrated: true,
},
'dep-package-2': {
version: '1.2.3',
integrated: true,
},
},
});
let content = mockFs.readFileSync(appDelegatePath);
expect(content).not.toContain('[FIRApp configure];');
await (0, integrate_1.integrate)();
content = mockFs.readFileSync(appDelegatePath);
expect(content).not.toContain('[FIRApp configure];');
expect(content).toContain('// with-deps');
});
it('should add installed but non integrated dependencies to integration queue', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-deps': '^1.2.3',
'react-native': '^0.0.0',
'dep-package': '^1.2.3',
'dep-package-2': '^1.2.3',
},
});
const appDelegatePath = writeMockAppDelegate();
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {
'dep-package': {
version: '1.2.3',
integrated: false,
},
'dep-package-2': {
version: '1.2.3',
integrated: false,
},
},
});
mockAll_1.mockPrompter.log.info.mockClear();
await (0, integrate_1.integrate)();
const content = mockFs.readFileSync(appDelegatePath);
expect(content).toContain('[FIRApp configure];');
expect(content).toContain('// with-deps');
expect(mockAll_1.mockPrompter.log.info).toHaveBeenCalledWith(expect.stringContaining('has dependencies that require integration'));
});
it('should warn and exit when dependencies is not installed', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-deps': '^1.2.3',
'react-native': '^0.0.0',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('please install it first and try again'));
});
it('should warn and exit when minimum rn version is not installed', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-min-rn': '^1.2.3',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('React Native not installed'));
});
it('should warn and exit when minimum rn version is less than installed one', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-min-rn': '^1.2.3',
'react-native': '^0.0.0',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('requires React Native'));
});
it('should not warn and exit when minimum rn version is higher than installed one', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-min-rn': '^1.2.3',
'react-native': '^1.0.0',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).not.toHaveBeenCalledWith(expect.stringContaining('requires React Native'));
});
it('should not warn and exit when minimum rn version is invalid', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-invalid-min-rn': '^1.2.3',
'react-native': '^1.2.3',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).not.toHaveBeenCalledWith(expect.stringContaining('requires React Native'));
});
it('should not warn and exit when rn version is invalid', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-min-rn': '^1.2.3',
'react-native': '^invalid',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).not.toHaveBeenCalledWith(expect.stringContaining('requires React Native'));
});
it('should warn and exit when minimum package version is not installed', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-min-v': '^0.0.0',
'react-native': '^0.0.0',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('requires version'));
});
it('should not warn and exit when minimum package version is higher than installed one', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-min-v': '^1.2.3',
'react-native': '^0.0.0',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).not.toHaveBeenCalledWith(expect.stringContaining('requires React Native'));
});
it('should not warn and exit when minimum package version is invalid', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {
'mock-package-with-invalid-min-v': '^invalid',
'react-native': '^0.0.0',
},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, integrate_1.integrate)();
expect(mockAll_1.mockPrompter.log.warning).not.toHaveBeenCalledWith(expect.stringContaining('requires React Native'));
});
});