feat: add responsive brand icon assets

This commit is contained in:
SimpleTest 2026-07-19 22:41:06 +03:00
parent c0d7bdf53c
commit c28c9a315f
31 changed files with 290 additions and 31 deletions

View File

@ -11,9 +11,10 @@
android:allowBackup="false" android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="false" android:fullBackupContent="false"
android:icon="@drawable/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.WhoNeedHelp" android:theme="@style/Theme.WhoNeedHelp"
android:usesCleartextTraffic="${usesCleartextTraffic}"> android:usesCleartextTraffic="${usesCleartextTraffic}">

View File

@ -209,7 +209,7 @@ public final class TrackingService extends Service implements LocationListener {
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
); );
Notification.Action stopAction = new Notification.Action.Builder( Notification.Action stopAction = new Notification.Action.Builder(
Icon.createWithResource(this, R.drawable.ic_launcher), Icon.createWithResource(this, R.drawable.ic_notification),
getString(R.string.tracking_stop_action), getString(R.string.tracking_stop_action),
stopPendingIntent stopPendingIntent
).build(); ).build();
@ -220,7 +220,7 @@ public final class TrackingService extends Service implements LocationListener {
: new Notification.Builder(this); : new Notification.Builder(this);
return builder return builder
.setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title) .setContentTitle(title)
.setContentText(text) .setContentText(text)
.setContentIntent(openPendingIntent) .setContentIntent(openPendingIntent)

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#14532D"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M47,22h14v25h25v14h-25v25h-14v-25h-25v-14h25z" />
</vector>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="512"
android:viewportHeight="512">
<group
android:pivotX="256"
android:pivotY="256"
android:scaleX="0.62"
android:scaleY="0.62">
<path
android:fillColor="#047B68"
android:pathData="M256,12C122,12 22,112 22,236c0,117 96,207 234,270 138,-63 234,-153 234,-270C490,112 390,12 256,12Z" />
<path
android:fillColor="#B83B12"
android:pathData="M425,176c42,91 10,189 -57,250 -32,29 -70,56 -112,80V282c62,-11 123,-51 169,-106Z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M256,55c-94,0 -171,53 -171,118 0,47 48,65 119,69 19,1 25,19 10,31 -17,13 -36,20 -53,26 -16,6 -18,26 -4,37 20,16 45,19 67,16l32,36 32,-36c22,3 47,0 67,-16 14,-11 12,-31 -4,-37 -17,-6 -36,-13 -53,-26 -15,-12 -9,-30 10,-31 71,-4 119,-22 119,-69 0,-65 -77,-118 -171,-118Z" />
<path
android:fillColor="#047B68"
android:pathData="M153,136a34,34 0,1 0,0 68a34,34 0,1 0,0 -68Z" />
<path
android:fillColor="#B83B12"
android:pathData="M359,136a34,34 0,1 0,0 68a34,34 0,1 0,0 -68Z" />
<path
android:fillColor="#B83B12"
android:pathData="M256,252c5,20 16,31 36,36 -20,5 -31,16 -36,36 -5,-20 -16,-31 -36,-36 20,-5 31,-16 36,-36Z" />
</group>
</vector>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="512"
android:viewportHeight="512">
<group
android:pivotX="256"
android:pivotY="256"
android:scaleX="0.62"
android:scaleY="0.62">
<path
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:pathData="M256,12C122,12 22,112 22,236c0,117 96,207 234,270 138,-63 234,-153 234,-270C490,112 390,12 256,12ZM256,55c-94,0 -171,53 -171,118 0,47 48,65 119,69 19,1 25,19 10,31 -17,13 -36,20 -53,26 -16,6 -18,26 -4,37 20,16 45,19 67,16l32,36 32,-36c22,3 47,0 67,-16 14,-11 12,-31 -4,-37 -17,-6 -36,-13 -53,-26 -15,-12 -9,-30 10,-31 71,-4 119,-22 119,-69 0,-65 -77,-118 -171,-118ZM153,136a34,34 0,1 0,0 68a34,34 0,1 0,0 -68ZM359,136a34,34 0,1 0,0 68a34,34 0,1 0,0 -68Z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M256,252c5,20 16,31 36,36 -20,5 -31,16 -36,36 -5,-20 -16,-31 -36,-36 20,-5 31,-16 36,-36Z" />
</group>
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:fillType="evenOdd"
android:pathData="M12,1.5C6.5,1.5 2.5,5.6 2.5,10.6c0,4.8 3.9,8.4 9.5,11.9 5.6,-3.5 9.5,-7.1 9.5,-11.9C21.5,5.6 17.5,1.5 12,1.5ZM8,6.7a1.5,1.5 0,1 0,0 3a1.5,1.5 0,1 0,0 -3ZM16,6.7a1.5,1.5 0,1 0,0 3a1.5,1.5 0,1 0,0 -3ZM12,10.5c0.3,1.1 0.9,1.7 2,2 -1.1,0.3 -1.7,0.9 -2,2 -0.3,-1.1 -0.9,-1.7 -2,-2 1.1,-0.3 1.7,-0.9 2,-2Z" />
</vector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#F7F7F5</color>
</resources>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -42,9 +42,13 @@ defmodule WhoNeedHelpWeb.Layouts do
class="flex min-w-0 items-center gap-3" class="flex min-w-0 items-center gap-3"
aria-label={gettext("Who Need Help home")} aria-label={gettext("Who Need Help home")}
> >
<span class="grid size-9 shrink-0 place-items-center rounded-xl bg-success text-xl text-success-content"> <img
+ src={~p"/images/logo.svg"}
</span> width="36"
height="36"
alt=""
class="size-9 shrink-0"
/>
<span class="truncate font-black tracking-tight">Who Need Help</span> <span class="truncate font-black tracking-tight">Who Need Help</span>
</a> </a>

