1import { execSync } from 'child_process';
2
3import { resolvePackageManager } from '../resolvePackageManager';
4
5// TODO: replace with jest.mocked when jest 27+ is upgraded to
6export const asMock = <T extends (...args: any[]) => any>(fn: T): jest.MockedFunction<T> =>
7  fn as jest.MockedFunction<T>;
8
9jest.mock('child_process', () => ({
10  execSync: jest.fn(),
11}));
12
13describe(resolvePackageManager, () => {
14  const originalEnv = process.env;
15
16  afterEach(() => {
17    process.env = originalEnv;
18  });
19
20  it('should use yarn due to the user agent', () => {
21    process.env.npm_config_user_agent = 'yarn/1.22.17 npm/? node/v16.13.0 darwin x64';
22    expect(resolvePackageManager()).toBe('yarn');
23  });
24  it('should use pnpm due to the user agent', () => {
25    process.env.npm_config_user_agent = 'pnpm';
26    expect(resolvePackageManager()).toBe('pnpm');
27  });
28  it('should use pnpm due to the user agent', () => {
29    process.env.npm_config_user_agent = 'bun';
30    expect(resolvePackageManager()).toBe('bun');
31  });
32  it('should use npm due to the user agent', () => {
33    process.env.npm_config_user_agent = 'npm/8.1.0 node/v16.13.0 darwin x64 workspaces/false';
34    expect(resolvePackageManager()).toBe('npm');
35  });
36  it('should use yarn due to manager being installed', () => {
37    delete process.env.npm_config_user_agent;
38    expect(resolvePackageManager()).toBe('yarn');
39    expect(execSync).toHaveBeenCalledWith('yarn --version', { stdio: 'ignore' });
40  });
41  it('should use pnpm due to manager being installed', () => {
42    delete process.env.npm_config_user_agent;
43
44    // throw for the first check -- yarn
45    asMock(execSync).mockImplementationOnce(() => {
46      throw new Error('foobar');
47    });
48
49    expect(resolvePackageManager()).toBe('pnpm');
50    expect(execSync).toHaveBeenCalledWith('pnpm --version', { stdio: 'ignore' });
51  });
52  it('should use bun due to manager being installed', () => {
53    delete process.env.npm_config_user_agent;
54
55    // throw for the first two checks -- yarn, pnpm
56    asMock(execSync)
57      .mockImplementationOnce(() => {
58        throw new Error('foobar');
59      })
60      .mockImplementationOnce(() => {
61        throw new Error('foobar');
62      });
63
64    expect(resolvePackageManager()).toBe('bun');
65    expect(execSync).toHaveBeenCalledWith('bun --version', { stdio: 'ignore' });
66  });
67  it('should default to npm when nothing else is available', () => {
68    delete process.env.npm_config_user_agent;
69
70    // throw for the first check -- yarn
71    asMock(execSync)
72      .mockClear()
73      .mockImplementationOnce(() => {
74        throw new Error('foobar');
75      })
76      .mockImplementationOnce(() => {
77        throw new Error('foobar');
78      })
79      .mockImplementationOnce(() => {
80        throw new Error('foobar');
81      });
82
83    expect(resolvePackageManager()).toBe('npm');
84    expect(execSync).toHaveBeenCalledTimes(3);
85  });
86});
87