From 17008a694d3bc6c28cf9d03c9d18410818266c5b Mon Sep 17 00:00:00 2001 From: Alex K Date: Mon, 6 Feb 2023 12:42:18 +0100 Subject: [PATCH] change(tracker): unit tests for tracker * chore(tracker):exclude test files from compilation * feat(tracker): webworker unit tests * fix(tracker): no empty tests * change(tracker): add jest test to workflow * change(tracker): fix jest run --------- Co-authored-by: nick-delirium --- .github/workflows/ui-tests.js.yml | 6 +- .gitignore | 1 + tracker/tracker/.eslintignore | 3 + tracker/tracker/.eslintrc.cjs | 2 +- .../webworker/PrimitiveEncoder.unit.test.ts | 63 ++++++++++++ .../src/webworker/QueueSender.unit.test.ts | 95 +++++++++++++++++++ tracker/tracker/tsconfig-base.json | 3 +- 7 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 tracker/tracker/src/webworker/PrimitiveEncoder.unit.test.ts create mode 100644 tracker/tracker/src/webworker/QueueSender.unit.test.ts diff --git a/.github/workflows/ui-tests.js.yml b/.github/workflows/ui-tests.js.yml index 94d5a05d5..dbc6d377e 100644 --- a/.github/workflows/ui-tests.js.yml +++ b/.github/workflows/ui-tests.js.yml @@ -47,8 +47,10 @@ jobs: cd tracker/tracker npm i -g yarn yarn -# - name: Jest tests -# run: yarn test + - name: Jest tests + run: | + cd tracker/tracker + yarn test - name: Build tracker inst run: | cd tracker/tracker diff --git a/.gitignore b/.gitignore index d509c8e8c..5eeb1c83b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ public node_modules *DS_Store *.env +*.log **/*.envrc .idea diff --git a/tracker/tracker/.eslintignore b/tracker/tracker/.eslintignore index 688a8d852..228c6174c 100644 --- a/tracker/tracker/.eslintignore +++ b/tracker/tracker/.eslintignore @@ -6,3 +6,6 @@ build .cache .eslintrc.cjs *.gen.ts + +**/*.test.ts +src/main/plugin.ts \ No newline at end of file diff --git a/tracker/tracker/.eslintrc.cjs b/tracker/tracker/.eslintrc.cjs index 72c31e9a4..3b3ebc4fc 100644 --- a/tracker/tracker/.eslintrc.cjs +++ b/tracker/tracker/.eslintrc.cjs @@ -3,7 +3,7 @@ module.exports = { root: true, parser: '@typescript-eslint/parser', parserOptions: { - project: ['./tsconfig-base.json', './src/main/tsconfig-cjs.json'], + project: ['./tsconfig-base.json', './src/main/tsconfig-cjs.json'], // ??TODO: use correct project tsconfigRootDir: __dirname, }, plugins: ['prettier', '@typescript-eslint'], diff --git a/tracker/tracker/src/webworker/PrimitiveEncoder.unit.test.ts b/tracker/tracker/src/webworker/PrimitiveEncoder.unit.test.ts new file mode 100644 index 000000000..2d4be80b4 --- /dev/null +++ b/tracker/tracker/src/webworker/PrimitiveEncoder.unit.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, test, jest, beforeEach, afterEach } from '@jest/globals' +import PrimitiveEncoder from './PrimitiveEncoder.js' + +describe('PrimitiveEncoder', () => { + test('initial state', () => { + const enc = new PrimitiveEncoder(10) + + expect(enc.getCurrentOffset()).toBe(0) + expect(enc.isEmpty).toBe(true) + expect(enc.flush().length).toBe(0) + }) + + test('skip()', () => { + const enc = new PrimitiveEncoder(10) + enc.skip(5) + expect(enc.getCurrentOffset()).toBe(5) + expect(enc.isEmpty).toBe(false) + }) + + test('checkpoint()', () => { + const enc = new PrimitiveEncoder(10) + enc.skip(5) + enc.checkpoint() + expect(enc.flush().length).toBe(5) + }) + + test('boolean(true)', () => { + const enc = new PrimitiveEncoder(10) + enc.boolean(true) + enc.checkpoint() + const bytes = enc.flush() + expect(bytes.length).toBe(1) + expect(bytes[0]).toBe(1) + }) + test('boolean(false)', () => { + const enc = new PrimitiveEncoder(10) + enc.boolean(false) + enc.checkpoint() + const bytes = enc.flush() + expect(bytes.length).toBe(1) + expect(bytes[0]).toBe(0) + }) + // TODO: test correct enc/dec on a top level(?) with player(PrimitiveReader.ts)/tracker(PrimitiveEncoder.ts) + + test('buffer oveflow with string()', () => { + const N = 10 + const enc = new PrimitiveEncoder(N) + const wasWritten = enc.string('long string'.repeat(N)) + expect(wasWritten).toBe(false) + }) + test('buffer oveflow with uint()', () => { + const enc = new PrimitiveEncoder(1) + const wasWritten = enc.uint(Number.MAX_SAFE_INTEGER) + expect(wasWritten).toBe(false) + }) + test('buffer oveflow with boolean()', () => { + const enc = new PrimitiveEncoder(1) + let wasWritten = enc.boolean(true) + expect(wasWritten).toBe(true) + wasWritten = enc.boolean(true) + expect(wasWritten).toBe(false) + }) +}) diff --git a/tracker/tracker/src/webworker/QueueSender.unit.test.ts b/tracker/tracker/src/webworker/QueueSender.unit.test.ts new file mode 100644 index 000000000..fc89a60a4 --- /dev/null +++ b/tracker/tracker/src/webworker/QueueSender.unit.test.ts @@ -0,0 +1,95 @@ +import { describe, expect, test, jest, beforeEach, afterEach } from '@jest/globals' +import QueueSender from './QueueSender.js' + +global.fetch = () => Promise.resolve(new Response()) // jsdom does not have it + +function mockFetch(status: number) { + return jest + .spyOn(global, 'fetch') + .mockImplementation(() => Promise.resolve({ status } as Response)) +} +const baseURL = 'MYBASEURL' +const sampleArray = new Uint8Array(1) +const randomToken = 'abc' +function defaultQueueSender({ + url = baseURL, + onUnauthorised = () => {}, + onFailed = () => {}, +} = {}) { + return new QueueSender(baseURL, onUnauthorised, onFailed) +} + +describe('QueueSender', () => { + afterEach(() => { + jest.restoreAllMocks() + }) + + // Test fetch first parameter + authorization header to be present + + // authorise() / push() + test('Does not call fetch if not authorised', () => { + const queueSender = defaultQueueSender() + const fetchMock = mockFetch(200) + + queueSender.push(sampleArray) + expect(fetchMock).not.toBeCalled() + }) + test('Calls fetch on push() if authorised', () => { + const queueSender = defaultQueueSender() + const fetchMock = mockFetch(200) + + queueSender.authorise(randomToken) + expect(fetchMock).toBeCalledTimes(0) + queueSender.push(sampleArray) + expect(fetchMock).toBeCalledTimes(1) + }) + test('Calls fetch on authorisation if there was a push() call before', () => { + const queueSender = defaultQueueSender() + const fetchMock = mockFetch(200) + + queueSender.push(sampleArray) + queueSender.authorise(randomToken) + expect(fetchMock).toBeCalledTimes(1) + }) + + // .clean() + test("Doesn't call fetch on push() after clean()", () => { + const queueSender = defaultQueueSender() + const fetchMock = mockFetch(200) + + queueSender.authorise(randomToken) + queueSender.clean() + queueSender.push(sampleArray) + expect(fetchMock).not.toBeCalled() + }) + test("Doesn't call fetch on authorisation if there was push() & clean() calls before", () => { + const queueSender = defaultQueueSender() + const fetchMock = mockFetch(200) + + queueSender.push(sampleArray) + queueSender.clean() + queueSender.authorise(randomToken) + expect(fetchMock).not.toBeCalled() + }) + + //Test N sequential ToBeCalledTimes(N) + //Test N sequential pushes with different timeouts to be sequential + + // onUnauthorised + test('Calls onUnauthorized callback on 401', (done) => { + const onUnauthorised = jest.fn() + const queueSender = defaultQueueSender({ + onUnauthorised, + }) + const fetchMock = mockFetch(401) + queueSender.authorise(randomToken) + queueSender.push(sampleArray) + setTimeout(() => { + // how to make test simpler and more explicit? + expect(onUnauthorised).toBeCalled() + done() + }, 100) + }) + //Test onFailure + //Test attempts timeout/ attempts count (toBeCalledTimes on one batch) +}) diff --git a/tracker/tracker/tsconfig-base.json b/tracker/tracker/tsconfig-base.json index 9af9edb73..fa70026d2 100644 --- a/tracker/tracker/tsconfig-base.json +++ b/tracker/tracker/tsconfig-base.json @@ -10,5 +10,6 @@ "target": "es6", "module": "es6", "moduleResolution": "nodenext" - } + }, + "exclude": ["**/*.test.ts"] }