|
1 | 1 | import { EJSON } from 'bson';
|
2 | 2 | import { expect } from 'chai';
|
3 |
| -import util from 'util'; |
| 3 | +import { inspect } from 'util'; |
4 | 4 |
|
5 | 5 | import { Logger } from '../../src/logger';
|
6 |
| -import { deprecateOptions, DeprecateOptionsConfig } from '../../src/utils'; |
| 6 | +import { deprecateOptions, DeprecateOptionsConfig, setDifference } from '../../src/utils'; |
7 | 7 |
|
8 | 8 | export function makeTestFunction(config: DeprecateOptionsConfig) {
|
9 | 9 | const fn = (options: any) => {
|
@@ -189,15 +189,15 @@ export function shouldRunServerlessTest(testRequirement: any, isServerless: any)
|
189 | 189 | * Attempts to use EJSON (to make type information obvious)
|
190 | 190 | * falls back to util.inspect if there's an error (circular reference)
|
191 | 191 | */
|
192 |
| -export function ejson(strings: any[], ...values: any[]) { |
| 192 | +export function ejson(strings: TemplateStringsArray, ...values: any[]) { |
193 | 193 | const stringParts = [strings[0]];
|
194 | 194 | for (const [idx, value] of values.entries()) {
|
195 | 195 | if (typeof value === 'object') {
|
196 | 196 | let stringifiedObject: string;
|
197 | 197 | try {
|
198 | 198 | stringifiedObject = EJSON.stringify(value, { relaxed: false });
|
199 | 199 | } catch (error) {
|
200 |
| - stringifiedObject = util.inspect(value, { |
| 200 | + stringifiedObject = inspect(value, { |
201 | 201 | depth: Infinity,
|
202 | 202 | showHidden: true,
|
203 | 203 | compact: true
|
@@ -270,6 +270,31 @@ export function extractAuthFromConnectionString(connectionString: string | any[]
|
270 | 270 | return connectionString.slice(indices.start, indices.end);
|
271 | 271 | }
|
272 | 272 |
|
| 273 | +/** |
| 274 | + * Ensures no extra keys are provided on an object |
| 275 | + * @param knownKeys - the super set of keys allowed to exist on objectWithKeys |
| 276 | + * @param objectWithKeys - An object (usually from JSON) that has an unknown amount of keys |
| 277 | + * |
| 278 | + * Users should combine the usage of this helper with an interface |
| 279 | + * ```ts |
| 280 | + * interface Pet { name: string } |
| 281 | + * const maybePet: any = { name: 'spot', age: number }; |
| 282 | + * assertSubsetOfKeys<Pet>(['name'], maybePet); // throws! |
| 283 | + * assertSubsetOfKeys<Pet>(['name', 'age'], maybePet); // compiler error! (age not defined) |
| 284 | + * assertSubsetOfKeys<Pet>([], maybePet); // compiler error! (missing keys) |
| 285 | + * ``` |
| 286 | + */ |
| 287 | +export function assertNoExtraKeys<T extends { [k: string]: any }>( |
| 288 | + knownKeys: Array<keyof Required<T>>, |
| 289 | + objectWithKeys: Partial<T> |
| 290 | +): asserts objectWithKeys is { [P in keyof T]-?: T[P] } { |
| 291 | + expect(knownKeys).to.have.lengthOf(knownKeys.length); |
| 292 | + const subsetKeys = Object.keys(objectWithKeys); |
| 293 | + const difference = Array.from(setDifference(subsetKeys, knownKeys)); |
| 294 | + const message = `Expected no extra keys. Found: [${difference.join(', ')}]`; |
| 295 | + expect(difference, message).to.be.empty; |
| 296 | +} |
| 297 | + |
273 | 298 | export interface FailPoint {
|
274 | 299 | configureFailPoint: 'failCommand';
|
275 | 300 | mode: { activationProbability: number } | { times: number } | 'alwaysOn' | 'off';
|
|
0 commit comments