react-native-integrate
Version:
Automate integration of additional code into React Native projects
475 lines (474 loc) • 19.2 kB
JavaScript
"use strict";
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 mockRestoreBackupFiles = jest.spyOn(require('../../utils/upgrade/restoreBackupFiles'), 'restoreBackupFiles');
const mockRunUpgradeTasks = jest.spyOn(require('../../utils/upgrade/runUpgradeTasks'), 'runUpgradeTasks');
const constants_1 = require("../../constants");
const options_1 = require("../../options");
const upgrade_1 = require("../../upgrade");
const mockAll_1 = require("../mocks/mockAll");
describe('upgrade', () => {
beforeEach(() => {
options_1.options.get().manual = true;
mockSpawn.mockImplementationOnce(() => ({
on: (_event, cb) => {
cb(0);
},
stdout: {
on: (_event, cb) => {
cb('stdout');
},
},
stderr: {
on: (_event, cb) => {
cb('stderr');
},
},
}));
mockSpawn.mockImplementationOnce(() => ({
on: (_event, cb) => {
cb(0);
},
stdout: {
on: (_event, cb) => {
cb('stdout');
},
},
stderr: {
on: (_event, cb) => {
cb('stderr');
},
},
}));
});
it('should skip import when import path is empty', async () => {
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockAll_1.mockPrompter.log.message.mockClear();
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.message).toHaveBeenCalledWith(expect.stringContaining('skipping import from old project'));
});
it('should restore files', async () => {
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockRestoreBackupFiles.mockReturnValueOnce(Promise.resolve(true));
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.message).toHaveBeenCalledWith(expect.stringContaining('skipping import from old project'));
});
it('should handle restore error', async () => {
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockRestoreBackupFiles.mockRejectedValueOnce(new Error('test'));
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.message).toHaveBeenCalledWith(expect.stringContaining('skipping import from old project'));
});
it('should execute upgrade.yml', async () => {
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockRunUpgradeTasks.mockResolvedValueOnce({
didRun: true,
completedTaskCount: 1,
});
mockAll_1.mockPrompter.log.info.mockClear();
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.info).toHaveBeenCalledWith(expect.stringContaining('task(s) successfully'));
});
it('should handle upgrade.yml execution error', async () => {
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockRunUpgradeTasks.mockRejectedValueOnce(new Error('test'));
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('test'));
});
it('should handle upgrade.yml failed tasks', async () => {
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockRunUpgradeTasks.mockResolvedValueOnce({
didRun: true,
failedTaskCount: 1,
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('task(s) - please complete upgrade manually'));
});
it('should not run tasks when lock does not exist', async () => {
const spinner = mockAll_1.mockPrompter.spinner();
spinner.stop.mockReset();
const appDelegatePath = writeMockAppDelegate();
await (0, upgrade_1.upgrade)();
const content = mockFs.readFileSync(appDelegatePath);
expect(content).not.toContain('[FIRApp configure];');
expect(spinner.stop).toHaveBeenCalledWith(expect.stringContaining('integrate-lock.json not found'));
});
it('should run tasks when lock exists', async () => {
const lockPath = writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {
'mock-package': {
version: '^1.2.3',
integrated: true,
},
},
});
const appDelegatePath = writeMockAppDelegate();
await (0, upgrade_1.upgrade)();
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 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, upgrade_1.upgrade)();
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: {
'mock-package-fail': {
version: '1.2.3',
integrated: true,
},
},
});
await (0, upgrade_1.upgrade)();
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 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: {
'mock-package': {
version: '1.2.3',
integrated: true,
},
},
});
await (0, upgrade_1.upgrade)();
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: {
'mock-package': {
version: '1.2.3',
integrated: true,
},
},
});
await (0, upgrade_1.upgrade)();
const content = mockFs.readFileSync(lockPath);
expect(mockAll_1.mockPrompter.log.error).toHaveBeenCalledWith(expect.stringContaining('test error'));
expect(content).not.toContain('[FIRApp configure];');
});
it('should re-integrate 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: {
'mock-package-with-deps': {
version: '1.2.3',
integrated: true,
},
'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, upgrade_1.upgrade)();
content = mockFs.readFileSync(appDelegatePath);
expect(content).toContain('[FIRApp configure];');
expect(content).toContain('// with-deps');
});
it('should warn and exit when package is not installed', async () => {
(0, mockAll_1.writeMockProject)({
name: 'mock-project',
version: '0.0.0',
description: 'Mock project',
dependencies: {},
});
writeMockLock({
lockfileVersion: constants_1.Constants.CURRENT_LOCK_VERSION,
packages: {
'mock-package': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('is not installed'));
});
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: {
'mock-package-with-deps': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.warning).toHaveBeenCalledWith(expect.stringContaining('is not integrated'));
});
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: {
'mock-package-with-min-rn': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
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: {
'mock-package-with-min-rn': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
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: {
'mock-package-with-min-rn': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
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: {
'mock-package-with-invalid-min-rn': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
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: {
'mock-package-with-min-rn': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
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: {
'mock-package-with-min-v': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
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: {
'mock-package-with-min-v': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
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: {
'mock-package-with-invalid-min-v': {
version: '1.2.3',
integrated: true,
},
},
});
mockAll_1.mockPrompter.log.warning.mockClear();
await (0, upgrade_1.upgrade)();
expect(mockAll_1.mockPrompter.log.warning).not.toHaveBeenCalledWith(expect.stringContaining('requires React Native'));
});
});