Skip to content

Commit 402145b

Browse files
committed
fix: nested documents must have exact keys
Adds a check that asserts when at a recursion depth greater than 1 that documents do not have extra keys
1 parent 62e48d4 commit 402145b

File tree

1 file changed

+28
-14
lines changed
  • test/functional/unified-spec-runner

1 file changed

+28
-14
lines changed

test/functional/unified-spec-runner/match.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -168,63 +168,77 @@ export function expectResultCheck(
168168
actual: Document,
169169
expected: Document | number | string | boolean,
170170
entities: EntitiesMap,
171-
path: string[] = []
171+
path: string[] = [],
172+
depth = 0
172173
): boolean {
173-
const result = resultCheck(actual, expected, entities, path);
174-
if (result[0] === false) {
175-
const path = result[1].join('');
174+
const ok = resultCheck(actual, expected, entities, path, depth);
175+
if (ok === false) {
176+
const pathString = path.join('');
176177
const expectedJSON = JSON.stringify(expected, undefined, 2);
177178
const actualJSON = JSON.stringify(actual, undefined, 2);
178-
expect.fail(`Unable to match ${expectedJSON} to ${actualJSON} at ${path}`);
179+
expect.fail(`Unable to match ${expectedJSON} to ${actualJSON} at ${pathString}`);
179180
}
180-
return result[0];
181+
return ok;
181182
}
182183

183184
export function resultCheck(
184185
actual: Document,
185186
expected: Document | number | string | boolean,
186187
entities: EntitiesMap,
187-
path: string[]
188-
): [ok: boolean, path: string[]] {
188+
path: string[],
189+
depth = 0
190+
): boolean {
189191
if (typeof expected === 'object' && expected !== null) {
190192
// Expected is an object
191193
// either its a special operator or just an object to check equality against
192194

193195
if (isSpecialOperator(expected)) {
194196
// Special operation check is a base condition
195197
// specialCheck may recurse depending upon the check ($$unsetOrMatches)
196-
return [specialCheck(actual, expected, entities, path), path];
198+
return specialCheck(actual, expected, entities, path, depth);
197199
} else {
198200
// Just a plain object, however this object can contain special operations
199201
// So we need to recurse over each key,value
200202
let ok = true;
201203
const expectedEntries = Object.entries(expected);
204+
205+
if (depth > 1 && Object.keys(actual).length !== Object.keys(expected).length) {
206+
throw new Error(`[${Object.keys(actual)}] length !== [${Object.keys(expected)}]`);
207+
}
208+
202209
for (const [key, value] of expectedEntries) {
203210
path.push(Array.isArray(expected) ? `[${key}]` : `.${key}`); // record what key we're at
204-
ok &&= expectResultCheck(actual[key], value, entities, path);
211+
depth += 1;
212+
ok &&= expectResultCheck(actual[key], value, entities, path, depth);
213+
depth -= 1;
205214
path.pop(); // if the recursion was successful we can drop the tested key
206215
}
207-
return [ok, path];
216+
return ok;
208217
}
209218
} else {
210219
// Here's our recursion base case
211220
// expected is: number | string | boolean | null
212-
return [isDeepStrictEqual(actual, expected), path];
221+
return isDeepStrictEqual(actual, expected);
213222
}
214223
}
215224

216225
export function specialCheck(
217226
actual: Document,
218227
expected: SpecialOperator,
219228
entities: EntitiesMap,
220-
path: string[] = []
229+
path: string[] = [],
230+
depth = 0
221231
): boolean {
222232
let ok = false;
223233
if (isUnsetOrMatchesOperator(expected)) {
224234
// $$unsetOrMatches
225235
ok = true; // start with true assumption
226236
if (actual === null || actual === undefined) ok = true;
227-
else ok &&= expectResultCheck(actual, expected.$$unsetOrMatches, entities, path);
237+
else {
238+
depth += 1;
239+
ok &&= expectResultCheck(actual, expected.$$unsetOrMatches, entities, path, depth);
240+
depth -= 1;
241+
}
228242
} else if (isMatchesEntityOperator(expected)) {
229243
// $$matchesEntity
230244
const entity = entities.get(expected.$$matchesEntity);

0 commit comments

Comments
 (0)