mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 10:02:59 +08:00
chore(express-partial-content): integrate tests and convert to vitest
This commit is contained in:
parent
d6736821b6
commit
c1a5b1a0aa
@ -1,182 +0,0 @@
|
|||||||
import * as utils from "../src/utils";
|
|
||||||
import * as ParseRangeHeaderExports from "../src/parseRangeHeader";
|
|
||||||
import { ContentDoesNotExistError } from "../src/ContentDoesNotExistError";
|
|
||||||
import { SinonSandbox, createSandbox, SinonStub, SinonSpy } from "sinon";
|
|
||||||
import { createPartialContentHandler } from "../src/createPartialContentHandler";
|
|
||||||
import { ContentProvider } from "../src/ContentProvider";
|
|
||||||
import { Logger } from "../src/Logger";
|
|
||||||
import { expect } from "chai";
|
|
||||||
import { Request, Response } from "express";
|
|
||||||
import { Content } from "../src/Content";
|
|
||||||
import { Stream } from "stream";
|
|
||||||
import { Range } from "../src/Range";
|
|
||||||
|
|
||||||
describe("createPartialContentHandler tests", () => {
|
|
||||||
let sandbox: SinonSandbox;
|
|
||||||
let logger: Logger;
|
|
||||||
beforeEach(() => {
|
|
||||||
sandbox = createSandbox();
|
|
||||||
logger = {
|
|
||||||
debug: sandbox.stub() as (message: string, extra?: any) => void
|
|
||||||
};
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
sandbox.restore();
|
|
||||||
});
|
|
||||||
it("returns a handler", () => {
|
|
||||||
const contentProvider = sandbox.stub().resolves({}) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
expect(typeof handler === "function");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("handler tests", () => {
|
|
||||||
let req: Request;
|
|
||||||
let res: Response;
|
|
||||||
let statusSpy: SinonSpy;
|
|
||||||
let sendSpy: SinonSpy;
|
|
||||||
let sendStatusSpy: SinonSpy;
|
|
||||||
beforeEach(() => {
|
|
||||||
req = {} as Request;
|
|
||||||
res = {
|
|
||||||
status: (code: number) => res,
|
|
||||||
send: (message: string) => res,
|
|
||||||
sendStatus: (code: number) => res,
|
|
||||||
setHeader: sandbox.stub() as (name: string, value: string) => void
|
|
||||||
} as Response;
|
|
||||||
statusSpy = sandbox.spy(res, "status");
|
|
||||||
sendSpy = sandbox.spy(res, "send");
|
|
||||||
sendStatusSpy = sandbox.spy(res, "sendStatus");
|
|
||||||
});
|
|
||||||
it("invokes contentProvider with the specified request", async () => {
|
|
||||||
const contentProvider = sandbox.stub().resolves({}) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
try {
|
|
||||||
await handler(req, res);
|
|
||||||
} catch {}
|
|
||||||
expect((contentProvider as SinonStub).calledOnceWith(req));
|
|
||||||
});
|
|
||||||
it("returns 404 if contentProvider throws ContentDoesNotExistError error", async () => {
|
|
||||||
const error = new ContentDoesNotExistError("404-File not found!");
|
|
||||||
const contentProvider = sandbox.stub().rejects(error) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
try {
|
|
||||||
await handler(req, res);
|
|
||||||
expect(statusSpy.calledOnceWith(404));
|
|
||||||
expect(sendSpy.calledOnceWith(error.message));
|
|
||||||
} catch {
|
|
||||||
expect(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
it("returns 500 if contentProvider throws any other error", async () => {
|
|
||||||
const error = new Error("Something went wrong!");
|
|
||||||
const contentProvider = sandbox.stub().rejects(error) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
try {
|
|
||||||
await handler(req, res);
|
|
||||||
expect(sendStatusSpy.calledOnceWith(500));
|
|
||||||
} catch {
|
|
||||||
expect(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
it("returns 416 if parseRangeHeader throws RangeParserError error", async () => {
|
|
||||||
const contentProvider = sandbox.stub().resolves({}) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
req.headers = { range: "bytes=30-10" };
|
|
||||||
try {
|
|
||||||
await handler(req, res);
|
|
||||||
expect(statusSpy.calledOnceWith(416));
|
|
||||||
} catch {
|
|
||||||
expect(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
it("returns 500 if parseRangeHeader throws other errors", async () => {
|
|
||||||
const parseRangeHeaderStub = sandbox
|
|
||||||
.stub(ParseRangeHeaderExports, "parseRangeHeader")
|
|
||||||
.throws(new Error("Something went wrong!"));
|
|
||||||
const contentProvider = sandbox.stub().resolves({}) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
try {
|
|
||||||
await handler(req, res);
|
|
||||||
expect(sendStatusSpy.calledOnceWith(500));
|
|
||||||
} catch {
|
|
||||||
expect(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
it("returns correct response if range is not specified", async () => {
|
|
||||||
const result = ({
|
|
||||||
pipe() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} as any) as Stream;
|
|
||||||
const content: Content = {
|
|
||||||
fileName: "file.txt",
|
|
||||||
totalSize: 10,
|
|
||||||
mimeType: "text/plain",
|
|
||||||
getStream(range?: Range) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const pipeSpy = sandbox.spy(result, "pipe");
|
|
||||||
const getStreamSpy = sandbox.spy(content, "getStream");
|
|
||||||
const contentProvider = sandbox.stub().resolves(content) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
const setContentTypeHeaderSpy = sandbox.spy(utils, "setContentTypeHeader");
|
|
||||||
const setContentDispositionHeaderSpy = sandbox.spy(utils, "setContentDispositionHeader");
|
|
||||||
const setAcceptRangesHeaderSpy = sandbox.spy(utils, "setAcceptRangesHeader");
|
|
||||||
const setContentLengthHeaderSpy = sandbox.spy(utils, "setContentLengthHeader");
|
|
||||||
const setContentRangeHeaderSpy = sandbox.spy(utils, "setContentRangeHeader");
|
|
||||||
try {
|
|
||||||
await handler(req, res);
|
|
||||||
expect(setContentTypeHeaderSpy.calledOnceWith(content.mimeType, res));
|
|
||||||
expect(setContentDispositionHeaderSpy.calledOnceWith(content.fileName, res));
|
|
||||||
expect(setAcceptRangesHeaderSpy.calledOnceWith(res));
|
|
||||||
expect(setContentLengthHeaderSpy.calledOnceWith(content.totalSize, res));
|
|
||||||
expect(getStreamSpy.calledOnceWith());
|
|
||||||
expect(pipeSpy.calledOnceWith(res));
|
|
||||||
expect(setContentRangeHeaderSpy.notCalled);
|
|
||||||
} catch {
|
|
||||||
expect(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
it("returns correct partial response if range is specified", async () => {
|
|
||||||
req.headers = {
|
|
||||||
range: "bytes=0-5"
|
|
||||||
};
|
|
||||||
const result = ({
|
|
||||||
pipe() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} as any) as Stream;
|
|
||||||
const content: Content = {
|
|
||||||
fileName: "file.txt",
|
|
||||||
totalSize: 10,
|
|
||||||
mimeType: "text/plain",
|
|
||||||
getStream(range?: Range) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const range = { start: 0, end: 5 };
|
|
||||||
const pipeSpy = sandbox.spy(result, "pipe");
|
|
||||||
const getStreamSpy = sandbox.spy(content, "getStream");
|
|
||||||
const contentProvider = sandbox.stub().resolves(content) as ContentProvider;
|
|
||||||
const handler = createPartialContentHandler(contentProvider, logger);
|
|
||||||
const setContentTypeHeaderSpy = sandbox.spy(utils, "setContentTypeHeader");
|
|
||||||
const setContentDispositionHeaderSpy = sandbox.spy(utils, "setContentDispositionHeader");
|
|
||||||
const setAcceptRangesHeaderSpy = sandbox.spy(utils, "setAcceptRangesHeader");
|
|
||||||
const setContentLengthHeaderSpy = sandbox.spy(utils, "setContentLengthHeader");
|
|
||||||
const setContentRangeHeaderSpy = sandbox.spy(utils, "setContentRangeHeader");
|
|
||||||
try {
|
|
||||||
await handler(req, res);
|
|
||||||
expect(setContentTypeHeaderSpy.calledOnceWith(content.mimeType, res));
|
|
||||||
expect(setContentDispositionHeaderSpy.calledOnceWith(content.fileName, res));
|
|
||||||
expect(setAcceptRangesHeaderSpy.calledOnceWith(res));
|
|
||||||
expect(setContentRangeHeaderSpy.calledOnceWith(range, content.totalSize, res));
|
|
||||||
expect(setContentLengthHeaderSpy.calledOnceWith(6, res));
|
|
||||||
expect(getStreamSpy.calledOnceWith(range));
|
|
||||||
expect(pipeSpy.calledOnceWith(res));
|
|
||||||
} catch {
|
|
||||||
expect(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,181 @@
|
|||||||
|
import * as utils from "./utils.js";
|
||||||
|
import * as ParseRangeHeaderExports from "./parseRangeHeader.js";
|
||||||
|
import { ContentDoesNotExistError } from "./ContentDoesNotExistError.js";
|
||||||
|
import { createPartialContentHandler } from "./createPartialContentHandler.js";
|
||||||
|
import type { ContentProvider } from "./ContentProvider.js";
|
||||||
|
import type { Logger } from "./Logger.js";
|
||||||
|
import type { Request, Response } from "express";
|
||||||
|
import type { Content } from "./Content.js";
|
||||||
|
import { Stream } from "stream";
|
||||||
|
import type { Range } from "./Range.js";
|
||||||
|
import type { MockInstance } from "vitest";
|
||||||
|
|
||||||
|
describe("createPartialContentHandler tests", () => {
|
||||||
|
let logger: Logger;
|
||||||
|
beforeEach(() => {
|
||||||
|
logger = {
|
||||||
|
debug: vi.fn() as (message: string, extra?: any) => void
|
||||||
|
};
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
it("returns a handler", () => {
|
||||||
|
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
expect(typeof handler === "function");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("handler tests", () => {
|
||||||
|
let req: Request;
|
||||||
|
let res: Response;
|
||||||
|
let statusSpy: MockInstance;
|
||||||
|
let sendSpy: MockInstance;
|
||||||
|
let sendStatusSpy: MockInstance;
|
||||||
|
beforeEach(() => {
|
||||||
|
req = {} as Request;
|
||||||
|
res = {
|
||||||
|
status: (code: number) => res,
|
||||||
|
send: (message: string) => res,
|
||||||
|
sendStatus: (code: number) => res,
|
||||||
|
setHeader: vi.fn() as (name: string, value: string) => void
|
||||||
|
} as Response;
|
||||||
|
statusSpy = vi.spyOn(res, "status");
|
||||||
|
sendSpy = vi.spyOn(res, "send");
|
||||||
|
sendStatusSpy = vi.spyOn(res, "sendStatus");
|
||||||
|
});
|
||||||
|
it("invokes contentProvider with the specified request", async () => {
|
||||||
|
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
try {
|
||||||
|
await handler(req, res);
|
||||||
|
} catch {}
|
||||||
|
expect(contentProvider).toHaveBeenCalledExactlyOnceWith(req);
|
||||||
|
});
|
||||||
|
it("returns 404 if contentProvider throws ContentDoesNotExistError error", async () => {
|
||||||
|
const error = new ContentDoesNotExistError("404-File not found!");
|
||||||
|
const contentProvider = vi.fn().mockRejectedValue(error) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
try {
|
||||||
|
await handler(req, res);
|
||||||
|
expect(statusSpy).toHaveBeenCalledExactlyOnceWith(404);
|
||||||
|
expect(sendSpy).toHaveBeenCalledExactlyOnceWith(error.message);
|
||||||
|
} catch {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it("returns 500 if contentProvider throws any other error", async () => {
|
||||||
|
const error = new Error("Something went wrong!");
|
||||||
|
const contentProvider = vi.fn().mockRejectedValue(error) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
try {
|
||||||
|
await handler(req, res);
|
||||||
|
expect(sendStatusSpy).toHaveBeenCalledExactlyOnceWith(500);
|
||||||
|
} catch {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it("returns 416 if parseRangeHeader throws RangeParserError error", async () => {
|
||||||
|
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
req.headers = { range: "bytes=30-10" };
|
||||||
|
try {
|
||||||
|
await handler(req, res);
|
||||||
|
expect(statusSpy).toHaveBeenCalledExactlyOnceWith(416);
|
||||||
|
} catch {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it("returns 500 if parseRangeHeader throws other errors", async () => {
|
||||||
|
const parseRangeHeaderStub = vi
|
||||||
|
.spyOn(ParseRangeHeaderExports, "parseRangeHeader")
|
||||||
|
.mockImplementation(() => {
|
||||||
|
throw new Error("Something went wrong!")
|
||||||
|
});
|
||||||
|
const contentProvider = vi.fn().mockResolvedValue({}) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
try {
|
||||||
|
await handler(req, res);
|
||||||
|
expect(sendStatusSpy).toHaveBeenCalledExactlyOnceWith(500);
|
||||||
|
} catch {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it("returns correct response if range is not specified", async () => {
|
||||||
|
const result = ({
|
||||||
|
pipe() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} as any) as Stream;
|
||||||
|
const content: Content = {
|
||||||
|
fileName: "file.txt",
|
||||||
|
totalSize: 10,
|
||||||
|
mimeType: "text/plain",
|
||||||
|
getStream(range?: Range) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const pipeSpy = vi.spyOn(result, "pipe");
|
||||||
|
const getStreamSpy = vi.spyOn(content, "getStream");
|
||||||
|
const contentProvider = vi.fn().mockResolvedValue(content) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
const setContentTypeHeaderSpy = vi.spyOn(utils, "setContentTypeHeader");
|
||||||
|
const setContentDispositionHeaderSpy = vi.spyOn(utils, "setContentDispositionHeader");
|
||||||
|
const setAcceptRangesHeaderSpy = vi.spyOn(utils, "setAcceptRangesHeader");
|
||||||
|
const setContentLengthHeaderSpy = vi.spyOn(utils, "setContentLengthHeader");
|
||||||
|
const setContentRangeHeaderSpy = vi.spyOn(utils, "setContentRangeHeader");
|
||||||
|
try {
|
||||||
|
await handler(req, res);
|
||||||
|
expect(setContentTypeHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.mimeType, res);
|
||||||
|
expect(setContentDispositionHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.fileName, res);
|
||||||
|
expect(setAcceptRangesHeaderSpy).toHaveBeenCalledExactlyOnceWith(res);
|
||||||
|
expect(setContentLengthHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.totalSize, res);
|
||||||
|
expect(getStreamSpy).toHaveBeenCalledExactlyOnceWith();
|
||||||
|
expect(pipeSpy).toHaveBeenCalledExactlyOnceWith(res);
|
||||||
|
expect(setContentRangeHeaderSpy).not.toHaveBeenCalled();
|
||||||
|
} catch {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it("returns correct partial response if range is specified", async () => {
|
||||||
|
req.headers = {
|
||||||
|
range: "bytes=0-5"
|
||||||
|
};
|
||||||
|
const result = ({
|
||||||
|
pipe() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} as any) as Stream;
|
||||||
|
const content: Content = {
|
||||||
|
fileName: "file.txt",
|
||||||
|
totalSize: 10,
|
||||||
|
mimeType: "text/plain",
|
||||||
|
getStream(range?: Range) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const range = { start: 0, end: 5 };
|
||||||
|
const pipeSpy = vi.spyOn(result, "pipe");
|
||||||
|
const getStreamSpy = vi.spyOn(content, "getStream");
|
||||||
|
const contentProvider = vi.fn().mockResolvedValue(content) as ContentProvider;
|
||||||
|
const handler = createPartialContentHandler(contentProvider, logger);
|
||||||
|
const setContentTypeHeaderSpy = vi.spyOn(utils, "setContentTypeHeader");
|
||||||
|
const setContentDispositionHeaderSpy = vi.spyOn(utils, "setContentDispositionHeader");
|
||||||
|
const setAcceptRangesHeaderSpy = vi.spyOn(utils, "setAcceptRangesHeader");
|
||||||
|
const setContentLengthHeaderSpy = vi.spyOn(utils, "setContentLengthHeader");
|
||||||
|
const setContentRangeHeaderSpy = vi.spyOn(utils, "setContentRangeHeader");
|
||||||
|
try {
|
||||||
|
await handler(req, res);
|
||||||
|
expect(setContentTypeHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.mimeType, res);
|
||||||
|
expect(setContentDispositionHeaderSpy).toHaveBeenCalledExactlyOnceWith(content.fileName, res);
|
||||||
|
expect(setAcceptRangesHeaderSpy).toHaveBeenCalledExactlyOnceWith(res);
|
||||||
|
expect(setContentRangeHeaderSpy).toHaveBeenCalledExactlyOnceWith(range, content.totalSize, res);
|
||||||
|
expect(setContentLengthHeaderSpy).toHaveBeenCalledExactlyOnceWith(6, res);
|
||||||
|
expect(getStreamSpy).toHaveBeenCalledExactlyOnceWith(range);
|
||||||
|
expect(pipeSpy).toHaveBeenCalledExactlyOnceWith(res);
|
||||||
|
} catch {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,20 +1,16 @@
|
|||||||
import { parseRangeHeader } from "../src/parseRangeHeader";
|
import { parseRangeHeader } from "./parseRangeHeader.js";
|
||||||
import { SinonSandbox, createSandbox } from "sinon";
|
import type { Logger } from "./Logger.js";
|
||||||
import { Logger } from "../src/Logger";
|
import { RangeParserError } from "./RangeParserError.js";
|
||||||
import { expect } from "chai";
|
|
||||||
import { RangeParserError } from "../src/RangeParserError";
|
|
||||||
|
|
||||||
describe("parseRangeHeader tests", () => {
|
describe("parseRangeHeader tests", () => {
|
||||||
let sandbox: SinonSandbox;
|
|
||||||
let logger: Logger;
|
let logger: Logger;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sandbox = createSandbox();
|
|
||||||
logger = {
|
logger = {
|
||||||
debug: sandbox.stub() as (message: string, extra?: any) => void
|
debug: vi.fn() as (message: string, extra?: any) => void
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
sandbox.restore();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
it("returns null if range is not specified", () => {
|
it("returns null if range is not specified", () => {
|
||||||
let value = parseRangeHeader("", 10, logger);
|
let value = parseRangeHeader("", 10, logger);
|
@ -1,6 +1,5 @@
|
|||||||
import { Request, Response } from "express";
|
import type { Request, Response } from "express";
|
||||||
import { expect } from "chai";
|
import { expect, type Mock } from "vitest";
|
||||||
import sinon, { SinonStub, SinonSpy } from "sinon";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getHeader,
|
getHeader,
|
||||||
@ -12,7 +11,7 @@ import {
|
|||||||
setContentDispositionHeader,
|
setContentDispositionHeader,
|
||||||
setContentRangeHeader,
|
setContentRangeHeader,
|
||||||
setCacheControlHeaderNoCache
|
setCacheControlHeaderNoCache
|
||||||
} from "../src/utils";
|
} from "./utils.js";
|
||||||
|
|
||||||
describe("utils tests", () => {
|
describe("utils tests", () => {
|
||||||
let req: Request;
|
let req: Request;
|
||||||
@ -25,7 +24,7 @@ describe("utils tests", () => {
|
|||||||
}
|
}
|
||||||
} as Request;
|
} as Request;
|
||||||
res = {
|
res = {
|
||||||
setHeader: sinon.stub() as (name: string, value: string) => void
|
setHeader: vi.fn() as (name: string, value: string) => void
|
||||||
} as Response;
|
} as Response;
|
||||||
});
|
});
|
||||||
describe("getHeader tests", () => {
|
describe("getHeader tests", () => {
|
||||||
@ -43,7 +42,7 @@ describe("utils tests", () => {
|
|||||||
const name = "Content-Type";
|
const name = "Content-Type";
|
||||||
const value = "application/octet-stream";
|
const value = "application/octet-stream";
|
||||||
setHeader(name, value, res);
|
setHeader(name, value, res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith(name, value));
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith(name, value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("getRangeHeader tests", () => {
|
describe("getRangeHeader tests", () => {
|
||||||
@ -56,34 +55,36 @@ describe("utils tests", () => {
|
|||||||
it("sets Content-Type header with specified value", () => {
|
it("sets Content-Type header with specified value", () => {
|
||||||
const value = "application/octet-stream";
|
const value = "application/octet-stream";
|
||||||
setContentTypeHeader(value, res);
|
setContentTypeHeader(value, res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Content-Type", value));
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Content-Type", value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("setContentLengthHeader tests", () => {
|
describe("setContentLengthHeader tests", () => {
|
||||||
it("sets Content-Length header with specified value", () => {
|
it("sets Content-Length header with specified value", () => {
|
||||||
const value = 100;
|
const value = "100";
|
||||||
setContentLengthHeader(value, res);
|
setContentLengthHeader(value, res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Content-Length", value));
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Content-Length", value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("setAcceptRangesHeader tests", () => {
|
describe("setAcceptRangesHeader tests", () => {
|
||||||
it("sets Accept-Ranges header with specified value", () => {
|
it("sets Accept-Ranges header with specified value", () => {
|
||||||
const value = "bytes";
|
const value = "bytes";
|
||||||
setAcceptRangesHeader(res);
|
setAcceptRangesHeader(res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Accept-Ranges", value));
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Accept-Ranges", value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("setContentRangeHeader tests", () => {
|
describe("setContentRangeHeader tests", () => {
|
||||||
it("sets Content-Range header with specified value", () => {
|
it("sets Content-Range header with specified value", () => {
|
||||||
let range = { start: 10, end: 100 };
|
let range: { start: number, end: number } | null = { start: 10, end: 100 };
|
||||||
const size = 1000;
|
const size = 1000;
|
||||||
let value = `bytes ${range.start}-${range.end}/${size}`;
|
let value = `bytes ${range.start}-${range.end}/${size}`;
|
||||||
setContentRangeHeader(range, size, res);
|
setContentRangeHeader(range, size, res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Content-Range", value));
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Content-Range", value);
|
||||||
|
(res.setHeader as Mock).mockReset();
|
||||||
|
|
||||||
range = null;
|
range = null;
|
||||||
value = `bytes */${size}`;
|
value = `bytes */${size}`;
|
||||||
setContentRangeHeader(range, size, res);
|
setContentRangeHeader(range, size, res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Content-Range", value));
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Content-Range", value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("setContentDispositionHeader tests", () => {
|
describe("setContentDispositionHeader tests", () => {
|
||||||
@ -91,20 +92,20 @@ describe("utils tests", () => {
|
|||||||
const fileName = "file.txt";
|
const fileName = "file.txt";
|
||||||
const value = `attachment; filename*=utf-8''${fileName}`;
|
const value = `attachment; filename*=utf-8''${fileName}`;
|
||||||
setContentDispositionHeader(fileName, res);
|
setContentDispositionHeader(fileName, res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Content-Disposition", value)).to.be.true;
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Content-Disposition", value);
|
||||||
});
|
});
|
||||||
it("sets Content-Disposition header with specified unicode", () => {
|
it("sets Content-Disposition header with specified unicode", () => {
|
||||||
const fileName = "file.txt";
|
const fileName = "file.txt";
|
||||||
const value = `attachment; filename*=utf-8''${encodeURIComponent(fileName)}`;
|
const value = `attachment; filename*=utf-8''${encodeURIComponent(fileName)}`;
|
||||||
setContentDispositionHeader(fileName, res);
|
setContentDispositionHeader(fileName, res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Content-Disposition", value)).to.be.true;
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Content-Disposition", value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("setCacheControlHeaderNoCache tests", () => {
|
describe("setCacheControlHeaderNoCache tests", () => {
|
||||||
it("sets Cache-Control header with specified value", () => {
|
it("sets Cache-Control header with specified value", () => {
|
||||||
const value = "no-cache";
|
const value = "no-cache";
|
||||||
setCacheControlHeaderNoCache(res);
|
setCacheControlHeaderNoCache(res);
|
||||||
expect((res.setHeader as SinonStub).calledOnceWith("Cache-Control", value));
|
expect(res.setHeader).toHaveBeenCalledExactlyOnceWith("Cache-Control", value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -5,6 +5,9 @@
|
|||||||
"references": [
|
"references": [
|
||||||
{
|
{
|
||||||
"path": "./tsconfig.lib.json"
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,26 @@
|
|||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
|
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
|
||||||
"emitDeclarationOnly": false,
|
"emitDeclarationOnly": false,
|
||||||
"types": ["node"]
|
"types": [
|
||||||
|
"node"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts"],
|
"include": [
|
||||||
"references": []
|
"src/**/*.ts"
|
||||||
|
],
|
||||||
|
"references": [],
|
||||||
|
"exclude": [
|
||||||
|
"vite.config.ts",
|
||||||
|
"vite.config.mts",
|
||||||
|
"vitest.config.ts",
|
||||||
|
"vitest.config.mts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.test.tsx",
|
||||||
|
"src/**/*.spec.tsx",
|
||||||
|
"src/**/*.test.js",
|
||||||
|
"src/**/*.spec.js",
|
||||||
|
"src/**/*.test.jsx",
|
||||||
|
"src/**/*.spec.jsx"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
29
packages/express-partial-content/tsconfig.spec.json
Normal file
29
packages/express-partial-content/tsconfig.spec.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./out-tsc/vitest",
|
||||||
|
"types": [
|
||||||
|
"vitest/globals",
|
||||||
|
"vitest/importMeta",
|
||||||
|
"vite/client",
|
||||||
|
"node",
|
||||||
|
"vitest"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"vite.config.ts",
|
||||||
|
"vite.config.mts",
|
||||||
|
"vitest.config.ts",
|
||||||
|
"vitest.config.mts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.test.tsx",
|
||||||
|
"src/**/*.spec.tsx",
|
||||||
|
"src/**/*.test.js",
|
||||||
|
"src/**/*.spec.js",
|
||||||
|
"src/**/*.test.jsx",
|
||||||
|
"src/**/*.spec.jsx",
|
||||||
|
"src/**/*.d.ts",
|
||||||
|
"src/**/*.ts"
|
||||||
|
]
|
||||||
|
}
|
23
packages/express-partial-content/vite.config.ts
Normal file
23
packages/express-partial-content/vite.config.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/packages/express-partial-content',
|
||||||
|
plugins: [],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
test: {
|
||||||
|
watch: false,
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
reporters: ['default'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: './test-output/vitest/coverage',
|
||||||
|
provider: 'v8' as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
Loading…
x
Reference in New Issue
Block a user