16a750d06SEvan Baconimport { vol, fs } from 'memfs'; 26a750d06SEvan Bacon 36a750d06SEvan Baconimport { createControlledEnvironment, getFiles } from '../env'; 46a750d06SEvan Bacon 56a750d06SEvan BaconbeforeEach(() => { 66a750d06SEvan Bacon vol.reset(); 76a750d06SEvan Bacon}); 86a750d06SEvan Bacon 96a750d06SEvan Baconconst originalEnv = process.env; 106a750d06SEvan Bacon 116a750d06SEvan Baconfunction resetEnv() { 126a750d06SEvan Bacon process.env = originalEnv; 1378a6243aSEvan Bacon delete process.env.EXPO_NO_DOTENV; 146a750d06SEvan Bacon} 156a750d06SEvan Bacon 166a750d06SEvan BaconbeforeEach(() => { 176a750d06SEvan Bacon resetEnv(); 186a750d06SEvan Bacon}); 196a750d06SEvan BaconafterAll(() => { 206a750d06SEvan Bacon resetEnv(); 216a750d06SEvan Bacon}); 226a750d06SEvan Bacon 236a750d06SEvan Bacondescribe(getFiles, () => { 2478a6243aSEvan Bacon const originalError = console.error; 256a750d06SEvan Bacon beforeEach(() => { 2678a6243aSEvan Bacon console.error = jest.fn(); 276a750d06SEvan Bacon resetEnv(); 286a750d06SEvan Bacon }); 2978a6243aSEvan Bacon afterEach(() => { 3078a6243aSEvan Bacon console.error = originalError; 3178a6243aSEvan Bacon }); 326a750d06SEvan Bacon 336a750d06SEvan Bacon it(`gets development files`, () => { 346a750d06SEvan Bacon expect(getFiles('development')).toEqual([ 356a750d06SEvan Bacon '.env.development.local', 366a750d06SEvan Bacon '.env.local', 376a750d06SEvan Bacon '.env.development', 386a750d06SEvan Bacon '.env', 396a750d06SEvan Bacon ]); 406a750d06SEvan Bacon }); 416a750d06SEvan Bacon it(`gets production files`, () => { 426a750d06SEvan Bacon expect(getFiles('production')).toEqual([ 436a750d06SEvan Bacon '.env.production.local', 446a750d06SEvan Bacon '.env.local', 456a750d06SEvan Bacon '.env.production', 466a750d06SEvan Bacon '.env', 476a750d06SEvan Bacon ]); 486a750d06SEvan Bacon }); 496a750d06SEvan Bacon it(`gets test files`, () => { 506a750d06SEvan Bacon // important 516a750d06SEvan Bacon expect(getFiles('test')).toEqual(['.env.test.local', '.env.test', '.env']); 526a750d06SEvan Bacon }); 5378a6243aSEvan Bacon it(`gets no files when dotenv is disabled`, () => { 5478a6243aSEvan Bacon process.env.EXPO_NO_DOTENV = '1'; 5578a6243aSEvan Bacon ['development', 'production', 'test'].forEach((mode) => { 5678a6243aSEvan Bacon expect(getFiles(mode)).toEqual([]); 57f5917927SEvan Bacon }); 58f5917927SEvan Bacon }); 596a750d06SEvan Bacon 606a750d06SEvan Bacon it(`throws if NODE_ENV is not set`, () => { 61f5917927SEvan Bacon getFiles(undefined); 62f5917927SEvan Bacon 63f5917927SEvan Bacon expect(console.error).toBeCalledTimes(2); 64f5917927SEvan Bacon expect(console.error).toBeCalledWith( 65f5917927SEvan Bacon expect.stringContaining('The NODE_ENV environment variable is required but was not specified') 666a750d06SEvan Bacon ); 676a750d06SEvan Bacon }); 686a750d06SEvan Bacon it(`throws if NODE_ENV is not valid`, () => { 696a750d06SEvan Bacon expect(() => getFiles('invalid')).toThrowErrorMatchingInlineSnapshot( 706a750d06SEvan Bacon `"Environment variable "NODE_ENV=invalid" is invalid. Valid values are "development", "test", and "production"` 716a750d06SEvan Bacon ); 726a750d06SEvan Bacon }); 736a750d06SEvan Bacon}); 746a750d06SEvan Bacon 756a750d06SEvan Bacondescribe('get', () => { 766a750d06SEvan Bacon beforeEach(() => { 776a750d06SEvan Bacon resetEnv(); 786a750d06SEvan Bacon }); 796a750d06SEvan Bacon 806a750d06SEvan Bacon it(`memoizes`, () => { 816a750d06SEvan Bacon delete process.env.FOO; 826a750d06SEvan Bacon const envRuntime = createControlledEnvironment(); 836a750d06SEvan Bacon vol.fromJSON( 846a750d06SEvan Bacon { 856a750d06SEvan Bacon '.env': 'FOO=default', 866a750d06SEvan Bacon }, 876a750d06SEvan Bacon '/' 886a750d06SEvan Bacon ); 896a750d06SEvan Bacon expect(envRuntime.get('/')).toEqual({ 90*e30a2315SEvan Bacon env: { 916a750d06SEvan Bacon FOO: 'default', 92*e30a2315SEvan Bacon }, 93*e30a2315SEvan Bacon files: ['/.env'], 946a750d06SEvan Bacon }); 956a750d06SEvan Bacon 966a750d06SEvan Bacon fs.writeFileSync('/.env', 'FOO=changed'); 976a750d06SEvan Bacon 986a750d06SEvan Bacon expect(envRuntime.get('/')).toEqual({ 99*e30a2315SEvan Bacon env: { 1006a750d06SEvan Bacon FOO: 'default', 101*e30a2315SEvan Bacon }, 102*e30a2315SEvan Bacon files: ['/.env'], 1036a750d06SEvan Bacon }); 1046a750d06SEvan Bacon expect(envRuntime.get('/', { force: true })).toEqual({ 105*e30a2315SEvan Bacon env: { 1066a750d06SEvan Bacon FOO: 'changed', 107*e30a2315SEvan Bacon }, 108*e30a2315SEvan Bacon files: ['/.env'], 1096a750d06SEvan Bacon }); 1106a750d06SEvan Bacon }); 1116a750d06SEvan Bacon}); 1126a750d06SEvan Bacondescribe('_getForce', () => { 1136a750d06SEvan Bacon beforeEach(() => { 1146a750d06SEvan Bacon resetEnv(); 1156a750d06SEvan Bacon }); 1166a750d06SEvan Bacon 1176a750d06SEvan Bacon it(`returns the value of the environment variable`, () => { 1186a750d06SEvan Bacon delete process.env.FOO; 1196a750d06SEvan Bacon 1206a750d06SEvan Bacon const envRuntime = createControlledEnvironment(); 1216a750d06SEvan Bacon vol.fromJSON( 1226a750d06SEvan Bacon { 1236a750d06SEvan Bacon '.env': 'FOO=bar', 1246a750d06SEvan Bacon }, 1256a750d06SEvan Bacon '/' 1266a750d06SEvan Bacon ); 1276a750d06SEvan Bacon 1286a750d06SEvan Bacon expect(envRuntime._getForce('/')).toEqual({ 129*e30a2315SEvan Bacon env: { 1306a750d06SEvan Bacon FOO: 'bar', 131*e30a2315SEvan Bacon }, 132*e30a2315SEvan Bacon files: ['/.env'], 1336a750d06SEvan Bacon }); 1346a750d06SEvan Bacon }); 1356a750d06SEvan Bacon 1366a750d06SEvan Bacon it(`cascades env files (development)`, () => { 1376a750d06SEvan Bacon delete process.env.FOO; 1386a750d06SEvan Bacon process.env.NODE_ENV = 'development'; 1396a750d06SEvan Bacon const envRuntime = createControlledEnvironment(); 1406a750d06SEvan Bacon vol.fromJSON( 1416a750d06SEvan Bacon { 1426a750d06SEvan Bacon '.env': 'FOO=default', 1436a750d06SEvan Bacon '.env.local': 'FOO=default-local', 1446a750d06SEvan Bacon '.env.development': 'FOO=dev', 1456a750d06SEvan Bacon '.env.production': 'FOO=prod', 1466a750d06SEvan Bacon '.env.production.local': 'FOO=prod-local', 1476a750d06SEvan Bacon '.env.development.local': 'FOO=dev-local', 1486a750d06SEvan Bacon }, 1496a750d06SEvan Bacon '/' 1506a750d06SEvan Bacon ); 1516a750d06SEvan Bacon 1526a750d06SEvan Bacon expect(envRuntime._getForce('/')).toEqual({ 153*e30a2315SEvan Bacon env: { 1546a750d06SEvan Bacon FOO: 'dev-local', 155*e30a2315SEvan Bacon }, 156*e30a2315SEvan Bacon files: ['/.env.development.local', '/.env.local', '/.env.development', '/.env'], 1576a750d06SEvan Bacon }); 1586a750d06SEvan Bacon }); 1596a750d06SEvan Bacon 1606a750d06SEvan Bacon it(`cascades env files (production)`, () => { 1616a750d06SEvan Bacon delete process.env.FOO; 1626a750d06SEvan Bacon process.env.NODE_ENV = 'production'; 1636a750d06SEvan Bacon const envRuntime = createControlledEnvironment(); 1646a750d06SEvan Bacon vol.fromJSON( 1656a750d06SEvan Bacon { 1666a750d06SEvan Bacon '.env': 'FOO=default', 1676a750d06SEvan Bacon '.env.local': 'FOO=default-local', 1686a750d06SEvan Bacon '.env.production': 'FOO=prod', 1696a750d06SEvan Bacon '.env.production.local': 'FOO=prod-local', 1706a750d06SEvan Bacon }, 1716a750d06SEvan Bacon '/' 1726a750d06SEvan Bacon ); 1736a750d06SEvan Bacon 1746a750d06SEvan Bacon expect(envRuntime._getForce('/')).toEqual({ 175*e30a2315SEvan Bacon files: ['/.env.production.local', '/.env.local', '/.env.production', '/.env'], 176*e30a2315SEvan Bacon env: { 1776a750d06SEvan Bacon FOO: 'prod-local', 178*e30a2315SEvan Bacon }, 1796a750d06SEvan Bacon }); 1806a750d06SEvan Bacon }); 1816a750d06SEvan Bacon 1826a750d06SEvan Bacon it(`cascades env files (default)`, () => { 1836a750d06SEvan Bacon delete process.env.FOO; 1846a750d06SEvan Bacon const envRuntime = createControlledEnvironment(); 1856a750d06SEvan Bacon vol.fromJSON( 1866a750d06SEvan Bacon { 1876a750d06SEvan Bacon '.env': 'FOO=default', 1886a750d06SEvan Bacon '.env.local': 'FOO=default-local', 1896a750d06SEvan Bacon }, 1906a750d06SEvan Bacon '/' 1916a750d06SEvan Bacon ); 1926a750d06SEvan Bacon 1936a750d06SEvan Bacon expect(envRuntime._getForce('/')).toEqual({ 194*e30a2315SEvan Bacon files: ['/.env.local', '/.env'], 195*e30a2315SEvan Bacon env: { 1966a750d06SEvan Bacon FOO: 'default-local', 197*e30a2315SEvan Bacon }, 1986a750d06SEvan Bacon }); 1996a750d06SEvan Bacon }); 2006a750d06SEvan Bacon 20178a6243aSEvan Bacon it(`skips modifying the environment with dotenv if disabled with EXPO_NO_DOTENV`, () => { 20278a6243aSEvan Bacon delete process.env.FOO; 20378a6243aSEvan Bacon process.env.EXPO_NO_DOTENV = '1'; 20478a6243aSEvan Bacon const envRuntime = createControlledEnvironment(); 20578a6243aSEvan Bacon vol.fromJSON( 20678a6243aSEvan Bacon { 20778a6243aSEvan Bacon '.env': 'FOO=default', 20878a6243aSEvan Bacon '.env.local': 'FOO=default-local', 20978a6243aSEvan Bacon }, 21078a6243aSEvan Bacon '/' 21178a6243aSEvan Bacon ); 21278a6243aSEvan Bacon 213*e30a2315SEvan Bacon expect(envRuntime._getForce('/')).toEqual({ env: {}, files: [] }); 21478a6243aSEvan Bacon }); 21578a6243aSEvan Bacon 2166a750d06SEvan Bacon it(`does not return the env var if the initial the value of the environment variable`, () => { 2176a750d06SEvan Bacon const envRuntime = createControlledEnvironment(); 2186a750d06SEvan Bacon process.env.FOO = 'not-bar'; 2196a750d06SEvan Bacon 2206a750d06SEvan Bacon vol.fromJSON( 2216a750d06SEvan Bacon { 2226a750d06SEvan Bacon '.env': 'FOO=bar', 2236a750d06SEvan Bacon }, 2246a750d06SEvan Bacon '/' 2256a750d06SEvan Bacon ); 2266a750d06SEvan Bacon 227*e30a2315SEvan Bacon expect(envRuntime._getForce('/')).toEqual({ env: {}, files: ['/.env'] }); 2286a750d06SEvan Bacon }); 2296a750d06SEvan Bacon 2306a750d06SEvan Bacon it(`Does not fail when no files are available`, () => { 2316a750d06SEvan Bacon vol.fromJSON({}, '/'); 232*e30a2315SEvan Bacon expect(createControlledEnvironment()._getForce('/')).toEqual({ 233*e30a2315SEvan Bacon env: {}, 234*e30a2315SEvan Bacon files: [], 235*e30a2315SEvan Bacon }); 2366a750d06SEvan Bacon }); 2376a750d06SEvan Bacon 2386a750d06SEvan Bacon it(`Does not assert on invalid env files`, () => { 2396a750d06SEvan Bacon vol.fromJSON( 2406a750d06SEvan Bacon { 2416a750d06SEvan Bacon '.env': 'ˆ˙•ª∆ø…ˆ', 2426a750d06SEvan Bacon }, 2436a750d06SEvan Bacon '/' 2446a750d06SEvan Bacon ); 2456a750d06SEvan Bacon 246*e30a2315SEvan Bacon expect(createControlledEnvironment()._getForce('/')).toEqual({ env: {}, files: ['/.env'] }); 2476a750d06SEvan Bacon }); 2486a750d06SEvan Bacon}); 249