fix(payment): make Swish QR code scannable by the Swish app #16
|
|
@ -112,6 +112,16 @@ describe('PaymentRedirect', () => {
|
|||
expect(wrapper.find('.payment__qr-img').exists()).toBe(true)
|
||||
})
|
||||
expect(mockToDataURL).toHaveBeenCalledTimes(1)
|
||||
// Regression guard: the QR must use a spec-compliant 4-module quiet zone
|
||||
// and pure black-on-white so the Swish app can scan it off a screen.
|
||||
expect(mockToDataURL).toHaveBeenCalledWith(
|
||||
expect.stringContaining('app.swish.nu'),
|
||||
expect.objectContaining({
|
||||
margin: 4,
|
||||
errorCorrectionLevel: 'M',
|
||||
color: { dark: '#000000', light: '#ffffff' },
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('renders a Swish payment link', async () => {
|
||||
|
|
|
|||
52
frontend/src/__tests__/payment.spec.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import { buildSwishPaymentUrl } from '@/api/payment'
|
||||
|
||||
describe('buildSwishPaymentUrl', () => {
|
||||
it('normalises Swedish national format to international', () => {
|
||||
expect(buildSwishPaymentUrl('0701234567', 49, 'test')).toContain(
|
||||
'sw=46701234567',
|
||||
)
|
||||
})
|
||||
|
||||
it('strips a leading + from international format', () => {
|
||||
const url = buildSwishPaymentUrl('+46701234567', 49, 'test')
|
||||
expect(url).toContain('sw=46701234567')
|
||||
expect(url).not.toContain('sw=%2B')
|
||||
expect(url).not.toContain('sw=+')
|
||||
})
|
||||
|
||||
it('leaves already-international numbers unchanged', () => {
|
||||
expect(buildSwishPaymentUrl('46701234567', 49, 'test')).toContain(
|
||||
'sw=46701234567',
|
||||
)
|
||||
})
|
||||
|
||||
it('leaves Swish Business numbers (123…) unchanged', () => {
|
||||
expect(buildSwishPaymentUrl('1234567890', 49, 'test')).toContain(
|
||||
'sw=1234567890',
|
||||
)
|
||||
})
|
||||
|
||||
it('strips whitespace from the number', () => {
|
||||
expect(buildSwishPaymentUrl('070 123 45 67', 49, 'test')).toContain(
|
||||
'sw=46701234567',
|
||||
)
|
||||
})
|
||||
|
||||
it('includes the amount with two decimal places in amt', () => {
|
||||
expect(buildSwishPaymentUrl('0701234567', 49, 'test')).toContain(
|
||||
'amt=49.00',
|
||||
)
|
||||
})
|
||||
|
||||
it('URL-encodes the message in the msg parameter', () => {
|
||||
const url = buildSwishPaymentUrl('0701234567', 49, 'ABC 123')
|
||||
expect(url).toContain('msg=ABC+123')
|
||||
})
|
||||
|
||||
it('uses the correct Swish C2B base URL', () => {
|
||||
expect(buildSwishPaymentUrl('0701234567', 49, 'test')).toContain(
|
||||
'https://app.swish.nu/1/p/sw/?',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
@ -48,9 +48,12 @@ export function buildSwishPaymentUrl(
|
|||
|
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
|
||||
* - 123… (Swish Business number) → unchanged
|
||||
* - 46… (already international) → unchanged
|
||||
* - 0… (Swedish national format) → 46 + rest without leading 0
|
||||
* - +46… (international with plus) → 46… (the plus is stripped first)
|
||||
|
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
|
||||
*/
|
||||
function normalizeSwishNumber(number: string): string {
|
||||
const trimmed = number.replace(/\s/g, '')
|
||||
|
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
|
||||
// Strip whitespace and a leading "+": a number stored as "+46 70 …" would
|
||||
|
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
|
||||
// otherwise miss every prefix check and leak a "+" into the `sw` param.
|
||||
|
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
|
||||
const trimmed = number.replace(/[\s+]/g, '')
|
||||
|
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
|
||||
if (trimmed.startsWith('123')) return trimmed
|
||||
if (trimmed.startsWith('46')) return trimmed
|
||||
if (trimmed.startsWith('0')) return '46' + trimmed.slice(1)
|
||||
|
|
|
|||
|
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
hermes
commented
💡 Suggestion: The comment says "a leading 💡 **Suggestion:** The comment says "a leading `+`" but `/[\s+]/g` strips *all* `+` characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Consider `number.replace(/^\+/, '').replace(/\s/g, '')` or adjusting the comment to say "any `+` characters".
hermes
commented
💡 Suggestion (low): 💡 **Suggestion (low):** `/[\s+]/g` strips *every* `+` from anywhere in the string, but the JSDoc above (L51) and the PR note describe stripping only a *leading* `+`. For valid phone numbers this is harmless (a `+` only ever appears as the international prefix), so no behaviour change — but the comment slightly overstates the intent. Either reword to "strips whitespace and any `+`", or for leading-only use `replace(/\s/g, '').replace(/^\+/, '')`. Either is fine.
|
||||
|
|
@ -27,16 +27,30 @@ onMounted(async () => {
|
|||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
const info = await fetchSwishInfo()
|
||||
swishNumber.value = info.number
|
||||
swishAmount.value = info.amount
|
||||
} catch {
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
error.value = 'Kunde inte ladda betalningsinformation. Försök igen senare.'
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
return
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
}
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
|
||||
// QR generation is best-effort and isolated from fetchSwishInfo: if the QR
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// library throws, the Swish payment link and manual fallback still render
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// instead of surfacing a misleading "could not load payment info" error.
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
try {
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
if (swishPaymentUrl.value) {
|
||||
qrDataUrl.value = await QRCode.toDataURL(swishPaymentUrl.value, {
|
||||
width: 224,
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
margin: 2,
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
color: { dark: '#111827', light: '#ffffff' },
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// Swish requires a reliably scannable black-on-white QR. The previous
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// settings (margin 2, #111827, 224px) produced a 2-module quiet zone
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// — half the QR spec minimum — which the Swish app's scanner fails to
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// read when scanning off a screen. Use the spec-compliant 4-module
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// quiet zone, pure black, and larger modules.
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
width: 288,
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
margin: 4,
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
errorCorrectionLevel: 'M',
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
color: { dark: '#000000', light: '#ffffff' },
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
})
|
||||
}
|
||||
} catch {
|
||||
error.value = 'Kunde inte ladda betalningsinformation. Försök igen senare.'
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
// ignored: payment link + manual fallback remain usable
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -239,8 +253,8 @@ async function confirmPayment() {
|
|||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
}
|
||||
|
||||
.payment__qr-img {
|
||||
width: 224px;
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
height: 224px;
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
width: 288px;
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
height: 288px;
|
||||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
border-radius: var(--radius-md);
|
||||
margin: 0 auto var(--space-sm);
|
||||
}
|
||||
|
|
|
|||
|
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
hermes
commented
💡 Suggestion: Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: 💡 **Suggestion:** Good resilience pattern — the silent catch degrades gracefully. Consider adding a test for this path: `mockToDataURL.mockRejectedValue(...)` → assert the Swish payment link and manual fallback still render.
hermes
commented
💡 Suggestion (low): Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a 💡 **Suggestion (low):** Swallowing the QR failure silently is the right UX — the Swish link + manual fallback still render. For production diagnosability, consider a `console.warn(…)` (or your error-telemetry hook) inside this catch so a recurring QR-library failure isn't invisible. No functional change either way.
|
||||
💡 Suggestion: The comment says "a leading
+" but/[\s+]/gstrips all+characters anywhere in the string, not just a leading one. This is harmless for real phone numbers, but the comment slightly misrepresents the behaviour. Considernumber.replace(/^\+/, '').replace(/\s/g, '')or adjusting the comment to say "any+characters".