Open notification to existing tab/window
This commit is contained in:
parent
37f32cce3a
commit
3a56b9f853
|
|
@ -25,6 +25,7 @@ const createSelf = () =>
|
|||
clients: {
|
||||
claim: jest.fn(() => Promise.resolve()),
|
||||
openWindow: jest.fn(() => Promise.resolve()),
|
||||
matchAll: jest.fn(() => Promise.resolve([])),
|
||||
},
|
||||
}) as unknown as ServiceWorkerGlobalScope
|
||||
|
||||
|
|
@ -32,12 +33,16 @@ let originalWindow: Window & typeof globalThis
|
|||
|
||||
describe("service worker", () => {
|
||||
let self: ServiceWorkerGlobalScope
|
||||
let controlledClients: Client[]
|
||||
let uncontrolledClients: Client[]
|
||||
|
||||
beforeEach(() => {
|
||||
originalWindow = global.window
|
||||
global.window = undefined as any
|
||||
indexedDB = new IDBFactory()
|
||||
self = createSelf()
|
||||
controlledClients = []
|
||||
uncontrolledClients = []
|
||||
|
||||
fetchMock.mockResponse((req) => {
|
||||
if (
|
||||
|
|
@ -94,28 +99,71 @@ describe("service worker", () => {
|
|||
)
|
||||
})
|
||||
|
||||
test("closes notification on click", async () => {
|
||||
initWorker(self)
|
||||
describe("on notification click", () => {
|
||||
test("the notification is closed", async () => {
|
||||
initWorker(self)
|
||||
|
||||
const notificationHandler = getHandler("notificationclick")
|
||||
const notificationHandler = getHandler("notificationclick")
|
||||
|
||||
const event = createNotificationEvent("tackupnow.com")
|
||||
notificationHandler(event)
|
||||
await waitUntilCalls(event)
|
||||
const event = createNotificationEvent("tackupnow.com")
|
||||
notificationHandler(event)
|
||||
await waitUntilCalls(event)
|
||||
|
||||
expect(event.notification.close).toHaveBeenCalled()
|
||||
})
|
||||
expect(event.notification.close).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test("opens tack up now on click", async () => {
|
||||
initWorker(self)
|
||||
test("opens tack up now if no clients match the destination", async () => {
|
||||
initWorker(self)
|
||||
|
||||
const notificationHandler = getHandler("notificationclick")
|
||||
const notificationHandler = getHandler("notificationclick")
|
||||
|
||||
const event = createNotificationEvent("tackupnow.com")
|
||||
notificationHandler(event)
|
||||
await waitUntilCalls(event)
|
||||
const event = createNotificationEvent("tackupnow.com")
|
||||
notificationHandler(event)
|
||||
await waitUntilCalls(event)
|
||||
|
||||
expect(self.clients.openWindow).toHaveBeenCalledWith("tackupnow.com")
|
||||
expect(self.clients.openWindow).toHaveBeenCalledWith("tackupnow.com")
|
||||
})
|
||||
|
||||
test("focuses first matching client", async () => {
|
||||
addClient("https://tackupnow.com/place", "window", true)
|
||||
const matchingClient = addClient(
|
||||
"https://tackupnow.com/otherplace",
|
||||
"window",
|
||||
true
|
||||
)
|
||||
addClient("https://tackupnow.com/yetanotherotherplace", "window", true)
|
||||
|
||||
initWorker(self)
|
||||
|
||||
const notificationHandler = getHandler("notificationclick")
|
||||
|
||||
const event = createNotificationEvent("https://tackupnow.com/otherplace")
|
||||
notificationHandler(event)
|
||||
await waitUntilCalls(event)
|
||||
|
||||
expect(matchingClient.focus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test("focuses uncontrolled matching clients", async () => {
|
||||
addClient("https://derpatious.world", "window", false)
|
||||
addClient("https://tackupnow.com/1", "window", false)
|
||||
const matchingClient = addClient(
|
||||
"https://tackupnow.com/2",
|
||||
"window",
|
||||
false
|
||||
)
|
||||
addClient("https://tackupnow.com/controlled", "window", true)
|
||||
|
||||
initWorker(self)
|
||||
|
||||
const notificationHandler = getHandler("notificationclick")
|
||||
|
||||
const event = createNotificationEvent("https://tackupnow.com/2")
|
||||
notificationHandler(event)
|
||||
await waitUntilCalls(event)
|
||||
|
||||
expect(matchingClient.focus).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
test("claims on activate", async () => {
|
||||
|
|
@ -287,6 +335,31 @@ describe("service worker", () => {
|
|||
})
|
||||
})
|
||||
|
||||
function addClient(url: string, type: ClientTypes, controlled: boolean) {
|
||||
const matchAllMock = self.clients.matchAll as jest.Mock
|
||||
|
||||
matchAllMock.mockImplementation(
|
||||
(args: { type: string; includeUncontrolled?: boolean }) => {
|
||||
const clientList = args.includeUncontrolled
|
||||
? [...uncontrolledClients, ...controlledClients]
|
||||
: controlledClients
|
||||
return clientList.filter((client) => client.type === args.type)
|
||||
}
|
||||
)
|
||||
|
||||
const clientList = controlled ? controlledClients : uncontrolledClients
|
||||
|
||||
const client: WindowClient = {
|
||||
url,
|
||||
type,
|
||||
focus: jest.fn(() => Promise.resolve(client)) as WindowClient["focus"],
|
||||
} as WindowClient
|
||||
|
||||
clientList.push(client)
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
function getHandler(eventName: string) {
|
||||
expect(self.addEventListener).toHaveBeenCalledWith(
|
||||
eventName,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,12 @@ export default function start(self: ServiceWorkerGlobalScope) {
|
|||
})
|
||||
|
||||
self.addEventListener("push", function (event: PushEvent) {
|
||||
const { title, body, badge, icon, destination } = event.data?.json()
|
||||
const { title, body, badge, icon, destination } = event.data?.json() ?? {
|
||||
title: "It was missing yo",
|
||||
badge: "image/blah",
|
||||
icon: "image/blah",
|
||||
destination: "https://tackupnow.com",
|
||||
}
|
||||
|
||||
event.waitUntil(
|
||||
self.registration.showNotification(title, {
|
||||
|
|
@ -31,9 +36,25 @@ export default function start(self: ServiceWorkerGlobalScope) {
|
|||
|
||||
self.addEventListener("notificationclick", function (event) {
|
||||
event.notification.close()
|
||||
const destination = event.notification.data.destination
|
||||
|
||||
event.waitUntil(
|
||||
self.clients.openWindow(event.notification.data.destination)
|
||||
(async () => {
|
||||
const clients = await self.clients.matchAll({
|
||||
type: "window",
|
||||
includeUncontrolled: true,
|
||||
})
|
||||
|
||||
const existingClient = clients.find(
|
||||
(client) => client.url === event.notification.data.destination
|
||||
)
|
||||
|
||||
if (existingClient === undefined) {
|
||||
await self.clients.openWindow(destination)
|
||||
} else {
|
||||
await existingClient.focus()
|
||||
}
|
||||
})()
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue