Mock Date in integration tests

This commit is contained in:
Henry Mercer
2020-01-13 14:16:16 +00:00
parent b43045adbf
commit 886fe35219
2 changed files with 37 additions and 9 deletions

View File

@@ -140,7 +140,12 @@ export function getQueryName(info: EvaluationInfo) {
* the last invocation of that function.
*/
export class InvocationRateLimiter<T> {
constructor(extensionContext: ExtensionContext, funcIdentifier: string, func: () => Promise<T>) {
constructor(
extensionContext: ExtensionContext,
funcIdentifier: string,
func: () => Promise<T>,
createDate: (dateString?: string) => Date = s => s ? new Date(s) : new Date()) {
this._createDate = createDate;
this._extensionContext = extensionContext;
this._func = func;
this._funcIdentifier = funcIdentifier;
@@ -150,7 +155,7 @@ export class InvocationRateLimiter<T> {
* Invoke the function if `minSecondsSinceLastInvocation` seconds have elapsed since the last invocation.
*/
public async invokeFunctionIfIntervalElapsed(minSecondsSinceLastInvocation: number): Promise<InvocationRateLimiterResult<T>> {
const updateCheckStartDate = new Date();
const updateCheckStartDate = this._createDate();
const lastInvocationDate = this.getLastInvocationDate();
if (minSecondsSinceLastInvocation && lastInvocationDate && lastInvocationDate <= updateCheckStartDate &&
lastInvocationDate.getTime() + minSecondsSinceLastInvocation * 1000 > updateCheckStartDate.getTime()) {
@@ -162,15 +167,16 @@ export class InvocationRateLimiter<T> {
}
private getLastInvocationDate(): Date | undefined {
const maybeDate: Date | undefined =
const maybeDateString: string | undefined =
this._extensionContext.globalState.get(InvocationRateLimiter._invocationRateLimiterPrefix + this._funcIdentifier);
return maybeDate ? new Date(maybeDate) : undefined;
return maybeDateString ? this._createDate(maybeDateString) : undefined;
}
private async setLastInvocationDate(date: Date): Promise<void> {
return await this._extensionContext.globalState.update(InvocationRateLimiter._invocationRateLimiterPrefix + this._funcIdentifier, date);
}
private readonly _createDate: (dateString?: string) => Date;
private readonly _extensionContext: ExtensionContext;
private readonly _func: () => Promise<T>;
private readonly _funcIdentifier: string;

View File

@@ -4,8 +4,19 @@ import { ExtensionContext, Memento } from "vscode";
import { InvocationRateLimiter } from "../../helpers";
describe("Invocation rate limiter", () => {
// 1 January 2020
let currentUnixTime = 1577836800;
function createDate(dateString?: string): Date {
if (dateString) {
return new Date(dateString);
}
const numMillisecondsPerSecond = 1000;
return new Date(currentUnixTime * numMillisecondsPerSecond);
}
function createInvocationRateLimiter<T>(funcIdentifier: string, func: () => Promise<T>): InvocationRateLimiter<T> {
return new InvocationRateLimiter(new MockExtensionContext(), funcIdentifier, func);
return new InvocationRateLimiter(new MockExtensionContext(), funcIdentifier, func, s => createDate(s));
}
it("initially invokes function", async () => {
@@ -17,7 +28,7 @@ describe("Invocation rate limiter", () => {
expect(numTimesFuncCalled).to.equal(1);
});
it("doesn't invoke function within time period", async () => {
it("doesn't invoke function again if no time has passed", async () => {
let numTimesFuncCalled = 0;
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
numTimesFuncCalled++;
@@ -27,7 +38,18 @@ describe("Invocation rate limiter", () => {
expect(numTimesFuncCalled).to.equal(1);
});
it("invoke function again after 0s time period has elapsed", async () => {
it("doesn't invoke function again if requested time since last invocation hasn't passed", async () => {
let numTimesFuncCalled = 0;
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
numTimesFuncCalled++;
});
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(100);
currentUnixTime += 1;
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(2);
expect(numTimesFuncCalled).to.equal(1);
});
it("invokes function again immediately if requested time since last invocation is 0 seconds", async () => {
let numTimesFuncCalled = 0;
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
numTimesFuncCalled++;
@@ -37,13 +59,13 @@ describe("Invocation rate limiter", () => {
expect(numTimesFuncCalled).to.equal(2);
});
it("invoke function again after 1s time period has elapsed", async () => {
it("invokes function again after requested time since last invocation has elapsed", async () => {
let numTimesFuncCalled = 0;
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
numTimesFuncCalled++;
});
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(1);
await new Promise((resolve, _reject) => setTimeout(() => resolve(), 1000));
currentUnixTime += 1;
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(1);
expect(numTimesFuncCalled).to.equal(2);
});