UNPKG

12.3 kBJavaScriptView Raw
1const fs = require('fs');
2const path = require('path');
3const glob = require('glob');
4const dotenv = require('dotenv');
5const SlateConfig = require('@shopify/slate-config');
6
7const slateEnv = require('../index');
8const config = new SlateConfig(require('../slate-env.schema'));
9
10const envPath = path.resolve(
11 config.get('env.rootDirectory'),
12 config.get('env.basename'),
13);
14
15const TEST_ENV = {
16 [config.get('env.keys.name')]: 'production',
17 [config.get('env.keys.store')]: 'test-shop.myshopify.com',
18 [config.get('env.keys.password')]: '123456789',
19 [config.get('env.keys.themeId')]: '987654321',
20 [config.get('env.keys.ignoreFiles')]: 'config/settings_data.json',
21 [config.get('env.keys.userEmail')]: 'test@email.com',
22};
23
24function setVars(vars) {
25 for (const key in vars) {
26 if (vars.hasOwnProperty(key)) {
27 process.env[key] = vars[key];
28 }
29 }
30}
31
32function clearVars(vars) {
33 for (const key in vars) {
34 if (vars.hasOwnProperty(key)) {
35 delete process.env[key];
36 }
37 }
38}
39
40afterEach(() => {
41 clearVars(TEST_ENV);
42 glob.sync(`${envPath}*`).forEach((file) => fs.unlinkSync(file));
43});
44
45describe('Slate Env', () => {
46 describe('clear()', () => {
47 beforeEach(() => {
48 setVars(TEST_ENV);
49 });
50
51 test('Clears all the values assigned to Slate environment variables', () => {
52 slateEnv.clear();
53
54 for (const key in TEST_ENV) {
55 if (TEST_ENV.hasOwnProperty(key)) {
56 expect(process.env[key]).toBe('');
57 }
58 }
59 });
60 });
61
62 describe('getSlateEnv()', () => {
63 beforeEach(() => {
64 setVars(TEST_ENV);
65 });
66
67 test('returns object containing all env variables without current values', () => {
68 expect(slateEnv.getSlateEnv()).toEqual(TEST_ENV);
69 });
70 });
71
72 describe('getDefaultSlateEnv', () => {
73 test('returns an object which contains the default variables and values of an env file', () => {
74 const emptyTestVars = {
75 [config.get('env.keys.store')]: '',
76 [config.get('env.keys.password')]: '',
77 [config.get('env.keys.themeId')]: '',
78 [config.get('env.keys.ignoreFiles')]: '',
79 };
80
81 expect(slateEnv.getDefaultSlateEnv()).toEqual(emptyTestVars);
82 });
83 });
84
85 describe('getEmptySlateEnv()', () => {
86 test('returns object containing all env file variables with empty values', () => {
87 const emptyTestVars = Object.assign({}, TEST_ENV);
88
89 for (const key in emptyTestVars) {
90 if (emptyTestVars.hasOwnProperty(key)) {
91 emptyTestVars[key] = '';
92 }
93 }
94
95 expect(slateEnv.getEmptySlateEnv()).toEqual(emptyTestVars);
96 });
97 });
98
99 describe('create()', () => {
100 describe('generates an .env file', () => {
101 test('with empty config values', () => {
102 slateEnv.create();
103
104 const envParsed = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
105
106 expect(envParsed).toEqual({
107 [config.get('env.keys.store')]: '',
108 [config.get('env.keys.password')]: '',
109 [config.get('env.keys.themeId')]: '',
110 [config.get('env.keys.ignoreFiles')]: '',
111 });
112 });
113
114 test('with specified config values', () => {
115 const env = slateEnv.getEmptySlateEnv();
116 const store = 'test-shop.myshopify.com';
117
118 env[config.get('env.keys.store')] = store;
119 slateEnv.create({values: env});
120
121 const envParsed = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
122
123 expect(envParsed).toHaveProperty(config.get('env.keys.store'), store);
124 });
125
126 test('with invalid config values ommited', () => {
127 const env = slateEnv.getEmptySlateEnv();
128 const store = 'test-shop.myshopify.com';
129 const invalidKey = 'INVALID_VARIABLE';
130 const invalidValue = 'some value';
131
132 env[config.get('env.keys.store')] = store;
133 env[invalidKey] = invalidValue;
134 slateEnv.create({values: env});
135
136 const envParsed = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
137
138 expect(envParsed).toHaveProperty(config.get('env.keys.store'), store);
139 expect(envParsed).not.toHaveProperty(invalidKey, invalidValue);
140 });
141
142 test('when a valid name is provided', () => {
143 const name = 'production';
144 const namedEnvPath = envPath.concat(`.${name}`);
145
146 slateEnv.create({name});
147 expect(fs.existsSync(namedEnvPath)).toBeTruthy();
148 });
149
150 test('when no name is provided', () => {
151 slateEnv.create();
152 expect(fs.existsSync(envPath)).toBeTruthy();
153 });
154
155 test('when an empty name ("") is provided', () => {
156 slateEnv.create({}, '');
157 expect(fs.existsSync(envPath)).toBeTruthy();
158 });
159
160 test('when a whitespace name (" ") is provided', () => {
161 slateEnv.create({}, ' ');
162 expect(fs.existsSync(envPath)).toBeTruthy();
163 });
164 });
165 });
166
167 describe('assign()', () => {
168 beforeEach(() => {
169 slateEnv.create({values: TEST_ENV});
170 slateEnv.create({values: TEST_ENV, name: 'production'});
171 });
172
173 test('reads default env file and assigns values to environment variables', () => {
174 slateEnv.assign();
175 expect(process.env[config.get('env.keys.store')]).toBe(
176 TEST_ENV[config.get('env.keys.store')],
177 );
178 });
179
180 test('reads named env file and assigns values to environment variables', () => {
181 slateEnv.assign('production');
182 expect(process.env[config.get('env.keys.store')]).toBe(
183 TEST_ENV[config.get('env.keys.store')],
184 );
185 });
186
187 test('does not overwrite an environment variable if it already has a value', () => {
188 const store = 'other-value.myshopify.com';
189 process.env[config.get('env.keys.store')] = store;
190 slateEnv.assign();
191
192 expect(process.env[config.get('env.keys.store')]).toBe(store);
193 });
194
195 test("throw an error if a name is provided and the env file doesn't exist", () => {
196 expect(() => slateEnv.assign('nope')).toThrow();
197 });
198 });
199
200 describe('getEnvName()', () => {
201 describe('if a env name is specified', () => {
202 beforeEach(() => {
203 slateEnv.create({values: TEST_ENV, name: 'production'});
204 slateEnv.assign('production');
205 });
206
207 test('returns the name of the environment', () => {
208 expect(slateEnv.getEnvNameValue()).toBe('production');
209 });
210 });
211
212 describe('if a env name is not specified', () => {
213 test(`returns the name '${config.get(
214 'env.defaultEnvName',
215 )}' if the default env file is present`, () => {
216 slateEnv.create(TEST_ENV);
217 slateEnv.assign();
218 expect(slateEnv.getEnvNameValue()).toBe(
219 config.get('env.defaultEnvName'),
220 );
221 });
222 test(`returns the name '${config.get(
223 'env.externalEnvName',
224 )}' if the default env file is not present`, () => {
225 slateEnv.assign();
226 expect(slateEnv.getEnvNameValue()).toBe(
227 config.get('env.externalEnvName'),
228 );
229 });
230 });
231 });
232
233 describe('getStoreValue()', () => {
234 test('returns the value of the environment variable that references the store URL', () => {
235 process.env[config.get('env.keys.store')] =
236 TEST_ENV[config.get('env.keys.store')];
237 expect(slateEnv.getStoreValue()).toBe(
238 TEST_ENV[config.get('env.keys.store')],
239 );
240 });
241
242 test('returns an empty string if the value is undefined', () => {
243 expect(slateEnv.getStoreValue()).toBe('');
244 });
245 });
246
247 describe('getPasswordValue()', () => {
248 test('returns the value of the environment variable that references the store API password', () => {
249 process.env[config.get('env.keys.password')] =
250 TEST_ENV[config.get('env.keys.password')];
251 expect(slateEnv.getPasswordValue()).toBe(
252 TEST_ENV[config.get('env.keys.password')],
253 );
254 });
255
256 test('returns an empty string if the value is undefined', () => {
257 expect(slateEnv.getPasswordValue()).toBe('');
258 });
259 });
260
261 describe('getThemeIdValue()', () => {
262 test('returns the value of the environment variable that references the store theme ID', () => {
263 process.env[config.get('env.keys.themeId')] =
264 TEST_ENV[config.get('env.keys.themeId')];
265 expect(slateEnv.getThemeIdValue()).toBe(
266 TEST_ENV[config.get('env.keys.themeId')],
267 );
268 });
269
270 test('returns an empty string if the value is undefined', () => {
271 expect(slateEnv.getThemeIdValue()).toBe('');
272 });
273 });
274
275 describe('getIgnoreFilesValue()', () => {
276 test('returns the value of the environment variable that references a list of files to ignore', () => {
277 process.env[config.get('env.keys.ignoreFiles')] =
278 TEST_ENV[config.get('env.keys.ignoreFiles')];
279 expect(slateEnv.getIgnoreFilesValue()).toBe(
280 TEST_ENV[config.get('env.keys.ignoreFiles')],
281 );
282 });
283
284 test('returns an empty string if the value is undefined', () => {
285 expect(slateEnv.getIgnoreFilesValue()).toBe('');
286 });
287 });
288
289 describe('validate()', () => {
290 describe('returns an object with an .isValid prop', () => {
291 test('that is true if no validation .errors is empty', () => {
292 setVars(TEST_ENV);
293 const result = slateEnv.validate();
294 expect(result).toHaveProperty('isValid', true);
295 expect(result.errors).toBeDefined();
296 expect(result.errors).toHaveLength(0);
297 });
298
299 test('that is false validation .errors is not empty', () => {
300 const result = slateEnv.validate();
301 expect(result).toHaveProperty('isValid', false);
302 expect(result.errors).toBeDefined();
303 expect(result.errors.length).toBeGreaterThan(0);
304 });
305 });
306 describe('returns errors if', () => {
307 test('the store URL environment variable is empty', () => {
308 setVars(
309 Object.assign({}, TEST_ENV, {
310 [config.get('env.keys.store')]: '',
311 }),
312 );
313 const result = slateEnv.validate();
314 expect(result.errors).toHaveLength(1);
315 });
316
317 test('the store URL environment variable is not a .myshopify.com or myshopify.io URL', () => {
318 ['shop1.myshopify.com', 'shop1.myshopify.io', 'shop1'].forEach(
319 (value) => {
320 setVars(
321 Object.assign({}, TEST_ENV, {
322 [config.get('env.keys.store')]: value,
323 }),
324 );
325 const result = slateEnv.validate();
326 expect(result.errors).toHaveLength(value === 'shop1' ? 1 : 0);
327 },
328 );
329 });
330
331 test('the store URL environment variable does not end with a trailing slash', () => {
332 ['shop1.myshopify.com', 'shop1.myshopify.com/'].forEach((value) => {
333 setVars(
334 Object.assign({}, TEST_ENV, {
335 [config.get('env.keys.store')]: value,
336 }),
337 );
338 const result = slateEnv.validate();
339 expect(result.errors).toHaveLength(
340 value === 'shop1.myshopify.com/' ? 1 : 0,
341 );
342 });
343 });
344
345 test('the store API password environment variable is empty', () => {
346 setVars(
347 Object.assign({}, TEST_ENV, {
348 [config.get('env.keys.password')]: '',
349 }),
350 );
351 const result = slateEnv.validate();
352 expect(result.errors).toHaveLength(1);
353 });
354
355 test('the store API password environment variable has invalid characters', () => {
356 setVars(
357 Object.assign({}, TEST_ENV, {
358 [config.get('env.keys.password')]: '8h1j-dnjn8',
359 }),
360 );
361 const result = slateEnv.validate();
362 expect(result.errors).toHaveLength(1);
363 });
364
365 test('the store Theme ID environment variable is empty', () => {
366 setVars(
367 Object.assign({}, TEST_ENV, {
368 [config.get('env.keys.themeId')]: '',
369 }),
370 );
371 const result = slateEnv.validate();
372 expect(result.errors).toHaveLength(1);
373 });
374
375 test("the store Theme ID environment variable is not 'live' or a string of numbers", () => {
376 setVars(
377 Object.assign({}, TEST_ENV, {
378 [config.get('env.keys.themeId')]: 'ds7dsh8d',
379 }),
380 );
381 const result = slateEnv.validate();
382 expect(result.errors).toHaveLength(1);
383 });
384 });
385 });
386});