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