1import { withPlugins } from '@expo/config-plugins';
2import { ExpoConfig } from '@expo/config-types';
3import { join } from 'path';
4
5import { withStaticPlugin } from '../withStaticPlugin';
6
7function withInternal(config: ExpoConfig, projectRoot: string) {
8  if (!config._internal) config._internal = {};
9  config._internal.projectRoot = projectRoot;
10  return config;
11}
12
13function withInternalRemoved(config: ExpoConfig) {
14  delete config._internal;
15  return config;
16}
17
18jest.unmock('resolve-from');
19
20const projectRoot = join(__dirname, 'fixtures/project-files');
21
22// Not using in-memory fs because the node resolution isn't mocked out.
23describe(withStaticPlugin, () => {
24  it(`asserts wrong type`, () => {
25    const config = withInternal(
26      {
27        name: 'foo',
28        slug: 'foo',
29      },
30      '/'
31    );
32
33    expect(() =>
34      withStaticPlugin(config, {
35        // @ts-ignore -- invalid type
36        plugin: true,
37      })
38    ).toThrow('Plugin is an unexpected type: boolean');
39    expect(() =>
40      withStaticPlugin(config, {
41        // @ts-ignore -- invalid type
42        plugin: [true],
43      })
44    ).toThrow('Plugin is an unexpected type: boolean');
45    expect(() =>
46      withStaticPlugin(config, {
47        // @ts-ignore -- invalid type
48        plugin: {},
49      })
50    ).toThrow('Plugin is an unexpected type: object');
51  });
52  it(`asserts wrong number of arguments`, () => {
53    const config = withInternal(
54      {
55        name: 'foo',
56        slug: 'foo',
57      },
58      '/'
59    );
60
61    expect(() =>
62      withStaticPlugin(config, {
63        // @ts-ignore -- invalid type
64        plugin: ['', '', ''],
65      })
66    ).toThrow(
67      'Wrong number of arguments provided for static config plugin, expected either 1 or 2, got 3'
68    );
69  });
70  it(`uses internal projectRoot`, () => {
71    let config: ExpoConfig = withInternal(
72      {
73        name: 'foo',
74        slug: 'foo',
75      },
76      projectRoot
77    );
78
79    config = withPlugins(config, [
80      // @ts-ignore -- invalid type
81      (c) =>
82        withStaticPlugin(c, {
83          plugin: './my-plugin.js',
84        }),
85      // @ts-ignore -- invalid type
86      withInternalRemoved,
87    ]);
88
89    expect(config).toStrictEqual({
90      name: 'foo',
91      slug: 'foo',
92      extras: {
93        modified: true,
94      },
95    });
96  });
97
98  it(`passes props to plugin`, () => {
99    let config: ExpoConfig = withInternal(
100      {
101        name: 'foo',
102        slug: 'foo',
103      },
104      '.'
105    );
106
107    config = withPlugins(config, [
108      // @ts-ignore -- invalid type
109      (c) =>
110        withStaticPlugin(c, {
111          plugin: ['./my-plugin.js', { foobar: true }],
112          projectRoot,
113        }),
114      // Uses a folder with index.js
115      // @ts-ignore -- invalid type
116      (c) =>
117        withStaticPlugin(c, {
118          plugin: './beta',
119          projectRoot,
120        }),
121    ]);
122
123    expect(config).toStrictEqual({
124      name: 'foo',
125      slug: 'foo',
126      extras: {
127        beta: true,
128        modified: true,
129        foobar: true,
130      },
131      _internal: {
132        projectRoot: '.',
133      },
134    });
135  });
136
137  it(`fails to resolve a non-existent file`, () => {
138    const config = {
139      name: 'foo',
140      slug: 'foo',
141    };
142
143    expect(() =>
144      withStaticPlugin(config, {
145        plugin: ['./not-existing.js', { foobar: true }],
146        projectRoot,
147      })
148    ).toThrow(/Failed to resolve plugin for module ".\/not-existing.js"/);
149  });
150});
151