diff --git a/networkProxy/package.json b/networkProxy/package.json index 032d91af9..9734f0a5e 100644 --- a/networkProxy/package.json +++ b/networkProxy/package.json @@ -9,11 +9,14 @@ "dist" ], "scripts": { - "build": "tsc" + "build": "tsc", + "test": "vitest" }, "author": "Nikita ", "license": "MIT", "devDependencies": { + "jsdom": "^25.0.1", + "vitest": "^2.1.1", "typescript": "^5.6.2" } } diff --git a/tracker/tracker/src/tests/network.utils.test.ts b/networkProxy/tests/network-utils.test.ts similarity index 56% rename from tracker/tracker/src/tests/network.utils.test.ts rename to networkProxy/tests/network-utils.test.ts index cf2730af9..51774b8e9 100644 --- a/tracker/tracker/src/tests/network.utils.test.ts +++ b/networkProxy/tests/network-utils.test.ts @@ -8,77 +8,80 @@ import { isIterable, formatByteSize, getURL, -} from '../main/modules/Network/utils.js' -import { describe, it, expect, jest } from '@jest/globals' +} from '../src/utils.js'; +import { describe, it, expect } from 'vitest'; describe('Network utility function tests', () => { it('genResponseByType should handle response types correctly', () => { - expect(genResponseByType('json', '{"key":"value"}')).toEqual({ key: 'value' }) - expect(genResponseByType('blob', new Blob())).toBe('[object Blob]') - }) + expect(genResponseByType('json', '{"key":"value"}')).toEqual({ key: 'value' }); + expect(genResponseByType('blob', new Blob())).toBe('[object Blob]'); + }); it('getStringResponseByType should handle response types correctly', () => { - expect(getStringResponseByType('json', '{"key":"value"}')).toBe('{"key":"value"}') - expect(getStringResponseByType('json', { key: 'value' })).toBe('{"key":"value"}') - expect(getStringResponseByType('blob', new Blob())).toBe('[object Blob]') - }) + expect(getStringResponseByType('json', '{"key":"value"}')).toBe('{"key":"value"}'); + expect(getStringResponseByType('json', { key: 'value' })).toBe('{"key":"value"}'); + expect(getStringResponseByType('blob', new Blob())).toBe('[object Blob]'); + }); it('genStringBody should handle body types correctly', () => { - expect(genStringBody('{"key":"value"}')).toBe('{"key":"value"}') - expect(genStringBody(new URLSearchParams('key=value'))).toBe('key=value') + expect(genStringBody('{"key":"value"}')).toBe('{"key":"value"}'); + expect(genStringBody(new URLSearchParams('key=value'))).toBe('key=value'); // Add more cases as needed - }) + }); it('genGetDataByUrl should get data from URL', () => { - expect(genGetDataByUrl('http://localhost/?key=value')).toEqual({ key: 'value' }) + expect(genGetDataByUrl('http://localhost/?key=value')).toEqual({ key: 'value' }); // Add more cases as needed - }) + }); + it('genGetDataByUrl handles wrong format', () => { // @ts-ignore - expect(genGetDataByUrl('http://localhost/?key=value', '')).toEqual({ key: 'value' }) - }) + expect(genGetDataByUrl('http://localhost/?key=value', '')).toEqual({ key: 'value' }); + }); it('genFormattedBody should format body correctly', () => { - const param = new URLSearchParams('key=value&other=test') - const blob = new Blob([param.toString()], { type: 'text/plain' }) - const uArr = new Uint8Array([1, 2, 3]) - const dataView = new DataView(uArr.buffer) - expect(genFormattedBody('{"key":"value"}')).toEqual({ key: 'value' }) - expect(genFormattedBody('key=value&other=test')).toEqual({ key: 'value', other: 'test' }) - expect(genFormattedBody(param)).toEqual({ key: 'value', other: 'test' }) - expect(genFormattedBody(blob)).toEqual('[byte data]') - expect(genFormattedBody(dataView)).toEqual('[byte data]') - expect(genFormattedBody(uArr)).toEqual('[byte data]') - }) + const param = new URLSearchParams('key=value&other=test'); + const blob = new Blob([param.toString()], { type: 'text/plain' }); + const uArr = new Uint8Array([1, 2, 3]); + const dataView = new DataView(uArr.buffer); + expect(genFormattedBody('{"key":"value"}')).toEqual({ key: 'value' }); + expect(genFormattedBody('key=value&other=test')).toEqual({ key: 'value', other: 'test' }); + expect(genFormattedBody(param)).toEqual({ key: 'value', other: 'test' }); + expect(genFormattedBody(blob)).toEqual('[byte data]'); + expect(genFormattedBody(dataView)).toEqual('[byte data]'); + expect(genFormattedBody(uArr)).toEqual('[byte data]'); + }); it('isPureObject should return true for objects', () => { - expect(isPureObject({})).toBe(true) - expect(isPureObject([])).toBe(true) - expect(isPureObject(null)).toBe(false) - expect(isPureObject(undefined)).toBe(false) - }) + expect(isPureObject({})).toBe(true); + expect(isPureObject([])).toBe(true); + expect(isPureObject(null)).toBe(false); + expect(isPureObject(undefined)).toBe(false); + }); it('isIterable should return true for iterables', () => { - expect(isIterable([])).toBe(true) - expect(isIterable(new Map())).toBe(true) - expect(isIterable('string')).toBe(true) - expect(isIterable(undefined)).toBe(false) - }) + expect(isIterable([])).toBe(true); + expect(isIterable(new Map())).toBe(true); + expect(isIterable('string')).toBe(true); + expect(isIterable(undefined)).toBe(false); + }); it('formatByteSize should format byte sizes correctly', () => { - expect(formatByteSize(500)).toBe('500B') - expect(formatByteSize(1500)).toBe('1.5 KB') - expect(formatByteSize(1500000)).toBe('1.5 MB') - expect(formatByteSize(-1)).toBe('') - }) + expect(formatByteSize(500)).toBe('500B'); + expect(formatByteSize(1500)).toBe('1.5 KB'); + expect(formatByteSize(1500000)).toBe('1.5 MB'); + expect(formatByteSize(-1)).toBe(''); + }); it('getURL should get a URL', () => { - // @ts-ignore - delete window.location - // @ts-ignore - window.location = new URL('https://www.example.com') - expect(getURL('https://example.com').toString()).toBe('https://example.com/') - expect(getURL('//example.com').toString()).toBe('https://example.com/') - expect(getURL('/path').toString()).toBe('https://www.example.com/path') - }) -}) + const originalLocation = window.location; + Object.defineProperty(window, 'location', { + value: new URL('https://www.example.com'), + writable: true, + }); + expect(getURL('https://example.com').toString()).toBe('https://example.com/'); + expect(getURL('//example.com').toString()).toBe('https://example.com/'); + expect(getURL('/path').toString()).toBe('https://www.example.com/path'); + window.location = originalLocation; + }); +}); diff --git a/tracker/tracker/src/tests/networkMessage.test.ts b/networkProxy/tests/networkMessage.test.ts similarity index 50% rename from tracker/tracker/src/tests/networkMessage.test.ts rename to networkProxy/tests/networkMessage.test.ts index 148d85c3d..2cba10196 100644 --- a/tracker/tracker/src/tests/networkMessage.test.ts +++ b/networkProxy/tests/networkMessage.test.ts @@ -1,29 +1,27 @@ -import NetworkMessage, { RequestState, httpMethod } from '../main/modules/Network/networkMessage.js' -import { NetworkRequest } from '../main/app/messages.gen.js' -import { describe, it, expect, beforeEach, jest } from '@jest/globals' +import NetworkMessage from '../src/networkMessage.js'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('NetworkMessage', () => { - const ignoredHeaders = ['cookie'] - const setSessionTokenHeader = jest.fn() - const sanitize = jest.fn() + const ignoredHeaders = ['cookie']; + const setSessionTokenHeader = vi.fn(); + const sanitize = vi.fn(); beforeEach(() => { - jest.clearAllMocks() - }) + vi.clearAllMocks(); + }); describe('getMessage', () => { it('should properly construct and return a NetworkRequest', () => { // @ts-ignore - const networkMessage = new NetworkMessage(ignoredHeaders, setSessionTokenHeader, sanitize) + const networkMessage = new NetworkMessage(ignoredHeaders, setSessionTokenHeader, sanitize); - // Set some basic properties - networkMessage.method = 'GET' - networkMessage.url = 'https://example.com' - networkMessage.status = 200 - networkMessage.requestType = 'xhr' - networkMessage.startTime = 0 - networkMessage.duration = 500 - networkMessage.getData = { key: 'value' } + networkMessage.method = 'GET'; + networkMessage.url = 'https://example.com'; + networkMessage.status = 200; + networkMessage.requestType = 'xhr'; + networkMessage.startTime = 0; + networkMessage.duration = 500; + networkMessage.getData = { key: 'value' }; // Expect sanitized message sanitize.mockReturnValueOnce({ @@ -32,60 +30,61 @@ describe('NetworkMessage', () => { status: 200, request: {}, response: {}, - }) + }); - const result = networkMessage.getMessage() + const result = networkMessage.getMessage(); - const expected = NetworkRequest( - 'xhr', - 'GET', - 'https://example.com', - JSON.stringify({}), - JSON.stringify({}), - 200, - // yeah - result[7], - 500, - 0, - ) - expect(result).toBeDefined() - expect(result).toEqual(expected) - expect(sanitize).toHaveBeenCalledTimes(1) - }) - }) + const expected = { + requestType: 'xhr', + method: 'GET', + url: 'https://example.com', + request: JSON.stringify({}), + response: JSON.stringify({}), + status: 200, + startTime: result!.startTime, + duration: 500, + responseSize: 0 + }; + + expect(result).toBeDefined(); + expect(result).toEqual(expected); + expect(sanitize).toHaveBeenCalledTimes(1); + }); + }); describe('writeHeaders', () => { it('should properly write request and response headers', () => { // @ts-ignore - const networkMessage = new NetworkMessage(ignoredHeaders, setSessionTokenHeader, sanitize) + const networkMessage = new NetworkMessage(ignoredHeaders, setSessionTokenHeader, sanitize); - networkMessage.requestHeader = { 'Content-Type': 'application/json', cookie: 'test' } - networkMessage.header = { 'Content-Type': 'application/json', cookie: 'test' } + networkMessage.requestHeader = { 'Content-Type': 'application/json', cookie: 'test' }; + networkMessage.header = { 'Content-Type': 'application/json', cookie: 'test' }; - const result = networkMessage.writeHeaders() + const result = networkMessage.writeHeaders(); - expect(result).toBeDefined() - expect(result.reqHs).toEqual({ 'Content-Type': 'application/json' }) - expect(result.resHs).toEqual({ 'Content-Type': 'application/json' }) - expect(setSessionTokenHeader).toHaveBeenCalledTimes(1) - }) - }) + expect(result).toBeDefined(); + expect(result.reqHs).toEqual({ 'Content-Type': 'application/json' }); + expect(result.resHs).toEqual({ 'Content-Type': 'application/json' }); + expect(setSessionTokenHeader).toHaveBeenCalledTimes(1); + }); + }); describe('isHeaderIgnored', () => { it('should properly identify ignored headers', () => { // @ts-ignore - const networkMessage = new NetworkMessage(ignoredHeaders, setSessionTokenHeader, sanitize) + const networkMessage = new NetworkMessage(ignoredHeaders, setSessionTokenHeader, sanitize); + + expect(networkMessage.isHeaderIgnored('cookie')).toBe(true); + expect(networkMessage.isHeaderIgnored('Content-Type')).toBe(false); + }); - expect(networkMessage.isHeaderIgnored('cookie')).toBe(true) - expect(networkMessage.isHeaderIgnored('Content-Type')).toBe(false) - }) it('if ignoreHeaders is true should ignore all headers', () => { // @ts-ignore - const networkMessage = new NetworkMessage(true, setSessionTokenHeader, sanitize) + const networkMessage = new NetworkMessage(true, setSessionTokenHeader, sanitize); - expect(networkMessage.isHeaderIgnored('cookie')).toBe(true) - expect(networkMessage.isHeaderIgnored('Content-Type')).toBe(true) - expect(networkMessage.isHeaderIgnored('Random-Header')).toBe(true) - }) - }) -}) + expect(networkMessage.isHeaderIgnored('cookie')).toBe(true); + expect(networkMessage.isHeaderIgnored('Content-Type')).toBe(true); + expect(networkMessage.isHeaderIgnored('Random-Header')).toBe(true); + }); + }); +}); diff --git a/networkProxy/vitest.config.ts b/networkProxy/vitest.config.ts new file mode 100644 index 000000000..2c6a151d4 --- /dev/null +++ b/networkProxy/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig(({ mode }) => ({ + define: { global: 'window' }, + test: { + environment: "jsdom" + } +})); \ No newline at end of file diff --git a/tracker/tracker/src/tests/networkProxy.test.ts b/tracker/tracker/src/tests/networkProxy.test.ts deleted file mode 100644 index 15844bd7c..000000000 --- a/tracker/tracker/src/tests/networkProxy.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -// @ts-nocheck -import { describe, test, expect, beforeEach, jest } from '@jest/globals' -import setProxy from '../main/modules/Network/index.js' -import FetchProxy from '../main/modules/Network/fetchProxy.js' -import XHRProxy from '../main/modules/Network/xhrProxy.js' -import BeaconProxy from '../main/modules/Network/beaconProxy.js' - -globalThis.fetch = jest.fn() - -jest.mock('../main/modules/Network/fetchProxy.js') -jest.mock('../main/modules/Network/xhrProxy.js') -jest.mock('../main/modules/Network/beaconProxy.js') - -describe('Network Proxy', () => { - let context - const ignoredHeaders = [] - const setSessionTokenHeader = jest.fn() - const sanitize = jest.fn() - const sendMessage = jest.fn() - const isServiceUrl = jest.fn() - const tokenUrlMatcher = jest.fn() - - beforeEach(() => { - context = { - fetch: jest.fn(), - XMLHttpRequest: jest.fn(), - navigator: { - sendBeacon: jest.fn(), - }, - } - FetchProxy.create.mockReturnValue(jest.fn()) - XHRProxy.create.mockReturnValue(jest.fn()) - BeaconProxy.create.mockReturnValue(jest.fn()) - }) - test('should not replace fetch if not present', () => { - context = { - XMLHttpRequest: jest.fn(), - navigator: { - sendBeacon: jest.fn(), - }, - } - setProxy( - context, - ignoredHeaders, - setSessionTokenHeader, - sanitize, - sendMessage, - isServiceUrl, - tokenUrlMatcher, - ) - expect(context.fetch).toBeUndefined() - expect(FetchProxy.create).toHaveBeenCalledTimes(0) - expect(XHRProxy.create).toHaveBeenCalled() - expect(BeaconProxy.create).toHaveBeenCalled() - }) - test('should replace XMLHttpRequest if present', () => { - setProxy( - context, - ignoredHeaders, - setSessionTokenHeader, - sanitize, - sendMessage, - isServiceUrl, - tokenUrlMatcher, - ) - expect(context.XMLHttpRequest).toEqual(expect.any(Function)) - expect(XHRProxy.create).toHaveBeenCalled() - }) - - test('should replace fetch if present', () => { - setProxy( - context, - ignoredHeaders, - setSessionTokenHeader, - sanitize, - sendMessage, - isServiceUrl, - tokenUrlMatcher, - ) - expect(context.fetch).toEqual(expect.any(Function)) - expect(FetchProxy.create).toHaveBeenCalled() - }) - - test('should replace navigator.sendBeacon if present', () => { - setProxy( - context, - ignoredHeaders, - setSessionTokenHeader, - sanitize, - sendMessage, - isServiceUrl, - tokenUrlMatcher, - ) - expect(context.navigator.sendBeacon).toEqual(expect.any(Function)) - expect(BeaconProxy.create).toHaveBeenCalled() - }) -})