UNPKG

@itwin/core-backend

Version:
112 lines 4.6 kB
import { expect } from "chai"; import { stub } from "sinon"; import { Readable, Writable } from "stream"; import { RpcRequestStatus } from "@itwin/core-common"; import { sendResponse } from "../../rpc/web/response"; import { brotliDecompressSync, unzipSync } from "node:zlib"; /* eslint-disable @typescript-eslint/no-deprecated */ class StubResponse extends Writable { chunks = []; get buffer() { return Buffer.concat(this.chunks); } // eslint-disable-next-line @typescript-eslint/naming-convention _write(chunk, _encoding, callback) { this.chunks.push(chunk); callback(); } send = stub().returns(this); status = stub(); set = stub(); } describe("sendResponse", () => { let protocol; let request; let fulfillment; let req; let res; beforeEach(() => { protocol = { getStatus: () => RpcRequestStatus.Resolved }; request = { operation: { operationName: "fake-RPC-operation" } }; fulfillment = { allowCompression: true, status: 200, result: { data: [], }, }; req = { header: () => "gzip, deflate, br" }; res = new StubResponse(); }); it("should compress response using Brotli", async () => { // Arrange const originalData = generateJson(); const originalDataSize = Buffer.byteLength(originalData); fulfillment.result.objects = originalData; // Act await sendResponse(protocol, request, fulfillment, req, res); // Assert expect(res.set.calledWithExactly("Content-Encoding", "br")).to.be.true; const compressedData = res.send.getCall(0).args[0]; expect(compressedData).to.not.be.undefined; expect(compressedData.length).to.be.lessThan(originalDataSize); expect(brotliDecompressSync(compressedData).toString()).to.be.equal(originalData); }); it("should compress response using Gzip if Brotli is not supported", async () => { // Arrange const originalData = generateJson(); const originalDataSize = Buffer.byteLength(originalData); fulfillment.result.objects = originalData; req.header = () => "gzip, deflate"; // Act await sendResponse(protocol, request, fulfillment, req, res); // Assert expect(res.set.calledWithExactly("Content-Encoding", "gzip")).to.be.true; const compressedData = res.send.getCall(0).args[0]; expect(compressedData).to.not.be.undefined; expect(compressedData.length).to.be.lessThan(originalDataSize); expect(unzipSync(compressedData).toString()).to.be.equal(originalData); }); it("should not compress if Brotli and Gzip is not supported", async () => { // Arrange const originalData = generateJson(); fulfillment.result.objects = originalData; req.header = () => undefined; // Act await sendResponse(protocol, request, fulfillment, req, res); // Assert expect(res.set.calledWithMatch("Content-Encoding")).to.be.false; expect(res.send.getCall(0).args[0]).to.be.equal(originalData); }); it("should compress stream", async () => { // Arrange const originalData = generateJson(); const originalDataSize = Buffer.byteLength(originalData); fulfillment.result.stream = Readable.from(originalData); // Act await sendResponse(protocol, request, fulfillment, req, res); await new Promise((resolve) => res.on("finish", resolve)); // Assert const compressedData = res.buffer; expect(compressedData).to.not.be.undefined; expect(compressedData.length).to.be.lessThan(originalDataSize); expect(brotliDecompressSync(compressedData).toString()).to.be.equal(originalData); }); it("should support Accept-Encoding header value format without spaces between values", async () => { // Arrange fulfillment.result.objects = generateJson(); req.header = () => "gzip,deflate,br,zstd"; // Act await sendResponse(protocol, request, fulfillment, req, res); // Assert expect(res.set.calledWithExactly("Content-Encoding", "br")).to.be.true; }); }); function generateJson(minimumSize = 2000) { let propertyIdx = 0; const obj = {}; while (JSON.stringify(obj).length < minimumSize) { obj[`property-${propertyIdx}`] = `value-${propertyIdx}`; propertyIdx++; } return JSON.stringify(obj); } //# sourceMappingURL=response.test.js.map