react-native-integrate
Version:
Automate integration of additional code into React Native projects
373 lines (372 loc) • 15.5 kB
JavaScript
"use strict";
/* eslint-disable @typescript-eslint/no-unsafe-call */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const { mockFs } = require('../../mocks/mockAll');
const mockWaitForFile = jest.spyOn(require('../../../utils/waitForFile'), 'waitForFile');
const path_1 = __importDefault(require("path"));
const fsTask_1 = require("../../../tasks/fsTask");
const getProjectPath_1 = require("../../../utils/getProjectPath");
const variables_1 = require("../../../variables");
const mockAll_1 = require("../../mocks/mockAll");
const projectFullPath = path_1.default.resolve(__dirname, '../../mock-project');
describe('fsTask', () => {
beforeEach(() => {
mockFs.writeFileSync('/test/file.json', 'test-content');
});
it('should handle upgrade when file is not in .upgrade folder', async () => {
variables_1.variables.set('__UPGRADE__', true);
mockAll_1.mockPrompter.text.mockReset();
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter mock file path
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '/test/file.json');
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.text).toHaveBeenCalled();
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-content');
variables_1.variables.clear();
});
it('should handle upgrade when file is in upgrade.json but not in files folder', async () => {
variables_1.variables.set('__UPGRADE__', true);
mockFs.writeFileSync(path_1.default.join((0, getProjectPath_1.getProjectPath)(), '.upgrade', 'packages', 'test-package', 'upgrade.json'), JSON.stringify({
files: {
'android/file.json': 'file.json',
},
}, null, 2));
mockAll_1.mockPrompter.text.mockReset();
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter mock file path
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '/test/file.json');
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.text).toHaveBeenCalled();
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-content');
variables_1.variables.clear();
});
it('should handle upgrade when file is in upgrade.json and in files folder', async () => {
variables_1.variables.set('__UPGRADE__', true);
mockFs.writeFileSync(path_1.default.join((0, getProjectPath_1.getProjectPath)(), '.upgrade', 'packages', 'test-package', 'upgrade.json'), JSON.stringify({
files: {
'android/file.json': 'file.json',
},
}, null, 2));
mockFs.writeFileSync(path_1.default.join((0, getProjectPath_1.getProjectPath)(), '.upgrade', 'packages', 'test-package', 'files', 'file.json'), 'test-upgrade-content');
mockAll_1.mockPrompter.text.mockReset();
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter mock file path
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '/test/file.json');
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.text).not.toHaveBeenCalled();
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-upgrade-content');
variables_1.variables.clear();
});
it('should copy entered file to destination', async () => {
mockAll_1.mockPrompter.text.mockReset();
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter mock file path
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '/test/file.json');
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.text).toHaveBeenCalled();
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-content');
});
it('should throw when copy destination is out of project', async () => {
mockAll_1.mockPrompter.text.mockReset();
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: '../somewhere/file.json',
},
],
};
// enter mock file path
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '/test/file.json');
await expect((0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
})).rejects.toThrowError('invalid destination path');
});
it('should skip if condition not met', async () => {
mockAll_1.mockPrompter.text.mockReset();
const task = {
task: 'fs',
actions: [
{
when: { test: 'random' },
copyFile: 'file.json',
destination: '../somewhere/file.json',
},
],
};
// enter mock file path
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '/test/file.json');
await expect((0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
})).resolves.not.toThrow();
});
it('should skip if waitForFile throws', async () => {
mockAll_1.mockPrompter.text.mockReset();
mockAll_1.mockPrompter.confirm.mockReset();
mockAll_1.mockPrompter.log.message.mockReset();
// simulate file exists in path
mockFs.writeFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'), 'test-content');
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter empty string
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockAll_1.mockPrompter.confirm.mockImplementationOnce(() => true);
mockWaitForFile.mockImplementationOnce(() => {
return Promise.reject(new Error('skip'));
});
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.log.message).toHaveBeenCalledWith(expect.stringContaining('skipped copy operation'));
});
it('should wait for user to copy file to destination when not exists', async () => {
mockAll_1.mockPrompter.text.mockReset();
mockAll_1.mockPrompter.confirm.mockReset();
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter empty string
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockAll_1.mockPrompter.confirm.mockImplementationOnce(() => true);
mockWaitForFile.mockImplementationOnce(() => {
// simulate manually writing file
mockFs.writeFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'), 'test-content');
return Promise.resolve(true);
});
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.text).toHaveBeenCalled();
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-content');
});
it('should wait for user to copy file to destination when exists', async () => {
mockAll_1.mockPrompter.text.mockReset();
mockAll_1.mockPrompter.confirm.mockReset();
mockAll_1.mockPrompter.log.message.mockReset();
// simulate file exists in path
mockFs.writeFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'), 'test-content');
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter empty string
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '');
mockAll_1.mockPrompter.confirm.mockImplementationOnce(() => true);
mockWaitForFile.mockImplementationOnce(() => {
return Promise.resolve(false);
});
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.text).toHaveBeenCalled();
expect(mockAll_1.mockPrompter.confirm).toHaveBeenCalled();
expect(mockAll_1.mockPrompter.log.message).toHaveBeenCalledWith(expect.stringContaining('file was updated'));
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-content');
});
it('should handle when user skip copying a file to destination when exists', async () => {
mockAll_1.mockPrompter.text.mockReset();
mockAll_1.mockPrompter.confirm.mockReset();
mockAll_1.mockPrompter.log.message.mockReset();
// simulate file exists in path
mockFs.writeFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'), 'test-content');
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter empty string
mockAll_1.mockPrompter.text.mockImplementation(() => '');
mockAll_1.mockPrompter.confirm.mockImplementationOnce(() => false);
mockWaitForFile.mockImplementationOnce(() => {
return Promise.resolve(false);
});
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.text).toHaveBeenCalled();
expect(mockAll_1.mockPrompter.confirm).toHaveBeenCalled();
expect(mockAll_1.mockPrompter.confirm).toReturnWith(false);
expect(mockAll_1.mockPrompter.log.message).toHaveBeenCalledWith(expect.stringContaining('skipped copy operation'));
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-content');
});
it('should remove entered file', async () => {
mockFs.writeFileSync(path_1.default.join(projectFullPath, 'android', 'file-to-delete.json'), 'test-content');
mockAll_1.mockPrompter.log.message.mockReset();
const task = {
task: 'fs',
actions: [
{
removeFile: 'android/file-to-delete.json',
},
],
};
// enter mock file path
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockFs.existsSync(path_1.default.join(projectFullPath, 'android', 'file-to-delete.json'))).toEqual(false);
});
it('should skip remove entered file when not exists', async () => {
mockAll_1.mockPrompter.log.message.mockReset();
expect(mockFs.existsSync(path_1.default.join(projectFullPath, 'android', 'file-to-delete.json'))).toEqual(false);
const task = {
task: 'fs',
actions: [
{
removeFile: 'file-to-delete.json',
},
],
};
// enter mock file path
await (0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockAll_1.mockPrompter.log.message).toHaveBeenCalledWith(expect.stringContaining('skipped remove operation'));
});
it('should throw when strict remove file not exists', async () => {
mockAll_1.mockPrompter.log.message.mockReset();
expect(mockFs.existsSync(path_1.default.join(projectFullPath, 'android', 'file-to-delete.json'))).toEqual(false);
const task = {
task: 'fs',
actions: [
{
removeFile: 'file-to-delete.json',
strict: true,
},
],
};
// enter mock file path
await expect((0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
})).rejects.toThrowError('does not exist');
});
it('should throw when remove destination is out of project', async () => {
const task = {
task: 'fs',
actions: [
{
removeFile: '../somewhere/file-to-delete.json',
},
],
};
// enter mock file path
await expect((0, fsTask_1.fsTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
})).rejects.toThrowError('invalid path to remove');
});
describe('runTask', () => {
it('should run fs tasks', async () => {
const task = {
task: 'fs',
actions: [
{
copyFile: 'file.json',
destination: 'android/file.json',
},
],
};
// enter mock file path
mockAll_1.mockPrompter.text.mockImplementationOnce(() => '/test/file.json');
await (0, fsTask_1.runTask)({
configPath: 'path/to/config',
task: task,
packageName: 'test-package',
});
expect(mockFs.readFileSync(path_1.default.join(projectFullPath, 'android', 'file.json'))).toEqual('test-content');
});
});
});