122 lines
5.0 KiB
TypeScript
122 lines
5.0 KiB
TypeScript
import { HttpResponse } from "../src/HttpClient";
|
|
import { LogLevel } from "../src/ILogger";
|
|
import { TransferFormat } from "../src/ITransport";
|
|
import { NullLogger } from "../src/Loggers";
|
|
import { LongPollingTransport } from "../src/LongPollingTransport";
|
|
import { ConsoleLogger } from "../src/Utils";
|
|
|
|
import { TestHttpClient } from "./TestHttpClient";
|
|
import { asyncit as it, PromiseSource, delay } from "./Utils";
|
|
import { HttpError, TimeoutError } from "../src/Errors";
|
|
import { AbortSignal } from "../src/AbortController";
|
|
|
|
describe("LongPollingTransport", () => {
|
|
it("shuts down poll after timeout even if server doesn't shut it down on receiving the DELETE", async () => {
|
|
let firstPoll = true;
|
|
const pollCompleted = new PromiseSource();
|
|
const client = new TestHttpClient()
|
|
.on("GET", async (r) => {
|
|
if (firstPoll) {
|
|
firstPoll = false;
|
|
return new HttpResponse(200);
|
|
} else {
|
|
// Turn 'onabort' into a promise.
|
|
const abort = new Promise((resolve, reject) => r.abortSignal.onabort = resolve);
|
|
await abort;
|
|
|
|
// Signal that the poll has completed.
|
|
pollCompleted.resolve();
|
|
return new HttpResponse(204);
|
|
}
|
|
})
|
|
.on("DELETE", (r) => new HttpResponse(202));
|
|
const transport = new LongPollingTransport(client, null, NullLogger.instance, false, 100);
|
|
|
|
await transport.connect("http://example.com", TransferFormat.Text);
|
|
await transport.stop();
|
|
|
|
// This should complete within the shutdown timeout
|
|
await pollCompleted.promise;
|
|
});
|
|
|
|
it("sends DELETE request on stop", async () => {
|
|
let firstPoll = true;
|
|
const deleteReceived = new PromiseSource();
|
|
const pollCompleted = new PromiseSource();
|
|
const client = new TestHttpClient()
|
|
.on("GET", async (r) => {
|
|
if (firstPoll) {
|
|
firstPoll = false;
|
|
return new HttpResponse(200);
|
|
} else {
|
|
await deleteReceived.promise;
|
|
// Force the shutdown timer to be registered by not returning inline
|
|
await delay(10);
|
|
pollCompleted.resolve();
|
|
return new HttpResponse(204);
|
|
}
|
|
})
|
|
.on("DELETE", (r) => {
|
|
deleteReceived.resolve();
|
|
return new HttpResponse(202);
|
|
});
|
|
const transport = new LongPollingTransport(client, null, NullLogger.instance, false, 100);
|
|
|
|
await transport.connect("http://example.com", TransferFormat.Text);
|
|
await transport.stop();
|
|
|
|
// This should complete, because the DELETE request triggers it to stop.
|
|
await pollCompleted.promise;
|
|
});
|
|
|
|
for (const result of [200, 204, 300, new HttpError("Boom", 500), new TimeoutError()]) {
|
|
const resultName = typeof result === "number" ? result.toString() : result.constructor.name;
|
|
it(`does not fire shutdown timer when poll terminates with ${resultName}`, async () => {
|
|
let firstPoll = true;
|
|
const deleteReceived = new PromiseSource();
|
|
const pollCompleted = new PromiseSource();
|
|
const client = new TestHttpClient()
|
|
.on("GET", async (r) => {
|
|
if (firstPoll) {
|
|
firstPoll = false;
|
|
return new HttpResponse(200);
|
|
} else {
|
|
await deleteReceived.promise;
|
|
// Force the shutdown timer to be registered by not returning inline
|
|
await delay(10);
|
|
pollCompleted.resolve();
|
|
|
|
if (typeof result === "number") {
|
|
return new HttpResponse(result);
|
|
} else {
|
|
throw result;
|
|
}
|
|
}
|
|
})
|
|
.on("DELETE", (r) => {
|
|
deleteReceived.resolve();
|
|
return new HttpResponse(202);
|
|
});
|
|
const logMessages: string[] = [];
|
|
const transport = new LongPollingTransport(client, null, {
|
|
log(level: LogLevel, message: string) {
|
|
logMessages.push(message);
|
|
},
|
|
}, false, 100);
|
|
|
|
await transport.connect("http://example.com", TransferFormat.Text);
|
|
await transport.stop();
|
|
|
|
// This should complete, because the DELETE request triggers it to stop.
|
|
await pollCompleted.promise;
|
|
|
|
// Wait for the shutdown timeout to elapse
|
|
// This can be much cleaner when we port to Jest because it has a built-in set of
|
|
// fake timers!
|
|
await delay(150);
|
|
|
|
// The pollAbort token should be left unaborted because we shut down gracefully.
|
|
expect(transport.pollAborted).toBe(false);
|
|
});
|
|
}
|
|
}); |