Skip to content

Commit ebc052f

Browse files
author
Murat
committed
feat(upgrade): add pre_install upgrade stage
1 parent 7175c3e commit ebc052f

File tree

10 files changed

+221
-156
lines changed

10 files changed

+221
-156
lines changed

src/__tests__/unit/upgrade-cli.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require('../mocks/mockAll');
2+
const mockSpawn = jest.spyOn(require('child_process'), 'spawn');
23

34
import { resolve } from 'path';
45
import * as process from 'process';
@@ -12,6 +13,21 @@ describe('upgrade-cli', () => {
1213
debug: false,
1314
manual: true,
1415
}));
16+
mockSpawn.mockImplementationOnce(() => ({
17+
on: (_event: string, cb: (exitCode: number) => void) => {
18+
cb(0);
19+
},
20+
stdout: {
21+
on: (_event: string, cb: (...args: any[]) => void) => {
22+
cb('stdout');
23+
},
24+
},
25+
stderr: {
26+
on: (_event: string, cb: (...args: any[]) => void) => {
27+
cb('stderr');
28+
},
29+
},
30+
}));
1531
const mock = jest.spyOn(require('../../upgrade'), 'upgrade');
1632
const cli = require(resolve(__dirname, '../../upgrade-cli'));
1733

src/__tests__/unit/upgrade.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const {
44
writeMockAppDelegate,
55
writeMockLock,
66
} = require('../mocks/mockAll');
7+
const mockSpawn = jest.spyOn(require('child_process'), 'spawn');
78

