1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', {
|
4 | value: true
|
5 | });
|
6 | exports.emptyObject = emptyObject;
|
7 | exports.isOneline =
|
8 | exports.isError =
|
9 | exports.pathAsArray =
|
10 | exports.partition =
|
11 | exports.sparseArrayEquality =
|
12 | exports.arrayBufferEquality =
|
13 | exports.typeEquality =
|
14 | exports.subsetEquality =
|
15 | exports.iterableEquality =
|
16 | exports.getObjectSubset =
|
17 | exports.getPath =
|
18 | void 0;
|
19 |
|
20 | var _jestGetType = require('jest-get-type');
|
21 |
|
22 | var _jasmineUtils = require('./jasmineUtils');
|
23 |
|
24 | var global = (function () {
|
25 | if (typeof globalThis !== 'undefined') {
|
26 | return globalThis;
|
27 | } else if (typeof global !== 'undefined') {
|
28 | return global;
|
29 | } else if (typeof self !== 'undefined') {
|
30 | return self;
|
31 | } else if (typeof window !== 'undefined') {
|
32 | return window;
|
33 | } else {
|
34 | return Function('return this')();
|
35 | }
|
36 | })();
|
37 |
|
38 | var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | const hasPropertyInObject = (object, key) => {
|
44 | const shouldTerminate =
|
45 | !object || typeof object !== 'object' || object === Object.prototype;
|
46 |
|
47 | if (shouldTerminate) {
|
48 | return false;
|
49 | }
|
50 |
|
51 | return (
|
52 | Object.prototype.hasOwnProperty.call(object, key) ||
|
53 | hasPropertyInObject(Object.getPrototypeOf(object), key)
|
54 | );
|
55 | };
|
56 |
|
57 | const getPath = (object, propertyPath) => {
|
58 | if (!Array.isArray(propertyPath)) {
|
59 | propertyPath = pathAsArray(propertyPath);
|
60 | }
|
61 |
|
62 | if (propertyPath.length) {
|
63 | const lastProp = propertyPath.length === 1;
|
64 | const prop = propertyPath[0];
|
65 | const newObject = object[prop];
|
66 |
|
67 | if (!lastProp && (newObject === null || newObject === undefined)) {
|
68 |
|
69 |
|
70 |
|
71 | return {
|
72 | hasEndProp: false,
|
73 | lastTraversedObject: object,
|
74 | traversedPath: []
|
75 | };
|
76 | }
|
77 |
|
78 | const result = getPath(newObject, propertyPath.slice(1));
|
79 |
|
80 | if (result.lastTraversedObject === null) {
|
81 | result.lastTraversedObject = object;
|
82 | }
|
83 |
|
84 | result.traversedPath.unshift(prop);
|
85 |
|
86 | if (lastProp) {
|
87 |
|
88 |
|
89 |
|
90 | result.hasEndProp =
|
91 | newObject !== undefined ||
|
92 | (!(0, _jestGetType.isPrimitive)(object) && prop in object);
|
93 |
|
94 | if (!result.hasEndProp) {
|
95 | result.traversedPath.shift();
|
96 | }
|
97 | }
|
98 |
|
99 | return result;
|
100 | }
|
101 |
|
102 | return {
|
103 | lastTraversedObject: null,
|
104 | traversedPath: [],
|
105 | value: object
|
106 | };
|
107 | };
|
108 |
|
109 |
|
110 |
|
111 |
|
112 | exports.getPath = getPath;
|
113 |
|
114 | const getObjectSubset = (object, subset, seenReferences = new WeakMap()) => {
|
115 |
|
116 | if (Array.isArray(object)) {
|
117 | if (Array.isArray(subset) && subset.length === object.length) {
|
118 |
|
119 | return subset.map((sub, i) => getObjectSubset(object[i], sub));
|
120 | }
|
121 | } else if (object instanceof Date) {
|
122 | return object;
|
123 | } else if (isObject(object) && isObject(subset)) {
|
124 | if (
|
125 | (0, _jasmineUtils.equals)(object, subset, [
|
126 | iterableEquality,
|
127 | subsetEquality
|
128 | ])
|
129 | ) {
|
130 |
|
131 | return subset;
|
132 | }
|
133 |
|
134 | const trimmed = {};
|
135 | seenReferences.set(object, trimmed);
|
136 | Object.keys(object)
|
137 | .filter(key => hasPropertyInObject(subset, key))
|
138 | .forEach(key => {
|
139 | trimmed[key] = seenReferences.has(object[key])
|
140 | ? seenReferences.get(object[key])
|
141 | : getObjectSubset(object[key], subset[key], seenReferences);
|
142 | });
|
143 |
|
144 | if (Object.keys(trimmed).length > 0) {
|
145 | return trimmed;
|
146 | }
|
147 | }
|
148 |
|
149 | return object;
|
150 | };
|
151 |
|
152 | exports.getObjectSubset = getObjectSubset;
|
153 | const IteratorSymbol = Symbol.iterator;
|
154 |
|
155 | const hasIterator = object => !!(object != null && object[IteratorSymbol]);
|
156 |
|
157 |
|
158 | const iterableEquality = (
|
159 | a,
|
160 | b,
|
161 |
|
162 | aStack = [],
|
163 | bStack = []
|
164 | ) => {
|
165 | if (
|
166 | typeof a !== 'object' ||
|
167 | typeof b !== 'object' ||
|
168 | Array.isArray(a) ||
|
169 | Array.isArray(b) ||
|
170 | !hasIterator(a) ||
|
171 | !hasIterator(b)
|
172 | ) {
|
173 | return undefined;
|
174 | }
|
175 |
|
176 | if (a.constructor !== b.constructor) {
|
177 | return false;
|
178 | }
|
179 |
|
180 | let length = aStack.length;
|
181 |
|
182 | while (length--) {
|
183 |
|
184 |
|
185 |
|
186 |
|
187 | if (aStack[length] === a) {
|
188 | return bStack[length] === b;
|
189 | }
|
190 | }
|
191 |
|
192 | aStack.push(a);
|
193 | bStack.push(b);
|
194 |
|
195 | const iterableEqualityWithStack = (a, b) =>
|
196 | iterableEquality(a, b, [...aStack], [...bStack]);
|
197 |
|
198 | if (a.size !== undefined) {
|
199 | if (a.size !== b.size) {
|
200 | return false;
|
201 | } else if (
|
202 | (0, _jasmineUtils.isA)('Set', a) ||
|
203 | (0, _jasmineUtils.isImmutableUnorderedSet)(a)
|
204 | ) {
|
205 | let allFound = true;
|
206 |
|
207 | for (const aValue of a) {
|
208 | if (!b.has(aValue)) {
|
209 | let has = false;
|
210 |
|
211 | for (const bValue of b) {
|
212 | const isEqual = (0, _jasmineUtils.equals)(aValue, bValue, [
|
213 | iterableEqualityWithStack
|
214 | ]);
|
215 |
|
216 | if (isEqual === true) {
|
217 | has = true;
|
218 | }
|
219 | }
|
220 |
|
221 | if (has === false) {
|
222 | allFound = false;
|
223 | break;
|
224 | }
|
225 | }
|
226 | }
|
227 |
|
228 | aStack.pop();
|
229 | bStack.pop();
|
230 | return allFound;
|
231 | } else if (
|
232 | (0, _jasmineUtils.isA)('Map', a) ||
|
233 | (0, _jasmineUtils.isImmutableUnorderedKeyed)(a)
|
234 | ) {
|
235 | let allFound = true;
|
236 |
|
237 | for (const aEntry of a) {
|
238 | if (
|
239 | !b.has(aEntry[0]) ||
|
240 | !(0, _jasmineUtils.equals)(aEntry[1], b.get(aEntry[0]), [
|
241 | iterableEqualityWithStack
|
242 | ])
|
243 | ) {
|
244 | let has = false;
|
245 |
|
246 | for (const bEntry of b) {
|
247 | const matchedKey = (0, _jasmineUtils.equals)(aEntry[0], bEntry[0], [
|
248 | iterableEqualityWithStack
|
249 | ]);
|
250 | let matchedValue = false;
|
251 |
|
252 | if (matchedKey === true) {
|
253 | matchedValue = (0, _jasmineUtils.equals)(aEntry[1], bEntry[1], [
|
254 | iterableEqualityWithStack
|
255 | ]);
|
256 | }
|
257 |
|
258 | if (matchedValue === true) {
|
259 | has = true;
|
260 | }
|
261 | }
|
262 |
|
263 | if (has === false) {
|
264 | allFound = false;
|
265 | break;
|
266 | }
|
267 | }
|
268 | }
|
269 |
|
270 | aStack.pop();
|
271 | bStack.pop();
|
272 | return allFound;
|
273 | }
|
274 | }
|
275 |
|
276 | const bIterator = b[IteratorSymbol]();
|
277 |
|
278 | for (const aValue of a) {
|
279 | const nextB = bIterator.next();
|
280 |
|
281 | if (
|
282 | nextB.done ||
|
283 | !(0, _jasmineUtils.equals)(aValue, nextB.value, [
|
284 | iterableEqualityWithStack
|
285 | ])
|
286 | ) {
|
287 | return false;
|
288 | }
|
289 | }
|
290 |
|
291 | if (!bIterator.next().done) {
|
292 | return false;
|
293 | }
|
294 |
|
295 | aStack.pop();
|
296 | bStack.pop();
|
297 | return true;
|
298 | };
|
299 |
|
300 | exports.iterableEquality = iterableEquality;
|
301 |
|
302 | const isObject = a => a !== null && typeof a === 'object';
|
303 |
|
304 | const isObjectWithKeys = a =>
|
305 | isObject(a) &&
|
306 | !(a instanceof Error) &&
|
307 | !(a instanceof Array) &&
|
308 | !(a instanceof Date);
|
309 |
|
310 | const subsetEquality = (object, subset) => {
|
311 |
|
312 |
|
313 |
|
314 | const subsetEqualityWithContext =
|
315 | (seenReferences = new WeakMap()) =>
|
316 | (object, subset) => {
|
317 | if (!isObjectWithKeys(subset)) {
|
318 | return undefined;
|
319 | }
|
320 |
|
321 | return Object.keys(subset).every(key => {
|
322 | if (isObjectWithKeys(subset[key])) {
|
323 | if (seenReferences.has(subset[key])) {
|
324 | return (0, _jasmineUtils.equals)(object[key], subset[key], [
|
325 | iterableEquality
|
326 | ]);
|
327 | }
|
328 |
|
329 | seenReferences.set(subset[key], true);
|
330 | }
|
331 |
|
332 | const result =
|
333 | object != null &&
|
334 | hasPropertyInObject(object, key) &&
|
335 | (0, _jasmineUtils.equals)(object[key], subset[key], [
|
336 | iterableEquality,
|
337 | subsetEqualityWithContext(seenReferences)
|
338 | ]);
|
339 |
|
340 |
|
341 |
|
342 |
|
343 |
|
344 | seenReferences.delete(subset[key]);
|
345 | return result;
|
346 | });
|
347 | };
|
348 |
|
349 | return subsetEqualityWithContext()(object, subset);
|
350 | };
|
351 |
|
352 | exports.subsetEquality = subsetEquality;
|
353 |
|
354 | const typeEquality = (a, b) => {
|
355 | if (a == null || b == null || a.constructor === b.constructor) {
|
356 | return undefined;
|
357 | }
|
358 |
|
359 | return false;
|
360 | };
|
361 |
|
362 | exports.typeEquality = typeEquality;
|
363 |
|
364 | const arrayBufferEquality = (a, b) => {
|
365 | if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer)) {
|
366 | return undefined;
|
367 | }
|
368 |
|
369 | const dataViewA = new DataView(a);
|
370 | const dataViewB = new DataView(b);
|
371 |
|
372 | if (dataViewA.byteLength !== dataViewB.byteLength) {
|
373 | return false;
|
374 | }
|
375 |
|
376 | for (let i = 0; i < dataViewA.byteLength; i++) {
|
377 | if (dataViewA.getUint8(i) !== dataViewB.getUint8(i)) {
|
378 | return false;
|
379 | }
|
380 | }
|
381 |
|
382 | return true;
|
383 | };
|
384 |
|
385 | exports.arrayBufferEquality = arrayBufferEquality;
|
386 |
|
387 | const sparseArrayEquality = (a, b) => {
|
388 | if (!Array.isArray(a) || !Array.isArray(b)) {
|
389 | return undefined;
|
390 | }
|
391 |
|
392 | const aKeys = Object.keys(a);
|
393 | const bKeys = Object.keys(b);
|
394 | return (
|
395 | (0, _jasmineUtils.equals)(a, b, [iterableEquality, typeEquality], true) &&
|
396 | (0, _jasmineUtils.equals)(aKeys, bKeys)
|
397 | );
|
398 | };
|
399 |
|
400 | exports.sparseArrayEquality = sparseArrayEquality;
|
401 |
|
402 | const partition = (items, predicate) => {
|
403 | const result = [[], []];
|
404 | items.forEach(item => result[predicate(item) ? 0 : 1].push(item));
|
405 | return result;
|
406 | };
|
407 |
|
408 | exports.partition = partition;
|
409 |
|
410 | const pathAsArray = propertyPath => {
|
411 |
|
412 | const pattern = RegExp('[^.[\\]]+|(?=(?:\\.)(?:\\.|$))', 'g');
|
413 | const properties = [];
|
414 |
|
415 | if (propertyPath[0] === '.') {
|
416 | properties.push('');
|
417 | }
|
418 |
|
419 | propertyPath.replace(pattern, match => {
|
420 | properties.push(match);
|
421 | return match;
|
422 | });
|
423 | return properties;
|
424 | };
|
425 |
|
426 | exports.pathAsArray = pathAsArray;
|
427 |
|
428 | const isError = value => {
|
429 | switch (Object.prototype.toString.call(value)) {
|
430 | case '[object Error]':
|
431 | case '[object Exception]':
|
432 | case '[object DOMException]':
|
433 | return true;
|
434 |
|
435 | default:
|
436 | return value instanceof Error;
|
437 | }
|
438 | };
|
439 |
|
440 | exports.isError = isError;
|
441 |
|
442 | function emptyObject(obj) {
|
443 | return obj && typeof obj === 'object' ? !Object.keys(obj).length : false;
|
444 | }
|
445 |
|
446 | const MULTILINE_REGEXP = /[\r\n]/;
|
447 |
|
448 | const isOneline = (expected, received) =>
|
449 | typeof expected === 'string' &&
|
450 | typeof received === 'string' &&
|
451 | (!MULTILINE_REGEXP.test(expected) || !MULTILINE_REGEXP.test(received));
|
452 |
|
453 | exports.isOneline = isOneline;
|