diff options
| author | Pawel Zelawski <pawel@pzelawski.com> | 2026-05-23 11:12:09 +0200 |
|---|---|---|
| committer | Pawel Zelawski <pawel@pzelawski.com> | 2026-05-23 11:12:09 +0200 |
| commit | 236a87f89e97b55a0c42ae4e3178da9086ebda25 (patch) | |
| tree | b1da6b01a7ce0acbeeba3d3b1b3c25b43864bcdb /tests/client | |
| parent | b4369d9d0f700869fd82f64bdc3af012a1ce5bd9 (diff) | |
| parent | 04d93d7d235d328ef40c9dae4e1f56dc8a5e893f (diff) | |
merge: bring security hardening and tests from dev
Diffstat (limited to 'tests/client')
| -rw-r--r-- | tests/client/App.test.tsx | 122 | ||||
| -rw-r--r-- | tests/client/utils.test.ts | 26 |
2 files changed, 148 insertions, 0 deletions
diff --git a/tests/client/App.test.tsx b/tests/client/App.test.tsx new file mode 100644 index 0000000..960f383 --- /dev/null +++ b/tests/client/App.test.tsx @@ -0,0 +1,122 @@ +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import App from '../../src/client/App'; + +describe('App', () => { + const fetchMock = vi.fn(); + + beforeEach(() => { + fetchMock.mockReset(); + vi.stubGlobal('fetch', fetchMock); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it('shows qr code after successful start call', async () => { + fetchMock.mockResolvedValueOnce({ + ok: true, + json: async () => ({ + sessionId: 'session-1', + qrCodeDataUrl: 'data:image/png;base64,qr', + }), + }); + + render(<App />); + fireEvent.click( + screen.getByRole('button', { name: /sign in with digi-id/i }) + ); + + await waitFor(() => { + expect( + screen.getByRole('heading', { name: /scan the qr code/i }) + ).toBeInTheDocument(); + }); + expect(screen.getByAltText('Digi-ID QR Code')).toBeInTheDocument(); + }); + + it('transitions to success after polling confirms authentication', async () => { + fetchMock + .mockResolvedValueOnce({ + ok: true, + json: async () => ({ + sessionId: 'session-2', + qrCodeDataUrl: 'data:image/png;base64,qr', + }), + }) + .mockResolvedValueOnce({ + ok: true, + json: async () => ({ + status: 'success', + address: 'D123456789', + }), + }); + + render(<App />); + fireEvent.click( + screen.getByRole('button', { name: /sign in with digi-id/i }) + ); + + await waitFor(() => { + expect( + screen.getByText(/waiting for authentication/i) + ).toBeInTheDocument(); + }); + + await waitFor( + () => { + expect( + screen.getByText(/authentication successful/i) + ).toBeInTheDocument(); + }, + { timeout: 3000 } + ); + expect(screen.getByText('D123456789')).toBeInTheDocument(); + }); + + it('shows start errors in the initial state', async () => { + fetchMock.mockResolvedValueOnce({ + ok: false, + status: 500, + json: async () => ({ message: 'Backend unavailable' }), + }); + + render(<App />); + fireEvent.click( + screen.getByRole('button', { name: /sign in with digi-id/i }) + ); + + await waitFor(() => { + expect( + screen.getByText(/failed to initiate digi-id: backend unavailable/i) + ).toBeInTheDocument(); + }); + }); + + it('can cancel waiting flow and return to initial view', async () => { + fetchMock.mockResolvedValueOnce({ + ok: true, + json: async () => ({ + sessionId: 'session-3', + qrCodeDataUrl: 'data:image/png;base64,qr', + }), + }); + + render(<App />); + fireEvent.click( + screen.getByRole('button', { name: /sign in with digi-id/i }) + ); + + await waitFor(() => { + expect( + screen.getByRole('button', { name: /cancel/i }) + ).toBeInTheDocument(); + }); + + fireEvent.click(screen.getByRole('button', { name: /cancel/i })); + expect( + screen.getByRole('button', { name: /sign in with digi-id/i }) + ).toBeInTheDocument(); + }); +}); diff --git a/tests/client/utils.test.ts b/tests/client/utils.test.ts new file mode 100644 index 0000000..946ae53 --- /dev/null +++ b/tests/client/utils.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from 'vitest'; +import { getDigiByteAddressType } from '../../src/client/utils'; + +describe('getDigiByteAddressType', () => { + it('returns unknown for empty values', () => { + expect(getDigiByteAddressType(undefined)).toBe('Unknown'); + expect(getDigiByteAddressType(null)).toBe('Unknown'); + expect(getDigiByteAddressType('')).toBe('Unknown'); + }); + + it('detects segwit addresses', () => { + expect(getDigiByteAddressType('dgb1xyz')).toBe('SegWit (Bech32)'); + }); + + it('detects script addresses', () => { + expect(getDigiByteAddressType('Sxyz')).toBe('Script (P2SH)'); + }); + + it('detects legacy addresses', () => { + expect(getDigiByteAddressType('Dxyz')).toBe('Legacy (P2PKH)'); + }); + + it('returns unknown for unsupported prefixes', () => { + expect(getDigiByteAddressType('abc123')).toBe('Unknown'); + }); +}); |
