move fileScope to separate module, update dependencies and devDependencies
[squeep-api-dingus] / test / lib / common.js
1 /* eslint-disable capitalized-comments */
2 /* eslint-env mocha */
3 'use strict';
4
5 const assert = require('assert');
6 const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require
7 const common = require('../../lib/common');
8
9
10 describe('common', function () {
11
12 describe('generateETag', function () {
13 it('generates a tag from data', function () {
14 const expected = '"RHUvNyculE/SyROjU0LqzN0arxibrlBnazAashP8UGE"';
15 const data = 'example data';
16 const result = common.generateETag(undefined, undefined, data);
17 assert.strictEqual(result, expected);
18 });
19 it('generates a tag from data and stats', function () {
20 const expected = '"mtI0qCyqXsZVfX0Pgi+G6mQM10y9yVyi1NZejXSYttk"';
21 const stat = {
22 mtimeMs: 1600113038270.2375,
23 };
24 const data = 'example data';
25 const result = common.generateETag(undefined, stat, data);
26 assert.strictEqual(result, expected);
27 });
28 }); // generateETag
29
30 describe('get', function () {
31 const def = 'default';
32 it('covers missing obj', function () {
33 const result = common.get(undefined, undefined, def);
34 assert.strictEqual(result, def);
35 });
36 it('covers missing prop', function () {
37 const result = common.get({}, undefined, def);
38 assert.strictEqual(result, def);
39 });
40 it('covers default', function () {
41 const result = common.get({ k: 'v' }, 'x', def);
42 assert.strictEqual(result, def);
43 });
44 it('covers prop', function () {
45 const result = common.get({ k: 'v' }, 'k', def);
46 assert.strictEqual(result, 'v');
47 });
48 }); // get
49
50 describe('isClientCached', function () {
51 let req, modifiedTimeMs, eTag;
52 const blueMoon = 'Sat, 31 Oct 2020 07:51:00 GMT';
53 const blueMoonMs = 1604130660000;
54 const oneDayMs = 86400000;
55 const anotherETag = '"RHUvNyculE/SyROjU0LqzN0arxibrlBnazAashP8UGE"';
56 beforeEach(function () {
57 req = {
58 getHeader: sinon.stub(),
59 };
60 modifiedTimeMs = 0;
61 eTag = '"mtI0qCyqXsZVfX0Pgi+G6mQM10y9yVyi1NZejXSYttk"';
62 });
63 it('no headers, not cached', function () {
64 const result = common.isClientCached(req, modifiedTimeMs, eTag);
65 assert.strictEqual(result, false);
66 });
67 it('modified header, not cached', function () {
68 req.getHeader.onCall(0).returns(blueMoon);
69 modifiedTimeMs = blueMoonMs + oneDayMs;
70 const result = common.isClientCached(req, modifiedTimeMs, eTag);
71 assert.strictEqual(result, false);
72 });
73 it('modified header, cached', function () {
74 req.getHeader.onCall(0).returns(blueMoon);
75 modifiedTimeMs = blueMoonMs - oneDayMs;
76 const result = common.isClientCached(req, modifiedTimeMs, eTag);
77 assert.strictEqual(result, true);
78 });
79 it('match header, not matched', function () {
80 req.getHeader.onCall(1).returns(anotherETag);
81 const result = common.isClientCached(req, modifiedTimeMs, eTag);
82 assert.strictEqual(result, false);
83 });
84 it('match header, matched', function () {
85 req.getHeader.onCall(1).returns(`${anotherETag}, ${eTag}, ${anotherETag}`);
86 const result = common.isClientCached(req, modifiedTimeMs, eTag);
87 assert.strictEqual(result, true);
88 });
89 it('match header any, matched', function () {
90 req.getHeader.onCall(1).returns('*');
91 const result = common.isClientCached(req, modifiedTimeMs, eTag);
92 assert.strictEqual(result, true);
93 });
94 it('modified header cached, match header not matched, not cached', function () {
95 req.getHeader.onCall(0).returns(blueMoon);
96 modifiedTimeMs = blueMoonMs - oneDayMs;
97 req.getHeader.onCall(1).returns(`${anotherETag}, ${anotherETag}`);
98 const result = common.isClientCached(req, modifiedTimeMs, eTag);
99 assert.strictEqual(result, false);
100 });
101 }); // iscClientCached
102
103 describe('pick', function () {
104 it('picks', function () {
105 const srcObj = {
106 a: 1,
107 b: 2,
108 c: 3,
109 };
110 const result = common.pick(srcObj, ['a', 'c', 'd']);
111 assert.deepStrictEqual(result, {
112 'a': 1,
113 'c': 3,
114 });
115 });
116 }); // pick
117
118 describe('setOptions', function () {
119 it('sets options', function () {
120 const expected = {
121 keyOne: 'default',
122 keyTwo: 'option',
123 keyThree: 'default',
124 };
125 const target = {};
126 const defaultOptions = {
127 keyOne: 'default',
128 keyTwo: 'default',
129 keyThree: 'default',
130 };
131 const options = {
132 keyTwo: 'option',
133 keyFour: 'option',
134 };
135 common.setOptions(target, defaultOptions, options);
136 assert.deepStrictEqual(target, expected);
137 });
138 }); // setOptions
139
140 describe('splitFirst', function () {
141 it('splits', function () {
142 const expected = ['foo', 'awoo'];
143 const src = 'foo?awoo';
144 const delim = '?';
145 const fill = 'fill';
146 const result = common.splitFirst(src, delim, fill);
147 assert.deepStrictEqual(result, expected);
148 });
149 it('fills', function () {
150 const expected = ['foo', 'fill'];
151 const src = 'foo';
152 const delim = '?';
153 const fill = 'fill';
154 const result = common.splitFirst(src, delim, fill);
155 assert.deepStrictEqual(result, expected);
156 });
157 }); // splitFirst
158
159 describe('mergeEnum', function () {
160 it('merges enums', function () {
161 const origEnum = {
162 ContentType: {
163 TextHTML: 'text/html',
164 },
165 ErrorResponse: {
166 BadRequest: {
167 statusCode: 400,
168 errorMessage: 'Bad Request',
169 },
170 },
171 };
172 const newEnum = {
173 ContentType: {
174 TextPlain: 'text/plain',
175 },
176 ErrorResponse: {
177 BadResponse: {
178 statusCode: 401,
179 errorMessage: 'Unauthorized',
180 },
181 },
182 Header: {
183 Accept: 'accept',
184 },
185 Value: 'value',
186 };
187 const mergedEnum = {
188 ContentType: {
189 TextHTML: 'text/html',
190 TextPlain: 'text/plain',
191 },
192 ErrorResponse: {
193 BadRequest: {
194 statusCode: 400,
195 errorMessage: 'Bad Request',
196 },
197 BadResponse: {
198 statusCode: 401,
199 errorMessage: 'Unauthorized',
200 },
201 },
202 Header: {
203 Accept: 'accept',
204 },
205 Value: 'value',
206 };
207 const result = common.mergeEnum(origEnum, newEnum);
208 assert.deepStrictEqual(result, mergedEnum);
209 });
210 }); // mergeEnum
211
212 describe('requestId', function () {
213 it('returns a string', function () {
214 const id = common.requestId();
215 assert.strictEqual(typeof id, 'string');
216 assert(id.length > 0);
217 });
218 }); // requestId
219
220 describe('httpStatusCodeClass', function () {
221 it('works', function () {
222 for (const [statusCode, statusClassExpected] of Object.entries({
223 200: 2,
224 304: 3,
225 404: 4,
226 500: 5,
227 })) {
228 const statusClass = common.httpStatusCodeClass(statusCode);
229 assert.strictEqual(statusClass, statusClassExpected);
230 }
231 });
232 }); // ensureLoggerLevels
233
234 describe('mergeDeep', function () {
235 it('simple merge', function () {
236 const o1 = {
237 foo1: 'one',
238 };
239 const o2 = {
240 foo2: 'two',
241 };
242 const o3 = {
243 foo3: 'three',
244 };
245 const expected = {
246 foo1: 'one',
247 foo2: 'two',
248 foo3: 'three',
249 };
250 const result = common.mergeDeep(o1, o2, o3);
251 assert.deepStrictEqual(result, expected);
252 });
253 it('deep merge', function () {
254 const o1 = {
255 foo: {
256 quux: 1,
257 },
258 bar: 'baz',
259 };
260 const o2 = {
261 foo: {
262 myList: ['fancy'],
263 gleep: {
264 fraz: 2,
265 },
266 },
267 blah: 'frop',
268 };
269 const o3 = {
270 foo: {
271 myList: ['pants'],
272 gleep: {
273 troz: 'poit',
274 },
275 narf: 3,
276 },
277 bar: 'yup',
278 };
279 const expected = {
280 foo: {
281 myList: ['fancy', 'pants'],
282 gleep: {
283 fraz: 2,
284 troz: 'poit',
285 },
286 narf: 3,
287 quux: 1,
288 },
289 bar: 'yup',
290 blah: 'frop',
291 };
292 const result = common.mergeDeep(o1, o2, o3);
293 assert.deepStrictEqual(result, expected);
294 });
295 it('merged object is distinct', function () {
296 const o1 = {
297 foo: {
298 bar: 3,
299 },
300 };
301 const o2 = {
302 baz: {
303 quux: 4,
304 },
305 };
306 const expected = {
307 foo: {
308 bar: 3,
309 },
310 baz: {
311 quux: 4,
312 },
313 };
314 const result = common.mergeDeep(o1, o2);
315 assert.deepStrictEqual(result, expected);
316 const expected2 = {
317 foo: {
318 bar: 5,
319 },
320 baz: {
321 quux: 5,
322 },
323 };
324 result.foo.bar = 5;
325 result.baz.quux = 5;
326 assert.deepStrictEqual(result, expected2);
327 assert.strictEqual(o1.foo.bar, 3);
328 assert.strictEqual(o2.baz.quux, 4);
329 });
330 }); // mergeDeep
331
332 describe('unfoldHeaderLines', function () {
333 it('folds', function () {
334 const lines = [
335 'Normal-Header: some header data',
336 'Folded-Header: more data',
337 ' second line of data',
338 ' third line of data',
339 ];
340 const expected = [
341 'Normal-Header: some header data',
342 'Folded-Header: more data second line of data third line of data',
343 ];
344 const result = common.unfoldHeaderLines(lines);
345 assert.deepStrictEqual(result, expected);
346 });
347 it('covers no input', function () {
348 const lines = undefined;
349 const result = common.unfoldHeaderLines();
350 assert.deepStrictEqual(result, lines);
351 });
352 }); // unfoldHeaderLines
353
354 });