From 6f2709bcaa5fc82172133322b95f523fb2ee2c7f Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Fri, 23 Apr 2021 16:31:56 -0700 Subject: [PATCH] feat: add tests for registerServiceWorker --- test/unit/register.test.ts | 94 ++++++++++++++++++++++++++++++++++++++ test/unit/util.test.ts | 2 +- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/test/unit/register.test.ts b/test/unit/register.test.ts index d19f6300..c163e0a5 100644 --- a/test/unit/register.test.ts +++ b/test/unit/register.test.ts @@ -1,5 +1,7 @@ import { JSDOM } from "jsdom" import { loggerModule } from "../utils/helpers" +import { registerServiceWorker } from "../../src/browser/register" +import { LocationLike } from "./util.test" describe("register", () => { describe("when navigator and serviceWorker are defined", () => { @@ -37,6 +39,12 @@ describe("register", () => { global.navigator = (undefined as unknown) as Navigator & typeof globalThis global.location = (undefined as unknown) as Location & typeof globalThis }) + it("test should have access to browser globals from beforeAll", () => { + expect(typeof global.window).not.toBeFalsy() + expect(typeof global.document).not.toBeFalsy() + expect(typeof global.navigator).not.toBeFalsy() + expect(typeof global.location).not.toBeFalsy() + }) it("should register a ServiceWorker", () => { // Load service worker like you would in the browser @@ -84,4 +92,90 @@ describe("register", () => { expect(spy).toHaveBeenCalledWith("[Service Worker] navigator is undefined") }) }) + describe("registerServiceWorker", () => { + let serviceWorkerPath: string + let serviceWorkerScope: string + const mockFn = jest.fn((path: string, options: { scope: string }) => { + serviceWorkerPath = path + serviceWorkerScope = options.scope + return undefined + }) + + beforeAll(() => { + const location: LocationLike = { + pathname: "", + origin: "http://localhost:8080", + // search: "?environmentId=600e0187-0909d8a00cb0a394720d4dce", + } + const { window } = new JSDOM() + global.window = (window as unknown) as Window & typeof globalThis + global.document = window.document + global.navigator = window.navigator + global.location = location as Location + + Object.defineProperty(global.navigator, "serviceWorker", { + value: { + register: mockFn, + }, + }) + }) + + afterEach(() => { + mockFn.mockClear() + jest.resetModules() + }) + + afterAll(() => { + jest.restoreAllMocks() + + // We don't want these to stay around because it can affect other tests + global.window = (undefined as unknown) as Window & typeof globalThis + global.document = (undefined as unknown) as Document & typeof globalThis + global.navigator = (undefined as unknown) as Navigator & typeof globalThis + global.location = (undefined as unknown) as Location & typeof globalThis + }) + it("should register when options.base is undefined", async () => { + // Mock getElementById + const csStaticBasePath = "/static/development/Users/jp/Dev/code-server" + const spy = jest.spyOn(document, "getElementById") + // Create a fake element and set the attribute + const mockElement = document.createElement("div") + mockElement.id = "coder-options" + mockElement.setAttribute( + "data-settings", + `{"csStaticBase":"${csStaticBasePath}","logLevel":2,"disableTelemetry":false,"disableUpdateCheck":false}`, + ) + // Return mockElement from the spy + // this way, when we call "getElementById" + // it returns the element + spy.mockImplementation(() => mockElement) + + await registerServiceWorker() + + expect(mockFn).toBeCalled() + expect(serviceWorkerPath).toMatch(`${csStaticBasePath}/dist/serviceWorker.js`) + expect(serviceWorkerScope).toMatch("/") + }) + it("should register when options.base is defined", async () => { + const csStaticBasePath = "/static/development/Users/jp/Dev/code-server" + const spy = jest.spyOn(document, "getElementById") + // Create a fake element and set the attribute + const mockElement = document.createElement("div") + mockElement.id = "coder-options" + mockElement.setAttribute( + "data-settings", + `{"base":"proxy/","csStaticBase":"${csStaticBasePath}","logLevel":2,"disableTelemetry":false,"disableUpdateCheck":false}`, + ) + // Return mockElement from the spy + // this way, when we call "getElementById" + // it returns the element + spy.mockImplementation(() => mockElement) + + await registerServiceWorker() + + expect(mockFn).toBeCalled() + expect(serviceWorkerPath).toMatch(`/dist/serviceWorker.js`) + expect(serviceWorkerScope).toMatch("/") + }) + }) }) diff --git a/test/unit/util.test.ts b/test/unit/util.test.ts index 02f3fdc5..e4d6349a 100644 --- a/test/unit/util.test.ts +++ b/test/unit/util.test.ts @@ -16,7 +16,7 @@ import { loggerModule } from "../utils/helpers" const dom = new JSDOM() global.document = dom.window.document -type LocationLike = Pick +export type LocationLike = Pick // jest.mock is hoisted above the imports so we must use `require` here. jest.mock("@coder/logger", () => require("../utils/helpers").loggerModule)