-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add unit test for uploader.spec.ts #9543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| import { expect } from "chai"; | ||
| import * as sinon from "sinon"; | ||
| import * as fs from "fs"; | ||
| import * as zlib from "zlib"; | ||
| import { Uploader } from "./uploader"; | ||
| import { Client } from "../../apiv2"; | ||
| import * as hashcache from "./hashcache"; | ||
|
|
||
| describe("deploy/hosting/uploader", () => { | ||
| let clientPostStub: sinon.SinonStub; | ||
| let clientRequestStub: sinon.SinonStub; | ||
|
|
||
| class MockQueue { | ||
| public handler: any; | ||
| private promises: Promise<void>[] = []; | ||
| constructor(options: any) { | ||
| this.handler = options.handler; | ||
|
Check warning on line 17 in src/deploy/hosting/uploader.spec.ts
|
||
| } | ||
| add(item: any) { | ||
|
Check warning on line 19 in src/deploy/hosting/uploader.spec.ts
|
||
| const p = Promise.resolve(this.handler(item)); | ||
| this.promises.push(p); | ||
| } | ||
| process() { } | ||
|
Check failure on line 23 in src/deploy/hosting/uploader.spec.ts
|
||
| async wait() { | ||
| await Promise.all(this.promises); | ||
| return Promise.resolve(); | ||
| } | ||
| close() { } | ||
|
Check failure on line 28 in src/deploy/hosting/uploader.spec.ts
|
||
| stats() { | ||
| return { total: 0, complete: 0, cursor: 0 }; | ||
| } | ||
| } | ||
|
|
||
| beforeEach(() => { | ||
| sinon.stub(fs, "statSync"); | ||
| sinon.stub(fs, "createReadStream"); | ||
| sinon.stub(zlib, "createGzip"); | ||
| clientPostStub = sinon.stub(Client.prototype, "post"); | ||
| clientRequestStub = sinon.stub(Client.prototype, "request"); | ||
| sinon.stub(hashcache, "load").returns(new Map()); | ||
| sinon.stub(hashcache, "dump"); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| sinon.restore(); | ||
| }); | ||
|
|
||
| it("should initialize correctly", () => { | ||
| const uploader = new Uploader({ | ||
| version: "v1", | ||
| projectRoot: "root", | ||
| files: ["file1.txt"], | ||
| public: "public", | ||
| }); | ||
| expect(uploader).to.be.instanceOf(Uploader); | ||
| }); | ||
|
|
||
| it("should hash files and populate version", async () => { | ||
| const uploader = new Uploader({ | ||
| version: "v1", | ||
| projectRoot: "root", | ||
| files: ["file1.txt", "file2.txt"], | ||
| public: "public", | ||
| }); | ||
| (uploader as any).hashQueue = new MockQueue({ handler: (uploader as any).hashHandler.bind(uploader) }); | ||
|
Check failure on line 65 in src/deploy/hosting/uploader.spec.ts
|
||
| (uploader as any).populateQueue = new MockQueue({ handler: (uploader as any).populateHandler.bind(uploader) }); | ||
|
Check failure on line 66 in src/deploy/hosting/uploader.spec.ts
|
||
| (uploader as any).uploadQueue = new MockQueue({ handler: (uploader as any).uploadHandler.bind(uploader) }); | ||
|
Check failure on line 67 in src/deploy/hosting/uploader.spec.ts
|
||
|
|
||
| (fs.statSync as sinon.SinonStub).returns({ mtime: new Date(), size: 100 }); | ||
| const { PassThrough, Readable } = require("stream"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| // Mock stream for file1.txt | ||
| const mockStream1 = new Readable({ | ||
|
Check failure on line 73 in src/deploy/hosting/uploader.spec.ts
|
||
| read() { | ||
| this.push(Buffer.from("hash1")); | ||
| this.push(null); | ||
| }, | ||
| }); | ||
| // Mock stream for file2.txt | ||
| const mockStream2 = new Readable({ | ||
|
Check failure on line 80 in src/deploy/hosting/uploader.spec.ts
|
||
| read() { | ||
| this.push(Buffer.from("hash2")); | ||
| this.push(null); | ||
| }, | ||
| }); | ||
|
|
||
| (zlib.createGzip as sinon.SinonStub).callsFake(() => new PassThrough()); | ||
| (fs.createReadStream as sinon.SinonStub).callsFake((filePath: string) => { | ||
| if (filePath.includes("file1.txt")) { | ||
| return new Readable({ | ||
| read() { | ||
| this.push(Buffer.from("hash1")); | ||
| this.push(null); | ||
| }, | ||
| }); | ||
| } | ||
| if (filePath.includes("file2.txt")) { | ||
| return new Readable({ | ||
| read() { | ||
| this.push(Buffer.from("hash2")); | ||
| this.push(null); | ||
| }, | ||
| }); | ||
| } | ||
| return new PassThrough(); | ||
| }); | ||
|
Comment on lines
+72
to
+106
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This section for mocking streams can be simplified. The const createMockStream = (content: string) =>
new Readable({
read() {
this.push(Buffer.from(content));
this.push(null);
},
});
(zlib.createGzip as sinon.SinonStub).callsFake(() => new PassThrough());
(fs.createReadStream as sinon.SinonStub).callsFake((filePath: string) => {
if (filePath.includes("file1.txt")) {
return createMockStream("hash1");
}
if (filePath.includes("file2.txt")) {
return createMockStream("hash2");
}
return new PassThrough();
}); |
||
|
|
||
| clientPostStub.resolves({ | ||
| body: { | ||
| uploadUrl: "https://upload.url", | ||
| uploadRequiredHashes: [ | ||
| "af316ecb91a8ee7ae99210702b2d4758f30cdde3bf61e3d8e787d74681f90a6e", // hash for "hash1" | ||
| "e7bf382f6e5915b3f88619b866223ebf1d51c4c5321cccde2e9ff700a3259086" // hash for "hash2" | ||
|
Check failure on line 113 in src/deploy/hosting/uploader.spec.ts
|
||
| ] | ||
| }, | ||
| }); | ||
| clientRequestStub.resolves({ status: 200, response: { text: sinon.stub().resolves("") } }); | ||
|
|
||
| await uploader.start(); | ||
|
|
||
| expect(clientPostStub.calledWithMatch(/\/v1:populateFiles/)).to.be.true; | ||
| expect(clientPostStub.firstCall.args[1].files).to.have.property("/file1.txt"); | ||
| expect(clientPostStub.firstCall.args[1].files).to.have.property("/file2.txt"); | ||
| expect(clientRequestStub.calledTwice).to.be.true; | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
MockQueueclass usesanyin its constructor and methods. It could be made more type-safe by using generics, similar to the actualQueueimplementation it's mocking. This would improve the robustness and readability of the test setup. After applying this change, you'll also need to update the instantiation ofMockQueueto provide the generic type, for example:new MockQueue<string>({ ... }).