1*6fb32dddSKeith Kurakimport { getConfig } from '@expo/config';
2*6fb32dddSKeith Kurak
3fa5bc561SWill Schurmanimport { asMock } from '../../__tests__/asMock';
4c94ad8a2SEvan Baconimport { Log } from '../../log';
5c94ad8a2SEvan Baconimport {
6c94ad8a2SEvan Bacon  getVersionedDependenciesAsync,
7c94ad8a2SEvan Bacon  logIncorrectDependencies,
8c94ad8a2SEvan Bacon} from '../../start/doctor/dependencies/validateDependenciesVersions';
9c94ad8a2SEvan Baconimport { confirmAsync } from '../../utils/prompts';
10c94ad8a2SEvan Baconimport { checkPackagesAsync } from '../checkPackages';
118d3f3824SCedric van Puttenimport { fixPackagesAsync } from '../installAsync';
12c94ad8a2SEvan Bacon
13c94ad8a2SEvan Baconjest.mock('../../log');
14c94ad8a2SEvan Bacon
15c94ad8a2SEvan Baconjest.mock('../../utils/prompts');
16c94ad8a2SEvan Bacon
17c94ad8a2SEvan Baconjest.mock('../installAsync', () => ({
188d3f3824SCedric van Putten  fixPackagesAsync: jest.fn(),
19c94ad8a2SEvan Bacon}));
20c94ad8a2SEvan Bacon
21c94ad8a2SEvan Baconjest.mock('../../start/doctor/dependencies/validateDependenciesVersions', () => ({
22c94ad8a2SEvan Bacon  getVersionedDependenciesAsync: jest.fn(),
23c94ad8a2SEvan Bacon  logIncorrectDependencies: jest.fn(),
24c94ad8a2SEvan Bacon}));
25c94ad8a2SEvan Bacon
26c94ad8a2SEvan Baconjest.mock('@expo/config', () => ({
27c94ad8a2SEvan Bacon  getProjectConfigDescriptionWithPaths: jest.fn(),
28c94ad8a2SEvan Bacon  getConfig: jest.fn(() => ({
29c94ad8a2SEvan Bacon    pkg: {},
30c94ad8a2SEvan Bacon    exp: {
31c94ad8a2SEvan Bacon      sdkVersion: '45.0.0',
32c94ad8a2SEvan Bacon      name: 'my-app',
33c94ad8a2SEvan Bacon      slug: 'my-app',
34c94ad8a2SEvan Bacon    },
35c94ad8a2SEvan Bacon  })),
36c94ad8a2SEvan Bacon}));
37c94ad8a2SEvan Bacon
38c94ad8a2SEvan Bacondescribe(checkPackagesAsync, () => {
39c94ad8a2SEvan Bacon  it(`checks packages and exits when packages are invalid`, async () => {
40c94ad8a2SEvan Bacon    asMock(confirmAsync).mockResolvedValueOnce(false);
41c94ad8a2SEvan Bacon    asMock(getVersionedDependenciesAsync).mockResolvedValueOnce([
42c94ad8a2SEvan Bacon      {
43c94ad8a2SEvan Bacon        packageName: 'react-native',
448d3f3824SCedric van Putten        packageType: 'dependencies',
45c94ad8a2SEvan Bacon        expectedVersionOrRange: '^1.0.0',
46c94ad8a2SEvan Bacon        actualVersion: '0.69.0',
47c94ad8a2SEvan Bacon      },
48c94ad8a2SEvan Bacon    ]);
49c94ad8a2SEvan Bacon    await expect(
50c94ad8a2SEvan Bacon      checkPackagesAsync('/', {
51c94ad8a2SEvan Bacon        packages: ['react-native'],
52c94ad8a2SEvan Bacon        options: { fix: false },
53c94ad8a2SEvan Bacon        // @ts-expect-error
54c94ad8a2SEvan Bacon        packageManager: {},
55c94ad8a2SEvan Bacon        packageManagerArguments: [],
56c94ad8a2SEvan Bacon      })
57c94ad8a2SEvan Bacon    ).rejects.toThrowError(/EXIT/);
58c94ad8a2SEvan Bacon
59c94ad8a2SEvan Bacon    expect(logIncorrectDependencies).toBeCalledTimes(1);
60c94ad8a2SEvan Bacon
61c94ad8a2SEvan Bacon    expect(Log.exit).toBeCalledWith(
62c94ad8a2SEvan Bacon      // Because of ansi
63c94ad8a2SEvan Bacon      expect.stringContaining('Found outdated dependencies'),
64c94ad8a2SEvan Bacon      1
65c94ad8a2SEvan Bacon    );
66c94ad8a2SEvan Bacon  });
67c94ad8a2SEvan Bacon
68*6fb32dddSKeith Kurak  it(`notifies when dependencies are on exclude list`, async () => {
69*6fb32dddSKeith Kurak    asMock(confirmAsync).mockResolvedValueOnce(false);
70*6fb32dddSKeith Kurak    // @ts-expect-error
71*6fb32dddSKeith Kurak    asMock(getConfig).mockReturnValueOnce({
72*6fb32dddSKeith Kurak      pkg: {
73*6fb32dddSKeith Kurak        expo: {
74*6fb32dddSKeith Kurak          install: {
75*6fb32dddSKeith Kurak            exclude: ['expo-av', 'expo-blur'],
76*6fb32dddSKeith Kurak          },
77*6fb32dddSKeith Kurak        },
78*6fb32dddSKeith Kurak      },
79*6fb32dddSKeith Kurak      exp: {
80*6fb32dddSKeith Kurak        sdkVersion: '45.0.0',
81*6fb32dddSKeith Kurak        name: 'my-app',
82*6fb32dddSKeith Kurak        slug: 'my-app',
83*6fb32dddSKeith Kurak      },
84*6fb32dddSKeith Kurak    });
85*6fb32dddSKeith Kurak    asMock(getVersionedDependenciesAsync).mockResolvedValueOnce([
86*6fb32dddSKeith Kurak      {
87*6fb32dddSKeith Kurak        packageName: 'expo-av',
88*6fb32dddSKeith Kurak        packageType: 'dependencies',
89*6fb32dddSKeith Kurak        expectedVersionOrRange: '^2.0.0',
90*6fb32dddSKeith Kurak        actualVersion: '1.0.0',
91*6fb32dddSKeith Kurak      },
92*6fb32dddSKeith Kurak    ]);
93*6fb32dddSKeith Kurak    await checkPackagesAsync('/', {
94*6fb32dddSKeith Kurak      packages: ['expo-av'],
95*6fb32dddSKeith Kurak      options: { fix: true },
96*6fb32dddSKeith Kurak      // @ts-expect-error
97*6fb32dddSKeith Kurak      packageManager: {},
98*6fb32dddSKeith Kurak      packageManagerArguments: [],
99*6fb32dddSKeith Kurak    });
100*6fb32dddSKeith Kurak
101*6fb32dddSKeith Kurak    expect(Log.log).toBeCalledWith(
102*6fb32dddSKeith Kurak      expect.stringContaining('Skipped fixing dependencies: expo-av and expo-blur')
103*6fb32dddSKeith Kurak    );
104*6fb32dddSKeith Kurak  });
105*6fb32dddSKeith Kurak
106c94ad8a2SEvan Bacon  it(`checks packages and exits with zero if all are valid`, async () => {
107c94ad8a2SEvan Bacon    asMock(confirmAsync).mockResolvedValueOnce(false);
108c94ad8a2SEvan Bacon    asMock(getVersionedDependenciesAsync).mockResolvedValueOnce([]);
109c94ad8a2SEvan Bacon    await expect(
110c94ad8a2SEvan Bacon      checkPackagesAsync('/', {
111c94ad8a2SEvan Bacon        packages: ['react-native'],
112c94ad8a2SEvan Bacon        options: { fix: false },
113c94ad8a2SEvan Bacon        // @ts-expect-error
114c94ad8a2SEvan Bacon        packageManager: {},
115c94ad8a2SEvan Bacon        packageManagerArguments: [],
116c94ad8a2SEvan Bacon      })
117c94ad8a2SEvan Bacon    ).rejects.toThrowError(/EXIT/);
118c94ad8a2SEvan Bacon
119c94ad8a2SEvan Bacon    expect(logIncorrectDependencies).toBeCalledTimes(0);
120c94ad8a2SEvan Bacon
121c94ad8a2SEvan Bacon    expect(Log.exit).toBeCalledWith(
122c94ad8a2SEvan Bacon      // Because of ansi
123c94ad8a2SEvan Bacon      expect.stringContaining('Dependencies are up to date'),
124c94ad8a2SEvan Bacon      0
125c94ad8a2SEvan Bacon    );
126c94ad8a2SEvan Bacon  });
127c94ad8a2SEvan Bacon
128c94ad8a2SEvan Bacon  it(`fixes invalid packages`, async () => {
1298d3f3824SCedric van Putten    const issues: Awaited<ReturnType<typeof getVersionedDependenciesAsync>> = [
130c94ad8a2SEvan Bacon      {
131c94ad8a2SEvan Bacon        packageName: 'react-native',
1328d3f3824SCedric van Putten        packageType: 'dependencies',
133c94ad8a2SEvan Bacon        expectedVersionOrRange: '^1.0.0',
134c94ad8a2SEvan Bacon        actualVersion: '0.69.0',
135c94ad8a2SEvan Bacon      },
136c94ad8a2SEvan Bacon      {
137c94ad8a2SEvan Bacon        packageName: 'expo',
1388d3f3824SCedric van Putten        packageType: 'dependencies',
139c94ad8a2SEvan Bacon        expectedVersionOrRange: '^1.0.0',
140c94ad8a2SEvan Bacon        actualVersion: '0.69.0',
141c94ad8a2SEvan Bacon      },
1428d3f3824SCedric van Putten    ];
1438d3f3824SCedric van Putten
1448d3f3824SCedric van Putten    asMock(getVersionedDependenciesAsync).mockResolvedValueOnce(issues);
145c94ad8a2SEvan Bacon
146c94ad8a2SEvan Bacon    await checkPackagesAsync('/', {
147c94ad8a2SEvan Bacon      packages: ['react-native', 'expo'],
148c94ad8a2SEvan Bacon      options: { fix: true },
149c94ad8a2SEvan Bacon      // @ts-expect-error
150c94ad8a2SEvan Bacon      packageManager: {},
151c94ad8a2SEvan Bacon      packageManagerArguments: [],
152c94ad8a2SEvan Bacon    });
153c94ad8a2SEvan Bacon
1548d3f3824SCedric van Putten    expect(fixPackagesAsync).toBeCalledWith('/', {
155c94ad8a2SEvan Bacon      packageManager: {},
156c94ad8a2SEvan Bacon      packageManagerArguments: [],
1578d3f3824SCedric van Putten      packages: issues,
158c94ad8a2SEvan Bacon      sdkVersion: '45.0.0',
159c94ad8a2SEvan Bacon    });
160c94ad8a2SEvan Bacon    expect(logIncorrectDependencies).toBeCalledTimes(1);
161c94ad8a2SEvan Bacon  });
162c94ad8a2SEvan Bacon});
163