1import { installAsync } from '../../install/installAsync';
2import { copyAsync } from '../../utils/dir';
3import { queryAndGenerateAsync, selectAndGenerateAsync } from '../generate';
4import { selectTemplatesAsync } from '../templates';
5
6const asMock = <T extends (...args: any[]) => any>(fn: T): jest.MockedFunction<T> =>
7  fn as jest.MockedFunction<T>;
8
9jest.mock('../../log');
10jest.mock('../templates', () => {
11  const templates = jest.requireActual('../templates');
12  return {
13    ...templates,
14    selectTemplatesAsync: jest.fn(),
15  };
16});
17jest.mock('../../install/installAsync', () => ({ installAsync: jest.fn() }));
18jest.mock('../../utils/dir', () => ({ copyAsync: jest.fn() }));
19
20describe(queryAndGenerateAsync, () => {
21  it(`asserts an invalid file`, async () => {
22    await expect(
23      queryAndGenerateAsync('/', {
24        files: ['file1', 'file2'],
25        props: {
26          webStaticPath: 'web',
27        },
28        extras: [],
29      })
30    ).rejects.toThrowErrorMatchingInlineSnapshot(
31      `"Invalid files: file1, file2. Allowed: babel.config.js, webpack.config.js, metro.config.js, web/serve.json, web/index.html"`
32    );
33  });
34  it(`does nothing`, async () => {
35    await queryAndGenerateAsync('/', {
36      files: [],
37      props: {
38        webStaticPath: 'web',
39      },
40      extras: ['foobar'],
41    });
42    expect(copyAsync).not.toBeCalled();
43    expect(installAsync).not.toBeCalled();
44  });
45  it(`queries a file, generates, and installs`, async () => {
46    await queryAndGenerateAsync('/', {
47      files: ['babel.config.js'],
48      props: {
49        webStaticPath: 'web',
50      },
51      extras: ['foobar'],
52    });
53    expect(copyAsync).toBeCalledWith(
54      expect.stringMatching(/@expo\/cli\/static\/template\/babel\.config\.js/),
55      '/babel.config.js',
56      { overwrite: true, recursive: true }
57    );
58    expect(installAsync).toBeCalledWith(['babel-preset-expo'], {}, ['--dev', 'foobar']);
59  });
60});
61
62describe(selectAndGenerateAsync, () => {
63  it(`exits when no items are selected`, async () => {
64    asMock(selectTemplatesAsync).mockResolvedValue([]);
65
66    await expect(
67      selectAndGenerateAsync('/', {
68        props: {
69          webStaticPath: 'web',
70        },
71        extras: [],
72      })
73    ).rejects.toThrow(/EXIT/);
74
75    expect(copyAsync).not.toBeCalled();
76    expect(installAsync).not.toBeCalled();
77  });
78
79  it(`selects a file, generates, and installs`, async () => {
80    asMock(selectTemplatesAsync).mockResolvedValue([1]);
81
82    await selectAndGenerateAsync('/', {
83      props: {
84        webStaticPath: 'web',
85      },
86      extras: [],
87    });
88    expect(copyAsync).toBeCalledWith(
89      expect.stringMatching(/@expo\/webpack-config\/template\/webpack\.config\.js/),
90      '/webpack.config.js',
91      { overwrite: true, recursive: true }
92    );
93    expect(installAsync).toBeCalledWith(['@expo/webpack-config'], {}, ['--dev']);
94  });
95});
96