forked from slackapi/bolt-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest-helpers.ts
96 lines (85 loc) · 3.16 KB
/
test-helpers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// tslint:disable:no-implicit-dependencies
import sinon, { SinonSpy } from 'sinon';
import { Logger } from '@slack/logger';
export interface Override {
[packageName: string]: {
[exportName: string]: any;
};
}
export function mergeOverrides(...overrides: Override[]): Override {
let currentOverrides: Override = {};
for (const override of overrides) {
currentOverrides = mergeObjProperties(currentOverrides, override);
}
return currentOverrides;
}
function mergeObjProperties(first: Override, second: Override): Override {
const merged: Override = {};
const props = Object.keys(first).concat(Object.keys(second));
for (const prop of props) {
if (second[prop] === undefined && first[prop] !== undefined) {
merged[prop] = first[prop];
} else if (first[prop] === undefined && second[prop] !== undefined) {
merged[prop] = second[prop];
} else {
// second always overwrites the first
merged[prop] = { ...first[prop], ...second[prop] };
}
}
return merged;
}
export interface FakeLogger extends Logger {
setLevel: SinonSpy<Parameters<Logger['setLevel']>, ReturnType<Logger['setLevel']>>;
setName: SinonSpy<Parameters<Logger['setName']>, ReturnType<Logger['setName']>>;
debug: SinonSpy<Parameters<Logger['debug']>, ReturnType<Logger['debug']>>;
info: SinonSpy<Parameters<Logger['info']>, ReturnType<Logger['info']>>;
warn: SinonSpy<Parameters<Logger['warn']>, ReturnType<Logger['warn']>>;
error: SinonSpy<Parameters<Logger['error']>, ReturnType<Logger['error']>>;
}
export function createFakeLogger(): FakeLogger {
return {
// NOTE: the two casts are because of a TypeScript inconsistency with tuple types and any[]. all tuple types
// should be assignable to any[], but TypeScript doesn't think so.
setLevel: sinon.fake() as SinonSpy<Parameters<Logger['setLevel']>, ReturnType<Logger['setLevel']>>,
setName: sinon.fake() as SinonSpy<Parameters<Logger['setName']>, ReturnType<Logger['setName']>>,
debug: sinon.fake(),
info: sinon.fake(),
warn: sinon.fake(),
error: sinon.fake(),
};
}
export function delay(ms: number = 0): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
export function wrapToResolveOnFirstCall<T extends (...args: any[]) => void>(
original: T,
timeoutMs: number = 1000,
): { fn: (...args: Parameters<T>) => Promise<void>; promise: Promise<void>; } {
// tslint:disable-next-line:no-empty
let firstCallResolve: (value?: void | PromiseLike<void>) => void = () => { };
let firstCallReject: (reason?: any) => void = () => { }; // tslint:disable-line:no-empty
const firstCallPromise: Promise<void> = new Promise((resolve, reject) => {
firstCallResolve = resolve;
firstCallReject = reject;
});
const wrapped = async function (this: ThisParameterType<T>, ...args: Parameters<T>): Promise<void> {
try {
await original.call(this, ...args);
firstCallResolve();
} catch (error) {
firstCallReject(error);
}
};
setTimeout(
() => {
firstCallReject(new Error('First call to function took longer than expected'));
},
timeoutMs,
);
return {
promise: firstCallPromise,
fn: wrapped,
};
}