1import spawnAsync from '@expo/spawn-async';
2import tar from 'tar';
3
4import * as Log from '../../log';
5import { extractAsync } from '../tar';
6
7const asMock = (fn: any): jest.Mock => fn;
8
9jest.mock(`../../log`);
10
11function mockPlatform(value: typeof process.platform) {
12  Object.defineProperty(process, 'platform', {
13    value,
14  });
15}
16
17describe(extractAsync, () => {
18  const originalPlatform = process.platform;
19
20  beforeEach(() => {
21    asMock(spawnAsync).mockClear();
22    asMock(tar.extract).mockClear();
23    asMock(Log.warn).mockClear();
24  });
25
26  afterAll(() => {
27    mockPlatform(originalPlatform);
28  });
29
30  it('extracts a tar file using node module when native fails', async () => {
31    // set to mac in order to test native tools.
32    mockPlatform('darwin');
33    asMock(spawnAsync).mockImplementationOnce(() => {
34      throw new Error('mock failure');
35    });
36
37    await extractAsync('./template.tgz', './output');
38
39    // Expect a warning that surfaces the native error message.
40    expect(Log.warn).toBeCalledTimes(1);
41    expect(Log.warn).toHaveBeenLastCalledWith(
42      expect.stringMatching(/Failed to extract tar.*mock failure/)
43    );
44    // JS tools
45    expect(tar.extract).toBeCalledTimes(1);
46    expect(tar.extract).toHaveBeenLastCalledWith({ cwd: './output', file: './template.tgz' });
47  });
48
49  it('skips JS tools on mac when native tools work', async () => {
50    // set to mac in order to test native tools.
51    mockPlatform('darwin');
52
53    await extractAsync('./template.tgz', './output');
54
55    expect(spawnAsync).toBeCalledTimes(1);
56    expect(Log.warn).toBeCalledTimes(0);
57    expect(tar.extract).toBeCalledTimes(0);
58  });
59
60  it('skips native tools on windows', async () => {
61    mockPlatform('win32');
62
63    await extractAsync('./template.tgz', './output');
64
65    // No native tools or warnings.
66    expect(spawnAsync).toBeCalledTimes(0);
67    expect(Log.warn).toBeCalledTimes(0);
68    // JS tools
69    expect(tar.extract).toBeCalledTimes(1);
70    expect(tar.extract).toHaveBeenLastCalledWith({ cwd: './output', file: './template.tgz' });
71  });
72});
73