2021-02-11 22:02:49 +00:00
|
|
|
import { JSDOM } from "jsdom"
|
2021-04-23 23:31:56 +00:00
|
|
|
import { registerServiceWorker } from "../../src/browser/register"
|
2021-04-26 21:26:16 +00:00
|
|
|
import { loggerModule } from "../utils/helpers"
|
2021-04-23 23:31:56 +00:00
|
|
|
import { LocationLike } from "./util.test"
|
2021-02-11 22:02:49 +00:00
|
|
|
|
|
|
|
describe("register", () => {
|
2021-02-23 23:20:18 +00:00
|
|
|
describe("when navigator and serviceWorker are defined", () => {
|
|
|
|
const mockRegisterFn = jest.fn()
|
2021-02-22 22:50:26 +00:00
|
|
|
|
2021-02-23 23:20:18 +00:00
|
|
|
beforeAll(() => {
|
|
|
|
const { window } = new JSDOM()
|
|
|
|
global.window = (window as unknown) as Window & typeof globalThis
|
|
|
|
global.document = window.document
|
|
|
|
global.navigator = window.navigator
|
|
|
|
global.location = window.location
|
2021-02-22 22:50:26 +00:00
|
|
|
|
2021-02-23 23:20:18 +00:00
|
|
|
Object.defineProperty(global.navigator, "serviceWorker", {
|
|
|
|
value: {
|
|
|
|
register: mockRegisterFn,
|
|
|
|
},
|
|
|
|
})
|
2021-02-11 22:23:07 +00:00
|
|
|
})
|
2021-02-11 23:51:48 +00:00
|
|
|
|
2021-02-23 23:20:18 +00:00
|
|
|
beforeEach(() => {
|
2021-05-03 20:56:53 +00:00
|
|
|
jest.clearAllMocks()
|
2021-02-23 23:20:18 +00:00
|
|
|
jest.mock("@coder/logger", () => loggerModule)
|
|
|
|
})
|
2021-02-11 23:51:48 +00:00
|
|
|
|
2021-02-23 23:20:18 +00:00
|
|
|
afterEach(() => {
|
|
|
|
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
|
|
|
|
})
|
2021-05-03 20:56:53 +00:00
|
|
|
|
2021-04-23 23:31:56 +00:00
|
|
|
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()
|
|
|
|
})
|
2021-02-11 23:51:48 +00:00
|
|
|
|
2021-02-23 23:20:18 +00:00
|
|
|
it("should register a ServiceWorker", () => {
|
|
|
|
// Load service worker like you would in the browser
|
2021-03-09 23:32:31 +00:00
|
|
|
require("../../src/browser/register")
|
2021-02-23 23:20:18 +00:00
|
|
|
expect(mockRegisterFn).toHaveBeenCalled()
|
|
|
|
expect(mockRegisterFn).toHaveBeenCalledTimes(1)
|
|
|
|
})
|
|
|
|
|
|
|
|
it("should log an error if something doesn't work", () => {
|
|
|
|
const message = "Can't find browser"
|
|
|
|
const error = new Error(message)
|
|
|
|
|
|
|
|
mockRegisterFn.mockImplementation(() => {
|
|
|
|
throw error
|
|
|
|
})
|
|
|
|
|
|
|
|
// Load service worker like you would in the browser
|
2021-03-09 23:32:31 +00:00
|
|
|
require("../../src/browser/register")
|
2021-02-23 23:20:18 +00:00
|
|
|
|
|
|
|
expect(mockRegisterFn).toHaveBeenCalled()
|
|
|
|
expect(loggerModule.logger.error).toHaveBeenCalled()
|
|
|
|
expect(loggerModule.logger.error).toHaveBeenCalledTimes(1)
|
|
|
|
expect(loggerModule.logger.error).toHaveBeenCalledWith(
|
|
|
|
`[Service Worker] registration: ${error.message} ${error.stack}`,
|
|
|
|
)
|
|
|
|
})
|
2021-02-22 22:50:26 +00:00
|
|
|
})
|
2021-02-11 23:51:48 +00:00
|
|
|
|
2021-02-23 23:20:18 +00:00
|
|
|
describe("when navigator and serviceWorker are NOT defined", () => {
|
|
|
|
beforeEach(() => {
|
2021-05-03 20:56:53 +00:00
|
|
|
jest.clearAllMocks()
|
|
|
|
jest.mock("@coder/logger", () => loggerModule)
|
2021-02-11 23:51:48 +00:00
|
|
|
})
|
|
|
|
|
2021-02-23 23:20:18 +00:00
|
|
|
afterAll(() => {
|
|
|
|
jest.restoreAllMocks()
|
|
|
|
})
|
2021-02-11 23:51:48 +00:00
|
|
|
|
2021-05-03 20:56:53 +00:00
|
|
|
it("should log an error", () => {
|
2021-02-23 23:20:18 +00:00
|
|
|
// Load service worker like you would in the browser
|
2021-03-09 23:32:31 +00:00
|
|
|
require("../../src/browser/register")
|
2021-05-03 20:56:53 +00:00
|
|
|
expect(loggerModule.logger.error).toHaveBeenCalled()
|
|
|
|
expect(loggerModule.logger.error).toHaveBeenCalledTimes(1)
|
|
|
|
expect(loggerModule.logger.error).toHaveBeenCalledWith("[Service Worker] navigator is undefined")
|
2021-02-23 23:20:18 +00:00
|
|
|
})
|
2021-02-11 22:02:49 +00:00
|
|
|
})
|
2021-05-03 20:56:53 +00:00
|
|
|
|
2021-04-23 23:31:56 +00:00
|
|
|
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",
|
|
|
|
}
|
|
|
|
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("/")
|
|
|
|
})
|
|
|
|
})
|
2021-02-11 22:02:49 +00:00
|
|
|
})
|