Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma strängvärde byggs med konkatenering i stället för att matcha mönstret.
96 lines
4.0 KiB
TypeScript
96 lines
4.0 KiB
TypeScript
import { describe, it, expect, afterEach, vi } from 'vitest'
|
|
import { failureDescription, type ActionFailure } from '@/lib/browser/action-failure'
|
|
import { downloadFile } from '@/lib/browser/download-file'
|
|
import { postAction } from '@/lib/browser/post-action'
|
|
|
|
const originalFetch = globalThis.fetch
|
|
|
|
afterEach(() => {
|
|
globalThis.fetch = originalFetch
|
|
})
|
|
|
|
const COPY = {
|
|
timeout: 'Servern svarade inte i tid. Ingen betalfil sparades. Försök igen.',
|
|
network: 'Ingen kontakt med servern. Ingen betalfil sparades. Kontrollera din internetanslutning och försök igen.',
|
|
}
|
|
|
|
describe('failureDescription', () => {
|
|
it('names a timeout as a timeout', () => {
|
|
expect(failureDescription({ ok: false, reason: 'timeout' }, COPY)).toBe(COPY.timeout)
|
|
})
|
|
|
|
it('names a network failure as a network failure', () => {
|
|
// The union's own message for this arm is the generic "Något gick fel",
|
|
// which cannot be told apart from a server error. The caller's copy can.
|
|
const failure: ActionFailure = {
|
|
ok: false,
|
|
reason: 'network',
|
|
message: 'Något gick fel. Försök igen.',
|
|
}
|
|
expect(failureDescription(failure, COPY)).toBe(COPY.network)
|
|
expect(failureDescription(failure, COPY)).not.toBe(COPY.timeout)
|
|
})
|
|
|
|
it("keeps the server's own reason, which is more specific than any panel copy", () => {
|
|
const failure: ActionFailure = {
|
|
ok: false,
|
|
reason: 'server',
|
|
status: 400,
|
|
message: 'Bankgironummer saknas i företagsinställningar. Krävs för Bankgirot LB-fil.',
|
|
}
|
|
expect(failureDescription(failure, COPY)).toBe(
|
|
'Bankgironummer saknas i företagsinställningar. Krävs för Bankgirot LB-fil.',
|
|
)
|
|
})
|
|
|
|
it('gives the three reasons three different sentences', () => {
|
|
const said = new Set([
|
|
failureDescription({ ok: false, reason: 'timeout' }, COPY),
|
|
failureDescription({ ok: false, reason: 'network', message: 'x' }, COPY),
|
|
failureDescription({ ok: false, reason: 'server', status: 500, message: 'Serverfel' }, COPY),
|
|
])
|
|
expect(said.size).toBe(3)
|
|
})
|
|
})
|
|
|
|
describe('failure arms of downloadFile and postAction are interchangeable', () => {
|
|
// The panels feed both into one failureDescription call. If either union
|
|
// drifts, this stops compiling, which is the point.
|
|
it('accepts a downloadFile failure', async () => {
|
|
globalThis.fetch = (() => Promise.reject(new TypeError('fetch failed'))) as typeof fetch
|
|
const result = await downloadFile({ url: '/x', filename: 'f.txt', saveBlob: () => {} })
|
|
expect(result.ok).toBe(false)
|
|
if (!result.ok) expect(failureDescription(result, COPY)).toBe(COPY.network)
|
|
})
|
|
|
|
it('accepts a postAction failure', async () => {
|
|
globalThis.fetch = (() => Promise.reject(new TypeError('fetch failed'))) as typeof fetch
|
|
const result = await postAction({ url: '/x' })
|
|
expect(result.ok).toBe(false)
|
|
if (!result.ok) expect(failureDescription(result, COPY)).toBe(COPY.network)
|
|
})
|
|
|
|
it('still surfaces the salary route 400 verbatim, as the old inline handler did', async () => {
|
|
// The dominant real failure on the payment-file panels: the run is approved
|
|
// but company settings are incomplete. The route answers a plain-string
|
|
// envelope, not the structured one, and that sentence is the whole point of
|
|
// the toast: it names the field the user has to go and fill in. It must
|
|
// survive the move from the inline getErrorMessage call into downloadFile.
|
|
const message = 'Bankgironummer saknas i företagsinställningar. Krävs för Bankgirot LB-fil.'
|
|
globalThis.fetch = (() =>
|
|
Promise.resolve(
|
|
new Response(JSON.stringify({ error: message }), {
|
|
status: 400,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}),
|
|
)) as typeof fetch
|
|
const saveBlob = vi.fn()
|
|
|
|
const result = await downloadFile({ url: '/x', filename: 'lon_2026-04.txt', saveBlob })
|
|
|
|
expect(saveBlob).not.toHaveBeenCalled()
|
|
expect(result.ok).toBe(false)
|
|
if (!result.ok) expect(failureDescription(result, COPY)).toBe(message)
|
|
})
|
|
})
|