1c5d00206SEvan Baconimport { vol } from 'memfs';
2c5d00206SEvan Bacon
3dfe12d45SEvan Baconimport { installAsync } from '../../install/installAsync';
4dfe12d45SEvan Baconimport { copyAsync } from '../../utils/dir';
5dfe12d45SEvan Baconimport { queryAndGenerateAsync, selectAndGenerateAsync } from '../generate';
6dfe12d45SEvan Baconimport { selectTemplatesAsync } from '../templates';
7dfe12d45SEvan Bacon
8dfe12d45SEvan Baconconst asMock = <T extends (...args: any[]) => any>(fn: T): jest.MockedFunction<T> =>
9dfe12d45SEvan Bacon  fn as jest.MockedFunction<T>;
10dfe12d45SEvan Bacon
11dfe12d45SEvan Baconjest.mock('../../log');
12dfe12d45SEvan Baconjest.mock('../templates', () => {
13dfe12d45SEvan Bacon  const templates = jest.requireActual('../templates');
14dfe12d45SEvan Bacon  return {
15dfe12d45SEvan Bacon    ...templates,
16dfe12d45SEvan Bacon    selectTemplatesAsync: jest.fn(),
17dfe12d45SEvan Bacon  };
18dfe12d45SEvan Bacon});
19dfe12d45SEvan Baconjest.mock('../../install/installAsync', () => ({ installAsync: jest.fn() }));
20dfe12d45SEvan Baconjest.mock('../../utils/dir', () => ({ copyAsync: jest.fn() }));
21dfe12d45SEvan Bacon
22dfe12d45SEvan Bacondescribe(queryAndGenerateAsync, () => {
23dfe12d45SEvan Bacon  it(`asserts an invalid file`, async () => {
24dfe12d45SEvan Bacon    await expect(
25dfe12d45SEvan Bacon      queryAndGenerateAsync('/', {
26dfe12d45SEvan Bacon        files: ['file1', 'file2'],
27dfe12d45SEvan Bacon        props: {
28dfe12d45SEvan Bacon          webStaticPath: 'web',
29dfe12d45SEvan Bacon        },
30dfe12d45SEvan Bacon        extras: [],
31dfe12d45SEvan Bacon      })
32dfe12d45SEvan Bacon    ).rejects.toThrowErrorMatchingInlineSnapshot(
33*87669a95SMark Lawlor      `"Invalid files: file1, file2. Allowed: babel.config.js, webpack.config.js, metro.config.js, web/serve.json, web/index.html, tsconfig.json"`
34dfe12d45SEvan Bacon    );
35dfe12d45SEvan Bacon  });
36dfe12d45SEvan Bacon  it(`does nothing`, async () => {
37dfe12d45SEvan Bacon    await queryAndGenerateAsync('/', {
38dfe12d45SEvan Bacon      files: [],
39dfe12d45SEvan Bacon      props: {
40dfe12d45SEvan Bacon        webStaticPath: 'web',
41dfe12d45SEvan Bacon      },
42dfe12d45SEvan Bacon      extras: ['foobar'],
43dfe12d45SEvan Bacon    });
44dfe12d45SEvan Bacon    expect(copyAsync).not.toBeCalled();
45dfe12d45SEvan Bacon    expect(installAsync).not.toBeCalled();
46dfe12d45SEvan Bacon  });
47dfe12d45SEvan Bacon  it(`queries a file, generates, and installs`, async () => {
48dfe12d45SEvan Bacon    await queryAndGenerateAsync('/', {
49dfe12d45SEvan Bacon      files: ['babel.config.js'],
50dfe12d45SEvan Bacon      props: {
51dfe12d45SEvan Bacon        webStaticPath: 'web',
52dfe12d45SEvan Bacon      },
53dfe12d45SEvan Bacon      extras: ['foobar'],
54dfe12d45SEvan Bacon    });
55dfe12d45SEvan Bacon    expect(copyAsync).toBeCalledWith(
56dfe12d45SEvan Bacon      expect.stringMatching(/@expo\/cli\/static\/template\/babel\.config\.js/),
57dfe12d45SEvan Bacon      '/babel.config.js',
58dfe12d45SEvan Bacon      { overwrite: true, recursive: true }
59dfe12d45SEvan Bacon    );
60dfe12d45SEvan Bacon    expect(installAsync).toBeCalledWith(['babel-preset-expo'], {}, ['--dev', 'foobar']);
61dfe12d45SEvan Bacon  });
62dfe12d45SEvan Bacon});
63dfe12d45SEvan Bacon
64dfe12d45SEvan Bacondescribe(selectAndGenerateAsync, () => {
65c5d00206SEvan Bacon  afterEach(() => {
66c5d00206SEvan Bacon    vol.reset();
67c5d00206SEvan Bacon  });
68c5d00206SEvan Bacon
69dfe12d45SEvan Bacon  it(`exits when no items are selected`, async () => {
70dfe12d45SEvan Bacon    asMock(selectTemplatesAsync).mockResolvedValue([]);
71dfe12d45SEvan Bacon
72dfe12d45SEvan Bacon    await expect(
73dfe12d45SEvan Bacon      selectAndGenerateAsync('/', {
74dfe12d45SEvan Bacon        props: {
75dfe12d45SEvan Bacon          webStaticPath: 'web',
76dfe12d45SEvan Bacon        },
77dfe12d45SEvan Bacon        extras: [],
78dfe12d45SEvan Bacon      })
79dfe12d45SEvan Bacon    ).rejects.toThrow(/EXIT/);
80dfe12d45SEvan Bacon
81dfe12d45SEvan Bacon    expect(copyAsync).not.toBeCalled();
82dfe12d45SEvan Bacon    expect(installAsync).not.toBeCalled();
83dfe12d45SEvan Bacon  });
84dfe12d45SEvan Bacon
85dfe12d45SEvan Bacon  it(`selects a file, generates, and installs`, async () => {
86c5d00206SEvan Bacon    vol.fromJSON(
87c5d00206SEvan Bacon      {
88c5d00206SEvan Bacon        'node_modules/@expo/webpack-config/template/webpack.config.js': '',
89c5d00206SEvan Bacon      },
90c5d00206SEvan Bacon      '/'
91c5d00206SEvan Bacon    );
92c5d00206SEvan Bacon
93dfe12d45SEvan Bacon    asMock(selectTemplatesAsync).mockResolvedValue([1]);
94dfe12d45SEvan Bacon
95dfe12d45SEvan Bacon    await selectAndGenerateAsync('/', {
96dfe12d45SEvan Bacon      props: {
97dfe12d45SEvan Bacon        webStaticPath: 'web',
98dfe12d45SEvan Bacon      },
99dfe12d45SEvan Bacon      extras: [],
100dfe12d45SEvan Bacon    });
101c5d00206SEvan Bacon
102dfe12d45SEvan Bacon    expect(copyAsync).toBeCalledWith(
103dfe12d45SEvan Bacon      expect.stringMatching(/@expo\/webpack-config\/template\/webpack\.config\.js/),
104dfe12d45SEvan Bacon      '/webpack.config.js',
105dfe12d45SEvan Bacon      { overwrite: true, recursive: true }
106dfe12d45SEvan Bacon    );
107c5d00206SEvan Bacon    expect(installAsync).not.toBeCalled();
108c5d00206SEvan Bacon  });
109c5d00206SEvan Bacon
110c5d00206SEvan Bacon  it(`selects a file from installed, and generates`, async () => {
111c5d00206SEvan Bacon    vol.fromJSON({}, '/');
112c5d00206SEvan Bacon
113c5d00206SEvan Bacon    asMock(selectTemplatesAsync).mockResolvedValue([1]);
114c5d00206SEvan Bacon
115c5d00206SEvan Bacon    await selectAndGenerateAsync('/', {
116c5d00206SEvan Bacon      props: {
117c5d00206SEvan Bacon        webStaticPath: 'web',
118c5d00206SEvan Bacon      },
119c5d00206SEvan Bacon      extras: [],
120c5d00206SEvan Bacon    });
121c5d00206SEvan Bacon
122c5d00206SEvan Bacon    // NOTE(EvanBacon): This logic makes no sense anymore.
123c5d00206SEvan Bacon    // Why install a package after not using the versioned template?
124c5d00206SEvan Bacon    // This isn't high priority since the file never changes and we should drop Webpack.
125c5d00206SEvan Bacon    expect(copyAsync).toBeCalledWith(
126c5d00206SEvan Bacon      expect.stringMatching(/@expo\/cli\/static\/template\/webpack\.config\.js/),
127c5d00206SEvan Bacon      '/webpack.config.js',
128c5d00206SEvan Bacon      { overwrite: true, recursive: true }
129c5d00206SEvan Bacon    );
130dfe12d45SEvan Bacon    expect(installAsync).toBeCalledWith(['@expo/webpack-config'], {}, ['--dev']);
131dfe12d45SEvan Bacon  });
132dfe12d45SEvan Bacon});
133