From 35ba4b7979a7cfbb76176af6772da11f9729d519 Mon Sep 17 00:00:00 2001 From: Marius Friess <34072851+mariusfriess@users.noreply.github.com> Date: Sun, 20 Aug 2023 22:49:37 +0200 Subject: [PATCH] Add unit tests for BrowserModule (#56) * Add Browser tests * fix lint error --- jest-all.json | 3 +- src/browser/browser.service.spec.ts | 124 ++++++++++++++++++++++++++++ src/browser/browser.ts | 116 +++++++++++++------------- 3 files changed, 186 insertions(+), 57 deletions(-) create mode 100644 src/browser/browser.service.spec.ts diff --git a/jest-all.json b/jest-all.json index 369000d..24afbac 100644 --- a/jest-all.json +++ b/jest-all.json @@ -5,5 +5,6 @@ "testRegex": ".(e2e-)?spec.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" - } + }, + "collectCoverageFrom": ["src/**/*.ts", "test/**/*.ts"] } diff --git a/src/browser/browser.service.spec.ts b/src/browser/browser.service.spec.ts new file mode 100644 index 0000000..fda7135 --- /dev/null +++ b/src/browser/browser.service.spec.ts @@ -0,0 +1,124 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { BrowserService } from './browser.service'; +import { Server } from 'socket.io'; +import { Channel } from '../channel/channel'; + +describe('BrowserService', () => { + let service: BrowserService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [], + providers: [BrowserService], + }).compile(); + + service = module.get<BrowserService>(BrowserService); + }); + + afterEach(async () => { + await service.close(); + }); + + /** + * Single test case: Verifies if the BrowserService is defined. + */ + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('openWebsite', () => { + it('should create a browser context for a new channelId', async () => { + const channelId = 'test-channel-id'; + const url = 'https://example.com'; + const server = { + to: () => { + return { + emit: jest.fn(), + }; + }, + } as unknown as Server; + + const peerId = await service.openWebsite(channelId, url, server); + expect(peerId).toBeDefined(); + expect(service.getPeerId(channelId)).toEqual(peerId); + }); + }); + + describe('browserInteraction', () => { + it('should execute the browser interaction functions', async () => { + const channelId = 'test-channel-id'; + const url = 'https://example.com'; + const server = { + to: () => { + return { + emit: jest.fn(), + }; + }, + } as unknown as Server; + + const peerId = await service.openWebsite(channelId, url, server); + expect(peerId).toBeDefined(); + + await service.moveMouse(channelId, 0, 0); + await service.mouseDown(channelId); + await service.mouseUp(channelId); + await service.keyDown(channelId, 'a'); + await service.keyUp(channelId, 'a'); + await service.scroll(channelId, 0); + await service.navigateForward(channelId); + await service.closeBrowserContext(channelId); + expect(service.getPeerId(channelId)).toBeUndefined(); + }); + }); + + describe('getFromChannel', () => { + it('should return the browser context associated with a channel', async () => { + const channelId = 'test-channel-id'; + const url = 'https://example.com'; + const server = { + to: () => { + return { + emit: jest.fn(), + }; + }, + } as unknown as Server; + + const peerId = await service.openWebsite(channelId, url, server); + expect(peerId).toBeDefined(); + + const channel = { + id: channelId, + } as Channel; + + const browser = service.getFromChannel(channel); + expect(browser).toBeDefined(); + }); + }); + + describe('closeBrowserContext', () => { + it('should close the browser context associated with a channel', async () => { + const channelId = 'test-channel-id'; + const url = 'https://example.com'; + const server = { + to: () => { + return { + emit: jest.fn(), + }; + }, + } as unknown as Server; + + const peerId = await service.openWebsite(channelId, url, server); + expect(peerId).toBeDefined(); + + const channel = { + id: channelId, + } as Channel; + + const browser = service.getFromChannel(channel); + expect(browser).toBeDefined(); + await service.closeBrowserContext(channelId); + const browser2 = service.getFromChannel(channel); + expect(browser2).toBeNull(); + }); + }); +}); diff --git a/src/browser/browser.ts b/src/browser/browser.ts index 05a9702..199a4b5 100644 --- a/src/browser/browser.ts +++ b/src/browser/browser.ts @@ -21,6 +21,8 @@ export class Browser { * * @param browser - The Puppeteer browser instance. * @param url - The initial URL to open. + * @param server - The Socket.IO server instance. + * @param channelId - The ID of the channel. */ constructor( private browser: PuppeteerBrowser, @@ -38,7 +40,7 @@ export class Browser { LOGGER.debug(`Opening page with url: ${this.url}`); this.page = await this.browser.newPage(); - await installMouseHelper(this.page); + await this.installMouseHelper(this.page); await this.page.goto(this.url); await this.page.setViewport({ width: 1920, height: 1080 }); @@ -65,6 +67,7 @@ export class Browser { await this.page.bringToFront(); + /* istanbul ignore next */ const id = await extensionPage.evaluate(async () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -167,25 +170,25 @@ export class Browser { await this.browser.close(); } } -} -/** - * Helper function to install mouse tracking for puppeteer pages. - * - * @param page - The puppeteer page to install the mouse tracking on. - */ -async function installMouseHelper(page) { - await page.evaluateOnNewDocument(() => { - // Install mouse helper only for top-level frame. - if (window !== window.parent) { - return; - } - window.addEventListener( - 'DOMContentLoaded', - () => { - const box = document.createElement('puppeteer-mouse-pointer'); - const styleElement = document.createElement('style'); - styleElement.innerHTML = ` + /** + * Helper function to install mouse tracking for puppeteer pages. + * + * @param page - The puppeteer page to install the mouse tracking on. + */ + private async installMouseHelper(page) { + await page.evaluateOnNewDocument(() => { + // Install mouse helper only for top-level frame. + if (window !== window.parent) { + return; + } + // istanbul ignore next + window.addEventListener( + 'DOMContentLoaded', + () => { + const box = document.createElement('puppeteer-mouse-pointer'); + const styleElement = document.createElement('style'); + styleElement.innerHTML = ` puppeteer-mouse-pointer { pointer-events: none; position: absolute; @@ -222,43 +225,44 @@ async function installMouseHelper(page) { border-color: rgba(0,255,0,0.9); } `; - document.head.appendChild(styleElement); - document.body.appendChild(box); - document.addEventListener( - 'mousemove', - (event) => { - box.style.left = event.pageX + 'px'; - box.style.top = event.pageY + 'px'; - updateButtons(event.buttons); - }, - true, - ); - document.addEventListener( - 'mousedown', - (event) => { - updateButtons(event.buttons); - box.classList.add('button-' + event.which); - }, - true, - ); - document.addEventListener( - 'mouseup', - (event) => { - updateButtons(event.buttons); - box.classList.remove('button-' + event.which); - }, - true, - ); + document.head.appendChild(styleElement); + document.body.appendChild(box); + document.addEventListener( + 'mousemove', + (event) => { + box.style.left = event.pageX + 'px'; + box.style.top = event.pageY + 'px'; + updateButtons(event.buttons); + }, + true, + ); + document.addEventListener( + 'mousedown', + (event) => { + updateButtons(event.buttons); + box.classList.add('button-' + event.which); + }, + true, + ); + document.addEventListener( + 'mouseup', + (event) => { + updateButtons(event.buttons); + box.classList.remove('button-' + event.which); + }, + true, + ); - function updateButtons(buttons) { - for (let i = 0; i < 5; i++) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - box.classList.toggle('button-' + i, buttons & (1 << i)); + function updateButtons(buttons) { + for (let i = 0; i < 5; i++) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + box.classList.toggle('button-' + i, buttons & (1 << i)); + } } - } - }, - false, - ); - }); + }, + false, + ); + }); + } } -- GitLab