View File

@ -9,9 +9,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} /> <meta name="csrf-token" content={get_csrf_token()} />
<meta name="theme-color" content="#16a34a" /> <meta name="theme-color" content="#16a34a" />
<meta name="color-scheme" content="light dark" />
<.live_title default="Who Need Help" suffix=" · Who Need Help" phx-no-format>{assigns[:page_title]}</.live_title> <.live_title default="Who Need Help" suffix=" · Who Need Help" phx-no-format>{assigns[:page_title]}</.live_title>
<link rel="manifest" href={~p"/manifest.webmanifest"} /> <link rel="manifest" href={~p"/manifest.webmanifest"} />
<link rel="icon" type="image/svg+xml" href={~p"/images/logo.svg"} /> <link rel="icon" type="image/svg+xml" sizes="any" href={~p"/images/logo.svg"} />
<link rel="icon" type="image/png" sizes="48x48" href={~p"/images/favicon-48.png"} />
<link rel="apple-touch-icon" sizes="180x180" href={~p"/images/apple-touch-icon.png"} />
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} /> <link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"}> <script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"}>
</script> </script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-labelledby="title">
<title id="title">Who Need Help</title>
<path
fill="#000"
fill-rule="evenodd"
d="M256 12C122 12 22 112 22 236c0 117 96 207 234 270 138-63 234-153 234-270C490 112 390 12 256 12Zm0 43c-94 0-171 53-171 118 0 47 48 65 119 69 19 1 25 19 10 31-17 13-36 20-53 26-16 6-18 26-4 37 20 16 45 19 67 16l32 36 32-36c22 3 47 0 67-16 14-11 12-31-4-37-17-6-36-13-53-26-15-12-9-30 10-31 71-4 119-22 119-69 0-65-77-118-171-118Zm-103 81a34 34 0 1 0 0 68 34 34 0 0 0 0-68Zm206 0a34 34 0 1 0 0 68 34 34 0 0 0 0-68Z"
/>
<path
fill="#000"
d="M256 252c5 20 16 31 36 36-20 5-31 16-36 36-5-20-16-31-36-36 20-5 31-16 36-36Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 735 B

View File

