Add installation instructions for not iOS
Test / test (push) Failing after 2m12s
Details
Test / test (push) Failing after 2m12s
Details
This commit is contained in:
parent
e86534dc86
commit
c1cfdb78de
|
|
@ -7,4 +7,4 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: npm install && npm run test && npx playwright test
|
- run: npm install && npm run test && npx playwright install && npx playwright test
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
"*.spec.js"
|
"*.spec.js"
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"maxLineLength": 9999999
|
"maxLineLength": 9999
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import { usePush } from "../usePush"
|
import { usePush } from "../usePush"
|
||||||
|
import { request } from "http"
|
||||||
|
|
||||||
export default function EnableNotifications({
|
export default function EnableNotifications({
|
||||||
onSubscribe,
|
onSubscribe,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import PermissionDenied from "./PermissionDenied"
|
||||||
interface InstallPromptsProps {
|
interface InstallPromptsProps {
|
||||||
isMobileSafari: boolean
|
isMobileSafari: boolean
|
||||||
isSupported: boolean
|
isSupported: boolean
|
||||||
|
isIOS: boolean
|
||||||
notificationsEnabled: boolean
|
notificationsEnabled: boolean
|
||||||
onInstallComplete: () => void
|
onInstallComplete: () => void
|
||||||
}
|
}
|
||||||
|
|
@ -16,9 +17,10 @@ interface InstallPromptsProps {
|
||||||
export default function InstallPrompts({
|
export default function InstallPrompts({
|
||||||
isSupported,
|
isSupported,
|
||||||
isMobileSafari,
|
isMobileSafari,
|
||||||
|
isIOS,
|
||||||
onInstallComplete,
|
onInstallComplete,
|
||||||
}: InstallPromptsProps) {
|
}: InstallPromptsProps) {
|
||||||
const { step } = useInstallState({ isSupported, isMobileSafari })
|
const { step } = useInstallState({ isSupported, isMobileSafari, isIOS })
|
||||||
|
|
||||||
const steps = {
|
const steps = {
|
||||||
"open safari": <OpenSafari />,
|
"open safari": <OpenSafari />,
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,16 @@ import React from "react"
|
||||||
export default function PermissionDenied() {
|
export default function PermissionDenied() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<h1>Enable Notifications</h1>
|
||||||
<div>
|
<div>
|
||||||
<span>Tack Up Now</span> requires notifications permissions to work
|
<span className="bold">Tack Up Now</span> requires notifications
|
||||||
|
permissions to work
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div>Grant notifications permissions to use Tack Up Now</div>
|
<div>
|
||||||
|
You have denied permission to send notifications, please grant
|
||||||
|
notifications permissions to use Tack Up Now
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,11 @@ describe("root", () => {
|
||||||
path: "/",
|
path: "/",
|
||||||
meta: () => [],
|
meta: () => [],
|
||||||
links: () => [],
|
links: () => [],
|
||||||
loader: () => ({ isSupported: true, isMobileSafari: true }),
|
loader: () => ({
|
||||||
|
isSupported: true,
|
||||||
|
isMobileSafari: true,
|
||||||
|
isIOS: true,
|
||||||
|
}),
|
||||||
Component: Index,
|
Component: Index,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
|
||||||
|
|
@ -28,28 +28,25 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||||
os.name !== "iOS" ||
|
os.name !== "iOS" ||
|
||||||
versionAtLeast(coerceSemver(os.version) ?? "0.0.0", "16.4.0")
|
versionAtLeast(coerceSemver(os.version) ?? "0.0.0", "16.4.0")
|
||||||
|
|
||||||
|
const isIOS = os.name === "iOS"
|
||||||
|
|
||||||
return json({
|
return json({
|
||||||
isSupported,
|
isSupported,
|
||||||
isMobileSafari,
|
isMobileSafari,
|
||||||
name: os.name,
|
isIOS,
|
||||||
version: os.version,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
const { isSupported, isMobileSafari, name, version } =
|
const { isSupported, isMobileSafari, isIOS } = useLoaderData<typeof loader>()
|
||||||
useLoaderData<typeof loader>()
|
|
||||||
|
|
||||||
console.log(name, version)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
|
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
|
||||||
<Suspense>
|
<LandingMessage
|
||||||
<LandingMessage
|
isSupported={isSupported}
|
||||||
isSupported={isSupported}
|
isMobileSafari={isMobileSafari}
|
||||||
isMobileSafari={isMobileSafari}
|
isIOS={isIOS}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -57,11 +54,13 @@ export default function Index() {
|
||||||
function LandingMessage({
|
function LandingMessage({
|
||||||
isSupported,
|
isSupported,
|
||||||
isMobileSafari,
|
isMobileSafari,
|
||||||
|
isIOS,
|
||||||
}: {
|
}: {
|
||||||
isSupported: boolean
|
isSupported: boolean
|
||||||
isMobileSafari: boolean
|
isMobileSafari: boolean
|
||||||
|
isIOS: boolean
|
||||||
}) {
|
}) {
|
||||||
const { installed } = useInstallState({ isSupported, isMobileSafari })
|
const { installed } = useInstallState({ isSupported, isMobileSafari, isIOS })
|
||||||
|
|
||||||
const [isInstalled, setIsInstalled] = useState(installed)
|
const [isInstalled, setIsInstalled] = useState(installed)
|
||||||
|
|
||||||
|
|
@ -74,6 +73,7 @@ function LandingMessage({
|
||||||
<InstallPrompts
|
<InstallPrompts
|
||||||
isMobileSafari={isMobileSafari}
|
isMobileSafari={isMobileSafari}
|
||||||
isSupported={isSupported}
|
isSupported={isSupported}
|
||||||
|
isIOS={isIOS}
|
||||||
notificationsEnabled={false}
|
notificationsEnabled={false}
|
||||||
onInstallComplete={() => setIsInstalled(true)}
|
onInstallComplete={() => setIsInstalled(true)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@ type IOSInstallStep =
|
||||||
export default function useInstallState({
|
export default function useInstallState({
|
||||||
isSupported,
|
isSupported,
|
||||||
isMobileSafari,
|
isMobileSafari,
|
||||||
|
isIOS,
|
||||||
}: {
|
}: {
|
||||||
isSupported: boolean
|
isSupported: boolean
|
||||||
isMobileSafari: boolean
|
isMobileSafari: boolean
|
||||||
|
isIOS: boolean
|
||||||
}) {
|
}) {
|
||||||
const isClient = typeof window !== "undefined"
|
const isClient = typeof window !== "undefined"
|
||||||
|
|
||||||
|
|
@ -37,18 +39,25 @@ export default function useInstallState({
|
||||||
("standalone" in navigator && (navigator.standalone as boolean)) ||
|
("standalone" in navigator && (navigator.standalone as boolean)) ||
|
||||||
matchMedia("(dislay-mode: standalone)").matches
|
matchMedia("(dislay-mode: standalone)").matches
|
||||||
|
|
||||||
|
const iOSStates = [
|
||||||
|
state(!isMobileSafari, "open safari"),
|
||||||
|
state(!isRunningPWA, "install"),
|
||||||
|
]
|
||||||
|
|
||||||
|
const states = [
|
||||||
|
state(!isSupported, "unsupported"),
|
||||||
|
...(isIOS ? iOSStates : []),
|
||||||
|
state(permissionDenied, "permission denied"),
|
||||||
|
state(!notificationsEnabled, "enable notifications"),
|
||||||
|
]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
step: !isSupported
|
step: states.find(({ active }) => active)?.result ?? null,
|
||||||
? "unsupported"
|
|
||||||
: !isMobileSafari
|
|
||||||
? "open safari"
|
|
||||||
: !isRunningPWA && isMobileSafari
|
|
||||||
? "install"
|
|
||||||
: permissionDenied
|
|
||||||
? "permission denied"
|
|
||||||
: !notificationsEnabled
|
|
||||||
? "enable notifications"
|
|
||||||
: (null as IOSInstallStep | null),
|
|
||||||
installed: notificationsEnabled,
|
installed: notificationsEnabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const state = (active: boolean, result: IOSInstallStep) => ({
|
||||||
|
active,
|
||||||
|
result,
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,12 @@ function webkitOnly() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nonWebkitOnly() {
|
||||||
|
beforeEach(async ({ browserName }) => {
|
||||||
|
if (browserName === "webkit") skip()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
describe("when user is on iOS", () => {
|
describe("when user is on iOS", () => {
|
||||||
webkitOnly()
|
webkitOnly()
|
||||||
|
|
||||||
|
|
@ -108,7 +114,6 @@ describe("when user is on iOS", () => {
|
||||||
await page.goto("/")
|
await page.goto("/")
|
||||||
|
|
||||||
const deniedText = page.getByText(/requires notifications permissions/)
|
const deniedText = page.getByText(/requires notifications permissions/)
|
||||||
|
|
||||||
await expect(deniedText).toBeAttached()
|
await expect(deniedText).toBeAttached()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -156,10 +161,59 @@ describe("when user is on iOS", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("other browsers", () => {
|
describe("other browsers", () => {
|
||||||
describe("when notifications permissions are unknown", () => {
|
nonWebkitOnly()
|
||||||
test("prompt the user to allow notifications", async ({ page }) => {
|
|
||||||
// await page.
|
beforeEach(async ({ page }) => {
|
||||||
|
await page.route("/api/subscribe", async (route) => {
|
||||||
|
await route.fulfill()
|
||||||
})
|
})
|
||||||
|
await stubServiceWorker(page)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("prompt the user to allow notifications", async ({ page }) => {
|
||||||
|
await stubNotifications(page, { permission: "default" })
|
||||||
|
await page.goto("/")
|
||||||
|
|
||||||
|
const notificationText = page.getByText(/Enable Notifications/)
|
||||||
|
|
||||||
|
await expect(notificationText).toBeAttached()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("show tack up now when permission is granted", async ({ page }) => {
|
||||||
|
await stubNotifications(page, { permission: "granted" })
|
||||||
|
|
||||||
|
await page.goto("/")
|
||||||
|
|
||||||
|
const yourNotificationsHeading = page.getByText(/Your Notifications/)
|
||||||
|
await expect(yourNotificationsHeading).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("submit the push subscription on permission granted", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await stubNotifications(page, {
|
||||||
|
permission: "default",
|
||||||
|
requestPermissionResult: "granted",
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.goto("/")
|
||||||
|
|
||||||
|
const requestPromise = page.waitForRequest("/api/subscribe")
|
||||||
|
await page.getByText(/Enable Notifications/).click()
|
||||||
|
const request = await requestPromise
|
||||||
|
|
||||||
|
await expect(request.postDataJSON()).toEqual({ hi: "subscription" })
|
||||||
|
})
|
||||||
|
|
||||||
|
test("prompt to allow notifications if permission was denied", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await stubNotifications(page, { permission: "denied" })
|
||||||
|
|
||||||
|
await page.goto("/")
|
||||||
|
|
||||||
|
const deniedText = page.getByText(/requires notifications permissions/)
|
||||||
|
await expect(deniedText).toBeAttached()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue