Skip to content

Commit c1a5b1a

Browse files
committed
chore(express-partial-content): integrate tests and convert to vitest
1 parent d673682 commit c1a5b1a

File tree

8 files changed

+279
-210
lines changed

8 files changed

+279
-210
lines changed

_regroup_monorepo/express-partial-content/spec/createPartialContentHandler.spec.ts

-182
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import * as utils from "./utils.js";
2+
import * as ParseRangeHeaderExports from "./parseRangeHeader.js";
3+
import { ContentDoesNotExistError } from "./ContentDoesNotExistError.js";
4+
import { createPartialContentHandler } from "./createPartialContentHandler.js";
5+
import type { ContentProvider } from "./ContentProvider.js";
6+
import type { Logger } from "./Logger.js";
7+
import type { Request, Response } from "express";
8+
import type { Content } from "./Content.js";
9+
import { Stream } from "stream";
10+
import type { Range } from "./Range.js";
11+
import type { MockInstance } from "vitest";
12+
13+
describe("createPartialContentHandler tests", () => {
14+
let logger: Logger;
15+
beforeEach(() => {
16+
logger = {
17+
debug: vi.fn() as (message: string, extra?: any) => void
18+
};
19+
});
20+
afterEach(() => {
21+
vi.restoreAllMocks();
22+
});
23+
it("returns a handler", () => {
24+
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
25+
const handler = createPartialContentHandler(contentProvider, logger);
26+
expect(typeof handler === "function");
27+
});
28+
29+
describe("handler tests", () => {
30+
let req: Request;
31+
let res: Response;
32+
let statusSpy: MockInstance;
33+
let sendSpy: MockInstance;
34+
let sendStatusSpy: MockInstance;
35+
beforeEach(() => {
36+
req = {} as Request;
37+
res = {
38+
status: (code: number) => res,
39+
send: (message: string) => res,
40+
sendStatus: (code: number) => res,
41+
setHeader: vi.fn() as (name: string, value: string) => void
42+
} as Response;
43+
statusSpy = vi.spyOn(res, "status");
44+
sendSpy = vi.spyOn(res, "send");
45+
sendStatusSpy = vi.spyOn(res, "sendStatus");
46+
});
47+
it("invokes contentProvider with the specified request", async () => {
48+
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
49+
const handler = createPartialContentHandler(contentProvider, logger);
50+
try {
51+
await handler(req, res);
52+
} catch {}
53+
expect(contentProvider).toHaveBeenCalledExactlyOnceWith(req);
54+
});
55+
it("returns 404 if contentProvider throws ContentDoesNotExistError error", async () => {
56+
const error = new ContentDoesNotExistError("404-File not found!");
57+
const contentProvider = vi.fn().mockRejectedValue(error) as ContentProvider;
58+
const handler = createPartialContentHandler(contentProvider, logger);
59+
try {
60+
await handler(req, res);
61+
expect(statusSpy).toHaveBeenCalledExactlyOnceWith(404);
62+
expect(sendSpy).toHaveBeenCalledExactlyOnceWith(error.message);
63+
} catch {
64+
expect(false);
65+
}
66+
});
67+
it("returns 500 if contentProvider throws any other error", async () => {
68+
const error = new Error("Something went wrong!");
69+
const contentProvider = vi.fn().mockRejectedValue(error) as ContentProvider;
70+
const handler = createPartialContentHandler(contentProvider, logger);
71+
try {
72+
await handler(req, res);
73+
expect(sendStatusSpy).toHaveBeenCalledExactlyOnceWith(500);
74+
} catch {
75+
expect(false);
76+
}
77+
});
78+
it("returns 416 if parseRangeHeader throws RangeParserError error", async () => {
79+
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
80+
const handler = createPartialContentHandler(contentProvider, logger);
81+
req.headers = { range: "bytes=30-10" };
82+
try {
83+
await handler(req, res);
84+
expect(statusSpy).toHaveBeenCalledExactlyOnceWith(416);
85+
} catch {
86+
expect(false);
87+
}
88+
});
89+
it("returns 500 if parseRangeHeader throws other errors", async () => {
90+
const parseRangeHeaderStub = vi
91+
.spyOn(ParseRangeHeaderExports, "parseRangeHeader")
92+
.mockImplementation(() => {
93+
throw new Error("Something went wrong!")
94+
});
95+
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
96+
const handler = createPartialContentHandler(contentProvider, logger);
97+
try {
98+
await handler(req, res);
99+
expect(sendStatusSpy).toHaveBeenCalledExactlyOnceWith(500);
100+
} catch {
101+
expect(false);
102+
}
103+
});
104+
it("returns correct response if range is not specified", async () => {
105+
const result = ({
106+
pipe() {
107+
return result;
108+
}
109+
} as any) as Stream;
110+
const content: Content = {
111+
fileName: "file.txt",
112+
totalSize: 10,
113+
mimeType: "text/plain",
114+
getStream(range?: Range) {
115+
return result;
116+
}
117+
};
118+
const pipeSpy = vi.spyOn(result, "pipe");
119+
const getStreamSpy = vi.spyOn(content, "getStream");
120+
const contentProvider = vi.fn().mockResolvedValue(content) as ContentProvider;
121+
const handler = createPartialContentHandler(contentProvider, logger);
122+
const setContentTypeHeaderSpy = vi.spyOn(utils, "setContentTypeHeader");
123+
const setContentDispositionHeaderSpy = vi.spyOn(utils, "setContentDispositionHeader");
124+
const setAcceptRangesHeaderSpy = vi.spyOn(utils, "setAcceptRangesHeader");
125+
const setContentLengthHeaderSpy = vi.spyOn(utils, "setContentLengthHeader");
126+
const setContentRangeHeaderSpy = vi.spyOn(utils, "setContentRangeHeader");
127+
try {
128+
await handler(req, res);
129+
expect(setContentTypeHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.mimeType, res);
130+
expect(setContentDispositionHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.fileName, res);
131+
expect(setAcceptRangesHeaderSpy).toHaveBeenCalledExactlyOnceWith(res);
132+
expect(setContentLengthHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.totalSize, res);
133+
expect(getStreamSpy).toHaveBeenCalledExactlyOnceWith();
134+
expect(pipeSpy).toHaveBeenCalledExactlyOnceWith(res);
135+
expect(setContentRangeHeaderSpy).not.toHaveBeenCalled();
136+
} catch {
137+
expect(false);
138+
}
139+
});
140+
it("returns correct partial response if range is specified", async () => {
141+
req.headers = {
142+
range: "bytes=0-5"
143+
};
144+
const result = ({
145+
pipe() {
146+
return result;
147+
}
148+
} as any) as Stream;
149+
const content: Content = {
150+
fileName: "file.txt",
151+
totalSize: 10,
152+
mimeType: "text/plain",
153+
getStream(range?: Range) {
154+
return result;
155+
}
156+
};
157+
const range = { start: 0, end: 5 };
158+
const pipeSpy = vi.spyOn(result, "pipe");
159+
const getStreamSpy = vi.spyOn(content, "getStream");
160+
const contentProvider = vi.fn().mockResolvedValue(content) as ContentProvider;
161+
const handler = createPartialContentHandler(contentProvider, logger);
162+
const setContentTypeHeaderSpy = vi.spyOn(utils, "setContentTypeHeader");
163+
const setContentDispositionHeaderSpy = vi.spyOn(utils, "setContentDispositionHeader");
164+
const setAcceptRangesHeaderSpy = vi.spyOn(utils, "setAcceptRangesHeader");
165+
const setContentLengthHeaderSpy = vi.spyOn(utils, "setContentLengthHeader");
166+
const setContentRangeHeaderSpy = vi.spyOn(utils, "setContentRangeHeader");
167+
try {
168+
await handler(req, res);
169+
expect(setContentTypeHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.mimeType, res);
170+
expect(setContentDispositionHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.fileName, res);
171+
expect(setAcceptRangesHeaderSpy).toHaveBeenCalledExactlyOnceWith(res);
172+
expect(setContentRangeHeaderSpy).toHaveBeenCalledExactlyOnceWith(range, content.totalSize, res);
173+
expect(setContentLengthHeaderSpy).toHaveBeenCalledExactlyOnceWith(6, res);
174+
expect(getStreamSpy).toHaveBeenCalledExactlyOnceWith(range);
175+
expect(pipeSpy).toHaveBeenCalledExactlyOnceWith(res);
176+
} catch {
177+
expect(false);
178+
}
179+
});
180+
});
181+
});

_regroup_monorepo/express-partial-content/spec/parseRangeHeader.spec.ts renamed to packages/express-partial-content/src/parseRangeHeader.spec.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
1-
import { parseRangeHeader } from "../src/parseRangeHeader";
2-
import { SinonSandbox, createSandbox } from "sinon";
3-
import { Logger } from "../src/Logger";
4-
import { expect } from "chai";
5-
import { RangeParserError } from "../src/RangeParserError";
1+
import { parseRangeHeader } from "./parseRangeHeader.js";
2+
import type { Logger } from "./Logger.js";
3+
import { RangeParserError } from "./RangeParserError.js";
64

75
describe("parseRangeHeader tests", () => {
8-
let sandbox: SinonSandbox;
96
let logger: Logger;
107
beforeEach(() => {
11-
sandbox = createSandbox();
128
logger = {
13-
debug: sandbox.stub() as (message: string, extra?: any) => void
9+
debug: vi.fn() as (message: string, extra?: any) => void
1410
};
1511
});
1612
afterEach(() => {
17-
sandbox.restore();
13+
vi.restoreAllMocks();
1814
});
1915
it("returns null if range is not specified", () => {
2016
let value = parseRangeHeader("", 10, logger);

0 commit comments

Comments
 (0)