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