@ -1,6 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 71 48" fill="currentColor" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-labelledby="title">
<title id="title">Who Need Help</title>
<path <path
d="m26.371 33.477-.552-.1c-3.92-.729-6.397-3.1-7.57-6.829-.733-2.324.597-4.035 3.035-4.148 1.995-.092 3.362 1.055 4.57 2.39 1.557 1.72 2.984 3.558 4.514 5.305 2.202 2.515 4.797 4.134 8.347 3.634 3.183-.448 5.958-1.725 8.371-3.828.363-.316.761-.592 1.144-.886l-.241-.284c-2.027.63-4.093.841-6.205.735-3.195-.16-6.24-.828-8.964-2.582-2.486-1.601-4.319-3.746-5.19-6.611-.704-2.315.736-3.934 3.135-3.6.948.133 1.746.56 2.463 1.165.583.493 1.143 1.015 1.738 1.493 2.8 2.25 6.712 2.375 10.265-.068-5.842-.026-9.817-3.24-13.308-7.313-1.366-1.594-2.7-3.216-4.095-4.785-2.698-3.036-5.692-5.71-9.79-6.623C12.8-.623 7.745.14 2.893 2.361 1.926 2.804.997 3.319 0 4.149c.494 0 .763.006 1.032 0 2.446-.064 4.28 1.023 5.602 3.024.962 1.457 1.415 3.104 1.761 4.798.513 2.515.247 5.078.544 7.605.761 6.494 4.08 11.026 10.26 13.346 2.267.852 4.591 1.135 7.172.555ZM10.751 3.852c-.976.246-1.756-.148-2.56-.962 1.377-.343 2.592-.476 3.897-.528-.107.848-.607 1.306-1.336 1.49Zm32.002 37.924c-.085-.626-.62-.901-1.04-1.228-1.857-1.446-4.03-1.958-6.333-2-1.375-.026-2.735-.128-4.031-.61-.595-.22-1.26-.505-1.244-1.272.015-.78.693-1 1.31-1.184.505-.15 1.026-.247 1.6-.382-1.46-.936-2.886-1.065-4.787-.3-2.993 1.202-5.943 1.06-8.926-.017-1.684-.608-3.179-1.563-4.735-2.408l-.077.057c1.29 2.115 3.034 3.817 5.004 5.271 3.793 2.8 7.936 4.471 12.784 3.73A66.714 66.714 0 0 1 37 40.877c1.98-.16 3.866.398 5.753.899Zm-9.14-30.345c-.105-.076-.206-.266-.42-.069 1.745 2.36 3.985 4.098 6.683 5.193 4.354 1.767 8.773 2.07 13.293.51 3.51-1.21 6.033-.028 7.343 3.38.19-3.955-2.137-6.837-5.843-7.401-2.084-.318-4.01.373-5.962.94-5.434 1.575-10.485.798-15.094-2.553Zm27.085 15.425c.708.059 1.416.123 2.124.185-1.6-1.405-3.55-1.517-5.523-1.404-3.003.17-5.167 1.903-7.14 3.972-1.739 1.824-3.31 3.87-5.903 4.604.043.078.054.117.066.117.35.005.699.021 1.047.005 3.768-.17 7.317-.965 10.14-3.7.89-.86 1.685-1.817 2.544-2.71.716-.746 1.584-1.159 2.645-1.07Zm-8.753-4.67c-2.812.246-5.254 1.409-7.548 2.943-1.766 1.18-3.654 1.738-5.776 1.37-.374-.066-.75-.114-1.124-.17l-.013.156c.135.07.265.151.405.207.354.14.702.308 1.07.395 4.083.971 7.992.474 11.516-1.803 2.221-1.435 4.521-1.707 7.013-1.336.252.038.503.083.756.107.234.022.479.255.795.003-2.179-1.574-4.526-2.096-7.094-1.872Zm-10.049-9.544c1.475.051 2.943-.142 4.486-1.059-.452.04-.643.04-.827.076-2.126.424-4.033-.04-5.733-1.383-.623-.493-1.257-.974-1.889-1.457-2.503-1.914-5.374-2.555-8.514-2.5.05.154.054.26.108.315 3.417 3.455 7.371 5.836 12.369 6.008Zm24.727 17.731c-2.114-2.097-4.952-2.367-7.578-.537 1.738.078 3.043.632 4.101 1.728a13 13 0 0 0 1.182 1.106c1.6 1.29 4.311 1.352 5.896.155-1.861-.726-1.861-.726-3.601-2.452Zm-21.058 16.06c-1.858-3.46-4.981-4.24-8.59-4.008a9.667 9.667 0 0 1 2.977 1.39c.84.586 1.547 1.311 2.243 2.055 1.38 1.473 3.534 2.376 4.962 2.07-.656-.412-1.238-.848-1.592-1.507Zl-.006.006-.036-.004.021.018.012.053Za.127.127 0 0 0 .015.043c.005.008.038 0 .058-.002Zl-.008.01.005.026.024.014Z" fill="#047B68"
fill="#FD4F00" d="M256 12C122 12 22 112 22 236c0 117 96 207 234 270 138-63 234-153 234-270C490 112 390 12 256 12Z"
/>
<path
fill="#B83B12"
d="M425 176c42 91 10 189-57 250-32 29-70 56-112 80V282c62-11 123-51 169-106Z"
/>
<path
fill="#FFF"
d="M256 55c-94 0-171 53-171 118 0 47 48 65 119 69 19 1 25 19 10 31-17 13-36 20-53 26-16 6-18 26-4 37 20 16 45 19 67 16l32 36 32-36c22 3 47 0 67-16 14-11 12-31-4-37-17-6-36-13-53-26-15-12-9-30 10-31 71-4 119-22 119-69 0-65-77-118-171-118Z"
/>
<circle cx="153" cy="170" r="34" fill="#047B68" />
<circle cx="359" cy="170" r="34" fill="#B83B12" />
<path
fill="#B83B12"
d="M256 252c5 20 16 31 36 36-20 5-31 16-36 36-5-20-16-31-36-36 20-5 31-16 36-36Z"
/> />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -3,16 +3,47 @@
"short_name": "Who Need Help", "short_name": "Who Need Help",
"description": "Fast, local, voluntary mutual aid.", "description": "Fast, local, voluntary mutual aid.",
"start_url": "/", "start_url": "/",
"id": "/",
"scope": "/", "scope": "/",
"display": "standalone", "display": "standalone",
"background_color": "#ffffff", "background_color": "#ffffff",
"theme_color": "#16a34a", "theme_color": "#047b68",
"icons": [ "icons": [
{ {
"src": "/images/logo.svg", "src": "/images/logo.svg",
"sizes": "any", "sizes": "any",
"type": "image/svg+xml", "type": "image/svg+xml",
"purpose": "any maskable" "purpose": "any"
},
{
"src": "/images/pwa-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/images/pwa-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/images/pwa-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/images/pwa-maskable-1024.png",
"sizes": "1024x1024",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/images/logo-monochrome.svg",
"sizes": "any",
"type": "image/svg+xml",
"purpose": "monochrome"
} }
] ]
} }

