1import { vol, fs } from 'memfs';
2
3import { createControlledEnvironment, getFiles } from '../env';
4
5beforeEach(() => {
6  vol.reset();
7});
8
9const originalEnv = process.env;
10
11function resetEnv() {
12  process.env = originalEnv;
13}
14
15beforeEach(() => {
16  resetEnv();
17});
18afterAll(() => {
19  resetEnv();
20});
21
22describe(getFiles, () => {
23  beforeEach(() => {
24    resetEnv();
25  });
26
27  it(`gets development files`, () => {
28    expect(getFiles('development')).toEqual([
29      '.env.development.local',
30      '.env.local',
31      '.env.development',
32      '.env',
33    ]);
34  });
35  it(`gets production files`, () => {
36    expect(getFiles('production')).toEqual([
37      '.env.production.local',
38      '.env.local',
39      '.env.production',
40      '.env',
41    ]);
42  });
43  it(`gets test files`, () => {
44    // important
45    expect(getFiles('test')).toEqual(['.env.test.local', '.env.test', '.env']);
46  });
47
48  it(`throws if NODE_ENV is not set`, () => {
49    expect(() => getFiles(undefined)).toThrowErrorMatchingInlineSnapshot(
50      `"The NODE_ENV environment variable is required but was not specified. Ensure the project is bundled with Expo CLI."`
51    );
52  });
53  it(`throws if NODE_ENV is not valid`, () => {
54    expect(() => getFiles('invalid')).toThrowErrorMatchingInlineSnapshot(
55      `"Environment variable "NODE_ENV=invalid" is invalid. Valid values are "development", "test", and "production"`
56    );
57  });
58});
59
60describe('get', () => {
61  beforeEach(() => {
62    resetEnv();
63  });
64
65  it(`memoizes`, () => {
66    delete process.env.FOO;
67    const envRuntime = createControlledEnvironment();
68    vol.fromJSON(
69      {
70        '.env': 'FOO=default',
71      },
72      '/'
73    );
74    expect(envRuntime.get('/')).toEqual({
75      FOO: 'default',
76    });
77
78    fs.writeFileSync('/.env', 'FOO=changed');
79
80    expect(envRuntime.get('/')).toEqual({
81      FOO: 'default',
82    });
83    expect(envRuntime.get('/', { force: true })).toEqual({
84      FOO: 'changed',
85    });
86  });
87});
88describe('_getForce', () => {
89  beforeEach(() => {
90    resetEnv();
91  });
92
93  it(`returns the value of the environment variable`, () => {
94    delete process.env.FOO;
95
96    const envRuntime = createControlledEnvironment();
97    vol.fromJSON(
98      {
99        '.env': 'FOO=bar',
100      },
101      '/'
102    );
103
104    expect(envRuntime._getForce('/')).toEqual({
105      FOO: 'bar',
106    });
107  });
108
109  it(`cascades env files (development)`, () => {
110    delete process.env.FOO;
111    process.env.NODE_ENV = 'development';
112    const envRuntime = createControlledEnvironment();
113    vol.fromJSON(
114      {
115        '.env': 'FOO=default',
116        '.env.local': 'FOO=default-local',
117        '.env.development': 'FOO=dev',
118        '.env.production': 'FOO=prod',
119        '.env.production.local': 'FOO=prod-local',
120        '.env.development.local': 'FOO=dev-local',
121      },
122      '/'
123    );
124
125    expect(envRuntime._getForce('/')).toEqual({
126      FOO: 'dev-local',
127    });
128  });
129
130  it(`cascades env files (production)`, () => {
131    delete process.env.FOO;
132    process.env.NODE_ENV = 'production';
133    const envRuntime = createControlledEnvironment();
134    vol.fromJSON(
135      {
136        '.env': 'FOO=default',
137        '.env.local': 'FOO=default-local',
138        '.env.production': 'FOO=prod',
139        '.env.production.local': 'FOO=prod-local',
140      },
141      '/'
142    );
143
144    expect(envRuntime._getForce('/')).toEqual({
145      FOO: 'prod-local',
146    });
147  });
148
149  it(`cascades env files (default)`, () => {
150    delete process.env.FOO;
151    const envRuntime = createControlledEnvironment();
152    vol.fromJSON(
153      {
154        '.env': 'FOO=default',
155        '.env.local': 'FOO=default-local',
156      },
157      '/'
158    );
159
160    expect(envRuntime._getForce('/')).toEqual({
161      FOO: 'default-local',
162    });
163  });
164
165  it(`does not return the env var if the initial the value of the environment variable`, () => {
166    const envRuntime = createControlledEnvironment();
167    process.env.FOO = 'not-bar';
168
169    vol.fromJSON(
170      {
171        '.env': 'FOO=bar',
172      },
173      '/'
174    );
175
176    expect(envRuntime._getForce('/')).toEqual({});
177  });
178
179  it(`Does not fail when no files are available`, () => {
180    vol.fromJSON({}, '/');
181    expect(createControlledEnvironment()._getForce('/')).toEqual({});
182  });
183
184  it(`Does not assert on invalid env files`, () => {
185    vol.fromJSON(
186      {
187        '.env': 'ˆ˙•ª∆ø…ˆ',
188      },
189      '/'
190    );
191
192    expect(createControlledEnvironment()._getForce('/')).toEqual({});
193  });
194});
195