Add unit tests for InfoQuery and Query

This commit is contained in:
Jelle Glebbeek
2021-03-17 01:48:08 +01:00
parent 54de46b665
commit 49320a31cf
2 changed files with 201 additions and 0 deletions

48
tests/InfoQuery.test.js Normal file
View File

@@ -0,0 +1,48 @@
const InfoQuery = require("../modules/info/InfoQuery");
describe('Connect the InfoQuery', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('Checks the error when applicable', async () => {
const [env, instance] = instanceBuilder();
env.metadataLimiter.schedule.mockRejectedValue({ stderr: "test-error"});
const result = instance.connect();
await result;
expect(env.errorHandler.checkError).toBeCalledWith("test-error", "test__id");
});
it('Returns null on error', async () => {
const [env, instance] = instanceBuilder();
env.metadataLimiter.schedule.mockRejectedValue({ stderr: "test-error"});
const result = instance.connect();
await expect(result).resolves.toBe(null);
});
it('Schedules the query', async () => {
const [env, instance] = instanceBuilder();
const jsonString = "{\"test\": \"data\"}";
env.metadataLimiter.schedule.mockResolvedValue(jsonString);
const result = instance.connect();
await result;
expect(env.metadataLimiter.schedule).toBeCalledTimes(1);
});
it('Returns the parsed query data', async () => {
const [env, instance] = instanceBuilder();
const jsonString = "{\"test\": \"data\"}";
env.metadataLimiter.schedule.mockResolvedValue(jsonString);
const result = instance.connect();
await expect(result).resolves.toMatchObject(JSON.parse(jsonString))
});
});
function instanceBuilder() {
const env = {
metadataLimiter: {
schedule: jest.fn()
},
errorHandler: {
checkError: jest.fn()
}
};
return [env, new InfoQuery("http://url.link", "test__id", env)];
}

153
tests/Query.test.js Normal file
View File