View File

@ -1,15 +1,23 @@
const CACHE = "who-need-help-static-v1" const CACHE = "who-need-help-static-v2"
const SHELL = ["/assets/css/app.css", "/assets/js/app.js", "/images/logo.svg"] const SHELL = [
"/assets/css/app.css",
"/assets/js/app.js",
"/images/logo.svg",
"/images/pwa-192.png",
"/images/pwa-512.png"
]
self.addEventListener("install", event => { self.addEventListener("install", event => {
event.waitUntil(caches.open(CACHE).then(cache => cache.addAll(SHELL))) event.waitUntil(
caches.open(CACHE).then(cache => cache.addAll(SHELL)).then(() => self.skipWaiting())
)
}) })
self.addEventListener("activate", event => { self.addEventListener("activate", event => {
event.waitUntil( event.waitUntil(
caches.keys().then(keys => caches.keys().then(keys =>
Promise.all(keys.filter(key => key !== CACHE).map(key => caches.delete(key))) Promise.all(keys.filter(key => key !== CACHE).map(key => caches.delete(key)))
) ).then(() => self.clients.claim())
) )
}) })

View File

@ -0,0 +1,73 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
SOURCE="$ROOT/priv/static/images/logo.svg"
TMP_DIR=$(mktemp -d)
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
for command_name in inkscape magick; do
if ! command -v "$command_name" >/dev/null 2>&1; then
echo "Required command is unavailable: $command_name" >&2
exit 1
fi
done
render_square() {
local size=$1
local artwork_size=$2
local destination=$3
magick \
-size "${size}x${size}" \
xc:'#F7F7F5' \
\( "$TMP_DIR/mark-1024.png" -resize "${artwork_size}x${artwork_size}" \) \
-gravity center \
-composite \
-alpha on \
-depth 8 \
-strip \
"PNG32:$destination"
}
mkdir -p \
"$ROOT/android/store-assets" \
"$ROOT/android/app/src/main/res/mipmap-mdpi" \
"$ROOT/android/app/src/main/res/mipmap-hdpi" \
"$ROOT/android/app/src/main/res/mipmap-xhdpi" \
"$ROOT/android/app/src/main/res/mipmap-xxhdpi" \
"$ROOT/android/app/src/main/res/mipmap-xxxhdpi"
inkscape \
"$SOURCE" \
--export-type=png \
--export-filename="$TMP_DIR/mark-1024.png" \
--export-width=1024 \
--export-height=1024
magick "$TMP_DIR/mark-1024.png" -resize 48x48 -alpha on -depth 8 -strip \
"PNG32:$ROOT/priv/static/images/favicon-48.png"
magick "$TMP_DIR/mark-1024.png" -resize 192x192 -alpha on -depth 8 -strip \
"PNG32:$ROOT/priv/static/images/pwa-192.png"
magick "$TMP_DIR/mark-1024.png" -resize 512x512 -alpha on -depth 8 -strip \
"PNG32:$ROOT/priv/static/images/pwa-512.png"
magick "$TMP_DIR/mark-1024.png" -define icon:auto-resize=48,32,16 \
"$ROOT/priv/static/favicon.ico"
render_square 512 300 "$ROOT/priv/static/images/pwa-maskable-512.png"
render_square 1024 600 "$ROOT/priv/static/images/pwa-maskable-1024.png"
render_square 180 106 "$ROOT/priv/static/images/apple-touch-icon.png"
render_square 1024 600 "$ROOT/priv/static/images/app-icon-1024.png"
render_square 512 300 "$ROOT/android/store-assets/icon-512.png"
render_square 48 28 "$ROOT/android/app/src/main/res/mipmap-mdpi/ic_launcher.png"
render_square 72 42 "$ROOT/android/app/src/main/res/mipmap-hdpi/ic_launcher.png"
render_square 96 56 "$ROOT/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png"
render_square 144 84 "$ROOT/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png"
render_square 192 112 "$ROOT/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png"
echo "Generated web, PWA, store, and legacy Android brand assets from $SOURCE"

