Replace vapid key that accidentally got committed, show notifications in app
Test / test (push) Successful in 1m2s Details

This commit is contained in:
Jeff 2024-10-19 19:20:51 -04:00
parent e9c7d7a8ef
commit 37f32cce3a
6 changed files with 111 additions and 82 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ build/
/playwright-report/ /playwright-report/
/blob-report/ /blob-report/
/playwright/.cache/ /playwright/.cache/
send-it.js

View File

@ -20,9 +20,11 @@ const createSelf = () =>
subscribe: jest.fn(() => Promise.resolve(createSubscription())), subscribe: jest.fn(() => Promise.resolve(createSubscription())),
getSubscription: jest.fn(() => Promise.resolve(createSubscription())), getSubscription: jest.fn(() => Promise.resolve(createSubscription())),
}, },
showNotification: jest.fn(),
}, },
clients: { clients: {
claim: jest.fn(() => Promise.resolve()), claim: jest.fn(() => Promise.resolve()),
openWindow: jest.fn(() => Promise.resolve()),
}, },
}) as unknown as ServiceWorkerGlobalScope }) as unknown as ServiceWorkerGlobalScope
@ -37,28 +39,25 @@ describe("service worker", () => {
indexedDB = new IDBFactory() indexedDB = new IDBFactory()
self = createSelf() self = createSelf()
// fetchMock.mockIf(/http:\/\/localhost\/api\/subscribe\/?/, (req) => {
// return Promise.resolve(
// req.method === "POST"
// ? {
// body: JSON.stringify({ subscriptionId: 123 }),
// }
// : req.method === "PUT"
// ? { init: { status: 200 } }
// : { init: { status: 405 } }
// )
// })
fetchMock.mockResponse((req) => { fetchMock.mockResponse((req) => {
return Promise.resolve( if (
req.url.replace(/https?:\/\/[a-zA-Z0-9\.]*/, "") ===
"/api/subscription/" &&
req.method === "POST" req.method === "POST"
? { ) {
body: JSON.stringify({ subscriptionId: 123 }), return Promise.resolve({
} body: JSON.stringify({ subscriptionId: 123 }),
: req.method === "PUT" })
? { init: { status: 200 } } } else if (
: { init: { status: 405 } } req.url
) .replace(/https?:\/\/[a-zA-Z0-9\.]*/, "")
.startsWith("/api/subscription/") &&
req.method === "PUT"
) {
return Promise.resolve({ init: { status: 200 } })
}
return Promise.resolve({ init: { status: 500 } })
}) })
}) })
@ -67,13 +66,56 @@ describe("service worker", () => {
global.window = originalWindow global.window = originalWindow
}) })
xtest("displays push notifications", () => { test("displays push notifications", async () => {
initWorker(self) initWorker(self)
const pushHandler = getHandler("push") const pushHandler = getHandler("push")
const pushEvent = createEvent({ data: "HI" }) const pushEvent = createPushEvent(
JSON.stringify({
title: "Test title",
body: "Test text",
icon: "Test icon",
badge: "Test badge",
destination: "tackupnow.com/hi",
})
)
pushHandler(pushEvent) pushHandler(pushEvent)
await waitUntilCalls(pushEvent)
expect(self.registration.showNotification).toHaveBeenCalledWith(
"Test title",
{
body: "Test text",
icon: "Test icon",
badge: "Test badge",
data: { destination: "tackupnow.com/hi" },
}
)
})
test("closes notification on click", async () => {
initWorker(self)
const notificationHandler = getHandler("notificationclick")
const event = createNotificationEvent("tackupnow.com")
notificationHandler(event)
await waitUntilCalls(event)
expect(event.notification.close).toHaveBeenCalled()
})
test("opens tack up now on click", async () => {
initWorker(self)
const notificationHandler = getHandler("notificationclick")
const event = createNotificationEvent("tackupnow.com")
notificationHandler(event)
await waitUntilCalls(event)
expect(self.clients.openWindow).toHaveBeenCalledWith("tackupnow.com")
}) })
test("claims on activate", async () => { test("claims on activate", async () => {
@ -292,8 +334,19 @@ function createPushEvent(data: string) {
return createEvent(pushFields) return createEvent(pushFields)
} }
function createMessageEvent(message: any) { function createNotificationEvent(destination: string): NotificationEvent & {
return createEvent({ data: message }) waitUntil: jest.Mock<void, Parameters<ExtendableEvent["waitUntil"]>>
} {
return createEvent({
notification: {
close: jest.fn(),
data: {
destination,
},
},
}) as any as NotificationEvent & {
waitUntil: jest.Mock<void, Parameters<ExtendableEvent["waitUntil"]>>
}
} }
function createEvent(properties?: object) { function createEvent(properties?: object) {

View File

@ -16,29 +16,26 @@ export default function start(self: ServiceWorkerGlobalScope) {
event.waitUntil(self.clients.claim()) event.waitUntil(self.clients.claim())
}) })
// self.addEventListener("push", function (event: PushEvent) { self.addEventListener("push", function (event: PushEvent) {
// console.log("[Service Worker] Push Received.") const { title, body, badge, icon, destination } = event.data?.json()
// console.log(`[Service Worker] Push had this data: "${event.data?.text()}"`)
// const title = "Push Codelab" event.waitUntil(
// const options = { self.registration.showNotification(title, {
// body: "Yay it works.", body,
// icon: "images/icon.png", badge,
// badge: "images/badge.png", icon,
// } data: { destination },
})
)
})
// event.waitUntil(self.registration.showNotification(title, options)) self.addEventListener("notificationclick", function (event) {
// }) event.notification.close()
// self.addEventListener("notificationclick", function (event) { event.waitUntil(
// console.log("[Service Worker] Notification click Received.") self.clients.openWindow(event.notification.data.destination)
)
// event.notification.close() })
// event.waitUntil(
// self.clients.openWindow("https://developers.google.com/web/")
// )
// })
self.addEventListener("message", function (event) { self.addEventListener("message", function (event) {
const waitEvent = event as ExtendableEvent const waitEvent = event as ExtendableEvent

30
package-lock.json generated
View File

@ -31,7 +31,7 @@
"@babel/preset-env": "^7.24.5", "@babel/preset-env": "^7.24.5",
"@babel/preset-react": "^7.24.1", "@babel/preset-react": "^7.24.1",
"@babel/preset-typescript": "^7.24.1", "@babel/preset-typescript": "^7.24.1",
"@playwright/test": "^1.44.1", "@playwright/test": "^1.48.1",
"@remix-pwa/dev": "^3.1.0", "@remix-pwa/dev": "^3.1.0",
"@remix-run/dev": "^2.9.0", "@remix-run/dev": "^2.9.0",
"@remix-run/testing": "^2.9.1", "@remix-run/testing": "^2.9.1",
@ -3324,18 +3324,18 @@
} }
}, },
"node_modules/@playwright/test": { "node_modules/@playwright/test": {
"version": "1.44.1", "version": "1.48.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz",
"integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==", "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"playwright": "1.44.1" "playwright": "1.48.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=18"
} }
}, },
"node_modules/@remix-pwa/dev": { "node_modules/@remix-pwa/dev": {
@ -13843,33 +13843,33 @@
} }
}, },
"node_modules/playwright": { "node_modules/playwright": {
"version": "1.44.1", "version": "1.48.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz",
"integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"playwright-core": "1.44.1" "playwright-core": "1.48.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=18"
}, },
"optionalDependencies": { "optionalDependencies": {
"fsevents": "2.3.2" "fsevents": "2.3.2"
} }
}, },
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.44.1", "version": "1.48.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz",
"integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==",
"dev": true, "dev": true,
"bin": { "bin": {
"playwright-core": "cli.js" "playwright-core": "cli.js"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=18"
} }
}, },
"node_modules/playwright/node_modules/fsevents": { "node_modules/playwright/node_modules/fsevents": {

View File

@ -1 +1 @@
export default "BKc02U2-z7PkTbYgYLlxELWqzTVE631fs4IPuMLbxY_rxdo9VaduthqwkPOiblwjETl99uXes2Nc9EtPbS5x4uA" export default "BLoc3g9yZAgSB1HRwolI4NcGUaJRFhLKtf2Ys3Jcbtsr8yKsoCLldc4ynADLTGMbihTYbIKS8PdSHEKDGkCR4fI"

View File

@ -1,22 +0,0 @@
import webPush from "web-push"
const subscription = {
endpoint:
"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABm9FlbY5vMro60hF2iJF3UUBzweuFcg5NRSHXPSpHfUpjo5jKGVRnUxR4ekg0-FsvdQCP89cu__IFd06Tu2TJZ649YyqivRUBnAav0DgOLHGx5-t943QLS-wLvBqyJRCuuLlM1bLz6S9ph9AWJ8CG7rQuTabsHvw--s_w2KDQo3GcQXIM",
expirationTime: null,
keys: {
auth: "dDUqtFo26ekGEAmNzvmJAw",
p256dh:
"BHIT3J6xSRiHfz0m-QRHagDThiOZGVIANtPzOasrOBYG0s_yUnshTVharX5dZcq8GA5OkyMm3mqmA7_o_lFR4WE",
},
}
webPush.setVapidDetails(
"https://tackupnow.com",
"BKc02U2-z7PkTbYgYLlxELWqzTVE631fs4IPuMLbxY_rxdo9VaduthqwkPOiblwjETl99uXes2Nc9EtPbS5x4uA",
"Xmv5Pc4mqr138V3sCxXq7UmsbL5UgSOY43UuJ50nxPw"
)
webPush
.sendNotification(subscription, "Hi what's up?", {})
.then((x) => console.log("It sent", x))
.catch((error) => console.log("It did not send", error))