@@ -0,0 +1,153 @@
const UserAgent = require('user-agents');
const Query = require("../modules/types/Query");
const execa = require('execa');
const { PassThrough } = require('stream');
jest.mock('user-agents');
jest.mock('execa');
beforeEach(() => {
jest.clearAllMocks();
jest.doMock('execa', () => {
const originalModule = jest.requireActual('execa')
return {
__esModule: true,
...originalModule,
execa: jest.fn()
}
});
});
describe('ytdl Query', () => {
beforeEach(() => {
execa.mockResolvedValue({stdout: "fake-data"});
});
it('adds a random user agent when this setting is enabled', () => {
UserAgent.prototype.toString = jest.fn().mockReturnValue("agent");
const errorHandlerMock = jest.fn();
const instance = instanceBuilder(true, null, errorHandlerMock);
return instance.start("https://url.link", [], null).then(() => {
expect(UserAgent.prototype.toString).toBeCalledTimes(1);
expect(execa.mock.calls[0][1]).toContain("--user-agent");
expect(execa.mock.calls[0][1]).toContain("agent");
});
});
it('adds the cookies argument when specified in settings', () => {
const errorHandlerMock = jest.fn();
const instance = instanceBuilder(false, "a/path/to/cookies.txt", errorHandlerMock);
return instance.start("https://url.link", [], null).then(() => {
expect(execa.mock.calls[0][1]).toContain("--cookies");
expect(execa.mock.calls[0][1]).toContain("a/path/to/cookies.txt");
});
});
it('adds the url as final argument', () => {
const errorHandlerMock = jest.fn();
const instance = instanceBuilder(false, null, errorHandlerMock);
return instance.start("https://url.link", [], null).then(() => {
expect(execa.mock.calls[0][1]).toContain("https://url.link");
});
})
it('adds the no-cache-dir as argument', () => {
const errorHandlerMock = jest.fn();
const instance = instanceBuilder(false, null, errorHandlerMock);
return instance.start("https://url.link", [], null).then(() => {
expect(execa.mock.calls[0][1]).toContain("--no-cache-dir");
});
});
})
describe('Query with live callback', () => {
it('Stops with return value killed when stop() is called', async () => {
const [stdout, stderr, mock] = execaMockBuilder(true);
execa.mockReturnValue(mock)
const errorHandlerMock = jest.fn();
const callbackMock = jest.fn();
const instance = instanceBuilder(false, null, errorHandlerMock);
const result = instance.start("https://url.link", [], callbackMock);
setTimeout(() => {
instance.stop();
}, 100);
await expect(result).resolves.toEqual("killed");
expect(callbackMock).toBeCalledWith("killed");
});
it('Checks the error when stderr gets written to', async () => {
const [stdout, stderr, mock] = execaMockBuilder(false);
execa.mockReturnValue(mock)
console.error = jest.fn();
const errorHandlerMock = jest.fn();
const callbackMock = jest.fn();
const instance = instanceBuilder(false, null, errorHandlerMock);
const result = instance.start("https://url.link", [], callbackMock);
setTimeout(() => {
stderr.emit("data", "test-error");
}, 100);
setTimeout(() => {
stdout.emit("close");
}, 100);
await result;
expect(errorHandlerMock).toBeCalledWith("test-error", "test__id");
});
it('Resolves "done" when query was successful', async () => {
const [stdout, stderr, mock] = execaMockBuilder(false);
execa.mockReturnValue(mock)
const callbackMock = jest.fn();
const instance = instanceBuilder(false, null, jest.fn());
const result = instance.start("https://url.link", [], callbackMock);
setTimeout(() => {
stdout.emit("close");
}, 100);
await expect(result).resolves.toEqual("done");
expect(callbackMock).toBeCalledWith("done");
});
it('Sends live stdout to the callback', async () => {
const [stdout, stderr, mock] = execaMockBuilder(false);
execa.mockReturnValue(mock);
const callbackMock = jest.fn();
const instance = instanceBuilder(false, null, jest.fn());
const result = instance.start("https://url.link", [], callbackMock);
setTimeout(() => {
stdout.emit("data", "test-data");
stdout.emit("data", "more-test-data");
stdout.emit("close");
}, 100);
await result;
expect(callbackMock).toBeCalledWith("test-data");
expect(callbackMock).toBeCalledWith("more-test-data");
});
});
describe('Query without callback', () => {
it('Returns the data from the execa call', async () => {
execa.mockResolvedValue({stdout: "fake-data"});
const errorHandlerMock = jest.fn();
const instance = instanceBuilder(true, null, errorHandlerMock);
const result = instance.start("https://url.link", [], null)
await expect(result).resolves.toEqual("fake-data");
});
it('Returns a stringified empty object on error', async () => {
execa.mockResolvedValue(null);
const errorHandlerMock = jest.fn();
const instance = instanceBuilder(true, null, errorHandlerMock);
const result = instance.start("https://url.link", [], null)
await expect(result).resolves.toEqual("{}");
});
it('Checks the error on error', () => {
execa.mockResolvedValue(null);
const errorHandlerMock = jest.fn();
const instance = instanceBuilder(true, null, errorHandlerMock);
return instance.start("https://url.link", [], null).then(() => {
expect(errorHandlerMock).toBeCalledTimes(1);
});
});
})
function execaMockBuilder(killed) {
const stdout = new PassThrough();
const stderr = new PassThrough();
const mock = {stdout: stdout, stderr: stderr, cancel: jest.fn(() => { stdout.emit("close") }), killed: killed}
return [stdout, stderr, mock];
}
function instanceBuilder(spoofUserAgent, cookiePath, errorHandlerMock) {
return new Query({errorHandler: {checkError: errorHandlerMock}, paths: {ytdl: "a/path/to/ytdl"}, settings: {cookiePath: cookiePath, spoofUserAgent: spoofUserAgent}}, "test__id");
}