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 const originalError = console.error; 48 beforeEach(() => { 49 console.error = jest.fn(); 50 }); 51 afterEach(() => { 52 console.error = originalError; 53 }); 54 55 it(`throws if NODE_ENV is not set`, () => { 56 getFiles(undefined); 57 58 expect(console.error).toBeCalledTimes(2); 59 expect(console.error).toBeCalledWith( 60 expect.stringContaining('The NODE_ENV environment variable is required but was not specified') 61 ); 62 }); 63 it(`throws if NODE_ENV is not valid`, () => { 64 expect(() => getFiles('invalid')).toThrowErrorMatchingInlineSnapshot( 65 `"Environment variable "NODE_ENV=invalid" is invalid. Valid values are "development", "test", and "production"` 66 ); 67 }); 68}); 69 70describe('get', () => { 71 beforeEach(() => { 72 resetEnv(); 73 }); 74 75 it(`memoizes`, () => { 76 delete process.env.FOO; 77 const envRuntime = createControlledEnvironment(); 78 vol.fromJSON( 79 { 80 '.env': 'FOO=default', 81 }, 82 '/' 83 ); 84 expect(envRuntime.get('/')).toEqual({ 85 FOO: 'default', 86 }); 87 88 fs.writeFileSync('/.env', 'FOO=changed'); 89 90 expect(envRuntime.get('/')).toEqual({ 91 FOO: 'default', 92 }); 93 expect(envRuntime.get('/', { force: true })).toEqual({ 94 FOO: 'changed', 95 }); 96 }); 97}); 98describe('_getForce', () => { 99 beforeEach(() => { 100 resetEnv(); 101 }); 102 103 it(`returns the value of the environment variable`, () => { 104 delete process.env.FOO; 105 106 const envRuntime = createControlledEnvironment(); 107 vol.fromJSON( 108 { 109 '.env': 'FOO=bar', 110 }, 111 '/' 112 ); 113 114 expect(envRuntime._getForce('/')).toEqual({ 115 FOO: 'bar', 116 }); 117 }); 118 119 it(`cascades env files (development)`, () => { 120 delete process.env.FOO; 121 process.env.NODE_ENV = 'development'; 122 const envRuntime = createControlledEnvironment(); 123 vol.fromJSON( 124 { 125 '.env': 'FOO=default', 126 '.env.local': 'FOO=default-local', 127 '.env.development': 'FOO=dev', 128 '.env.production': 'FOO=prod', 129 '.env.production.local': 'FOO=prod-local', 130 '.env.development.local': 'FOO=dev-local', 131 }, 132 '/' 133 ); 134 135 expect(envRuntime._getForce('/')).toEqual({ 136 FOO: 'dev-local', 137 }); 138 }); 139 140 it(`cascades env files (production)`, () => { 141 delete process.env.FOO; 142 process.env.NODE_ENV = 'production'; 143 const envRuntime = createControlledEnvironment(); 144 vol.fromJSON( 145 { 146 '.env': 'FOO=default', 147 '.env.local': 'FOO=default-local', 148 '.env.production': 'FOO=prod', 149 '.env.production.local': 'FOO=prod-local', 150 }, 151 '/' 152 ); 153 154 expect(envRuntime._getForce('/')).toEqual({ 155 FOO: 'prod-local', 156 }); 157 }); 158 159 it(`cascades env files (default)`, () => { 160 delete process.env.FOO; 161 const envRuntime = createControlledEnvironment(); 162 vol.fromJSON( 163 { 164 '.env': 'FOO=default', 165 '.env.local': 'FOO=default-local', 166 }, 167 '/' 168 ); 169 170 expect(envRuntime._getForce('/')).toEqual({ 171 FOO: 'default-local', 172 }); 173 }); 174 175 it(`does not return the env var if the initial the value of the environment variable`, () => { 176 const envRuntime = createControlledEnvironment(); 177 process.env.FOO = 'not-bar'; 178 179 vol.fromJSON( 180 { 181 '.env': 'FOO=bar', 182 }, 183 '/' 184 ); 185 186 expect(envRuntime._getForce('/')).toEqual({}); 187 }); 188 189 it(`Does not fail when no files are available`, () => { 190 vol.fromJSON({}, '/'); 191 expect(createControlledEnvironment()._getForce('/')).toEqual({}); 192 }); 193 194 it(`Does not assert on invalid env files`, () => { 195 vol.fromJSON( 196 { 197 '.env': 'ˆ˙•ª∆ø…ˆ', 198 }, 199 '/' 200 ); 201 202 expect(createControlledEnvironment()._getForce('/')).toEqual({}); 203 }); 204}); 205