View File

@ -17,6 +17,15 @@ defmodule WhoNeedHelpWeb.PageControllerTest do
1 1
assert Enum.empty?(LazyHTML.query(document, "body > nav[aria-label='Account and language']")) assert Enum.empty?(LazyHTML.query(document, "body > nav[aria-label='Account and language']"))
assert Enum.count(LazyHTML.query(document, "header img[src='/images/logo.svg'][alt='']")) == 1
assert Enum.count(LazyHTML.query(document, "head link[rel='icon'][href='/images/logo.svg']")) ==
1
assert Enum.count(
LazyHTML.query(document, "head link[rel='apple-touch-icon'][sizes='180x180']")
) == 1
end end
test "GET / selects Russian locale", %{conn: conn} do test "GET / selects Russian locale", %{conn: conn} do
@ -40,11 +49,50 @@ defmodule WhoNeedHelpWeb.PageControllerTest do
test "GET /manifest.webmanifest", %{conn: conn} do test "GET /manifest.webmanifest", %{conn: conn} do
conn = get(conn, "/manifest.webmanifest") conn = get(conn, "/manifest.webmanifest")
assert response(conn, 200) =~ ~s("short_name": "Who Need Help") manifest = conn |> response(200) |> JSON.decode!()
assert manifest["short_name"] == "Who Need Help"
assert manifest["id"] == "/"
assert Enum.any?(manifest["icons"], fn icon ->
icon["sizes"] == "192x192" and icon["purpose"] == "any"
end)
assert Enum.any?(manifest["icons"], fn icon ->
icon["sizes"] == "512x512" and icon["purpose"] == "any"
end)
assert Enum.any?(manifest["icons"], fn icon ->
icon["sizes"] == "1024x1024" and icon["purpose"] == "maskable"
end)
assert Enum.any?(manifest["icons"], fn icon ->
icon["type"] == "image/svg+xml" and icon["purpose"] == "monochrome"
end)
end end
test "GET /sw.js", %{conn: conn} do test "GET /sw.js", %{conn: conn} do
conn = get(conn, "/sw.js") conn = get(conn, "/sw.js")
assert response(conn, 200) =~ ~s(const CACHE = "who-need-help-static-v1") body = response(conn, 200)
assert body =~ ~s(const CACHE = "who-need-help-static-v2")
assert body =~ "self.skipWaiting()"
assert body =~ "self.clients.claim()"
end
test "brand raster fallbacks are served", %{conn: conn} do
for path <- [
"/images/favicon-48.png",
"/images/pwa-192.png",
"/images/pwa-512.png",
"/images/pwa-maskable-512.png",
"/images/pwa-maskable-1024.png",
"/images/apple-touch-icon.png"
] do
response = conn |> recycle() |> get(path)
assert response.status == 200
assert get_resp_header(response, "content-type") == ["image/png"]
end
end end
end end