89
const mockRunTask = jest.spyOn(require('../../utils/runTask'), 'runTask');
910
const mockParseConfig = jest.spyOn(
@@ -27,6 +28,21 @@ import { mockPrompter, writeMockProject } from '../mocks/mockAll';
2728
describe('upgrade', () => {
2829
beforeEach(() => {
2930
options.get().manual = true;
31+
mockSpawn.mockImplementationOnce(() => ({
32+
on: (_event: string, cb: (exitCode: number) => void) => {
33+
cb(0);
34+
},
35+
stdout: {
36+
on: (_event: string, cb: (...args: any[]) => void) => {
37+
cb('stdout');
38+
},
39+
},
40+
stderr: {
41+
on: (_event: string, cb: (...args: any[]) => void) => {
42+
cb('stderr');
43+
},
44+
},
45+
}));
3046
});
3147
it('should skip import when import path is empty', async () => {
3248
mockPrompter.text.mockImplementationOnce(() => '');

src/__tests__/unit/utils/upgrade/other/importPackageJson.spec.ts

Lines changed: 85 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { getProjectPath } from '../../../../../utils/getProjectPath';
99
import {
1010
getInstallCommand,
1111
importPackageJson,
12+
installModules,
1213
} from '../../../../../utils/upgrade/other/importPackageJson';
1314
import { mockFs } from '../../../../mocks/mockFs';
1415
import { mockPrompter } from '../../../../mocks/mockPrompter';
@@ -47,22 +48,6 @@ describe('importPackageJson', () => {
4748
expect(importGetter).toBeTruthy();
4849
expect(importGetter.value).toEqual('[email protected]');
4950

50-
mockSpawn.mockImplementationOnce(() => ({
51-
on: (_event: string, cb: (exitCode: number) => void) => {
52-
cb(0);
53-
},
54-
stdout: {
55-
on: (_event: string, cb: (...args: any[]) => void) => {
56-
cb('stdout');
57-
},
58-
},
59-
stderr: {
60-
on: (_event: string, cb: (...args: any[]) => void) => {
61-
cb('stderr');
62-
},
63-
},
64-
}));
65-
6651
await importGetter.apply();
6752

6853
expect(
@@ -71,44 +56,6 @@ describe('importPackageJson', () => {
7156
)
7257
).toContain('non-integrated-mock-package');
7358
});
74-
it('should get package.json and handle failed module installation', async () => {
75-
mockFs.writeFileSync(
76-
'/oldProject/' + Constants.PACKAGE_JSON_FILE_NAME,
77-
JSON.stringify(
78-
{
79-
name: 'test',
80-
dependencies: {
81-
'react-native': '1.0.0',
82-
'some-package': '1.0.0',
83-
},
84-
} as PackageJsonType,
85-
null,
86-
2
87-
)
88-
);
89-
90-
const importGetter = importPackageJson('/oldProject') as ImportGetter;
91-
92-
mockSpawn.mockImplementationOnce(() => ({
93-
on: (_event: string, cb: (exitCode: number) => void) => {
94-
cb(1);
95-
},
96-
stdout: {
97-
on: (_event: string, cb: (...args: any[]) => void) => {
98-
cb('stdout');
99-
},
100-
},
101-
stderr: {
102-
on: (_event: string, cb: (...args: any[]) => void) => {
103-
cb('stderr');
104-
},
105-
},
106-
}));
107-
mockPrompter.multiselect.mockClear();
108-
109-
await importGetter.apply();
110-
expect(mockPrompter.multiselect).toHaveBeenCalled();
111-
});
11259
it('should get package.json on windows', async () => {
11360
mockFs.writeFileSync(
11461
'/oldProject/' + Constants.PACKAGE_JSON_FILE_NAME,
@@ -131,24 +78,7 @@ describe('importPackageJson', () => {
13178

13279
const importGetter = importPackageJson('/oldProject') as ImportGetter;
13380

134-
mockSpawn.mockImplementationOnce(() => ({
135-
on: (_event: string, cb: (exitCode: number) => void) => {
136-
cb(0);
137-
},
138-
stdout: {
139-
on: (_event: string, cb: (...args: any[]) => void) => {
140-
cb('stdout');
141-
},
142-
},
143-
stderr: {
144-
on: (_event: string, cb: (...args: any[]) => void) => {
145-
cb('stderr');
146-
},
147-
},
148-
}));
149-
15081
await importGetter.apply();
151-
expect(mockSpawn).toHaveBeenCalledWith('npm', ['install'], { shell: true });
15282

15383
Object.defineProperty(process, 'platform', {
15484
value: originalPlatform,
@@ -202,22 +132,6 @@ describe('importPackageJson', () => {
202132

203133
const importGetter = importPackageJson('/oldProject') as ImportGetter;
204134

205-
mockSpawn.mockImplementationOnce(() => ({
206-
on: (_event: string, cb: (exitCode: number) => void) => {
207-
cb(0);
208-
},
209-
stdout: {
210-
on: (_event: string, cb: (...args: any[]) => void) => {
211-
cb('stdout');
212-
},
213-
},
214-
stderr: {
215-
on: (_event: string, cb: (...args: any[]) => void) => {
216-
cb('stderr');
217-
},
218-
},
219-
}));
220-
221135
await importGetter.apply();
222136

223137
expect(
@@ -232,6 +146,90 @@ describe('importPackageJson', () => {
232146
).not.toContain('dev-package');
233147
});
234148

149+
describe('installModules', () => {
150+
it('should install modules', async () => {
151+
mockFs.writeFileSync(
152+
'/oldProject/' + Constants.PACKAGE_JSON_FILE_NAME,
153+
JSON.stringify(
154+
{
155+
name: 'test',
156+
dependencies: {
157+
'react-native': '1.0.0',
158+
'some-package': '1.0.0',
159+
},
160+
} as PackageJsonType,
161+
null,
162+
2
163+
)
164+
);
165+
166+
mockSpawn.mockImplementationOnce(() => ({
167+
on: (_event: string, cb: (exitCode: number) => void) => {
168+
cb(0);
169+
},
170+
stdout: {
171+
on: (_event: string, cb: (...args: any[]) => void) => {
172+
cb('stdout');
173+
},
174+
},
175+
stderr: {
176+
on: (_event: string, cb: (...args: any[]) => void) => {
177+
cb('stderr');
178+
},
179+
},
180+
}));
181+
const originalPlatform = process.platform;
182+
Object.defineProperty(process, 'platform', {
183+
value: 'win32',
184+
});
185+
186+
await installModules('/oldProject');
187+
expect(mockSpawn).toHaveBeenCalledWith('npm', ['install'], {
188+
shell: true,
189+
cwd: getProjectPath(),
190+
});
191+
Object.defineProperty(process, 'platform', {
192+
value: originalPlatform,
193+
});
194+
});
195+
it('should handle failed module installation', async () => {
196+
mockFs.writeFileSync(
197+
'/oldProject/' + Constants.PACKAGE_JSON_FILE_NAME,
198+
JSON.stringify(
199+
{
200+
name: 'test',
201+
dependencies: {
202+
'react-native': '1.0.0',
203+
'some-package': '1.0.0',
204+
},
205+
} as PackageJsonType,
206+
null,
207+
2
208+
)
209+
);
210+
211+
mockSpawn.mockImplementationOnce(() => ({
212+
on: (_event: string, cb: (exitCode: number) => void) => {
213+
cb(1);
214+
},
215+
stdout: {
216+
on: (_event: string, cb: (...args: any[]) => void) => {
217+
cb('stdout');
218+
},
219+
},
220+
stderr: {
221+
on: (_event: string, cb: (...args: any[]) => void) => {
222+
cb('stderr');
223+
},
224+
},
225+
}));
226+
mockPrompter.multiselect.mockClear();
227+
228+
await installModules('/oldProject');
229+
expect(mockPrompter.multiselect).toHaveBeenCalled();
230+
});
231+
});
232+
235233
describe('getInstallCommand', () => {
236234
it('should ask user when multiple lock exists', async () => {
237235
mockFs.writeFileSync('/oldProject/package-lock.json', '');

src/schema/upgrade.schema.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,6 +2036,24 @@
20362036
},
20372037
"type": "array"
20382038
},
2039+
"pre_install": {
2040+
"additionalProperties": false,
2041+
"properties": {
2042+
"imports": {
2043+
"items": {
2044+
"type": "string"
2045+
},
2046+
"type": "array"
2047+
},
2048+
"steps": {
2049+
"items": {
2050+
"$ref": "#/definitions/ModStep"
2051+
},
2052+
"type": "array"
2053+
}
2054+
},
2055+
"type": "object"
2056+
},
20392057
"steps": {
20402058
"items": {
20412059
"$ref": "#/definitions/ModStep"

src/types/upgrade.types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { AnyObject, ModStep } from './mod.types';
22

33
export type UpgradeConfig = {
44
env?: AnyObject;
5+
pre_install?: {
6+
imports?: string[];
7+
steps?: ModStep[];
8+
};
59
imports?: string[];
610
steps?: ModStep[];
711
};

0 commit comments

Comments
 (0)