deckhearth/test/pages/login.test.js
varutasu 73424aae59
Mobile scanner checkout: scan first, commit later (#157)
* Start scanner-mobile-checkout convoy for the cart-then-commit phone flow.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Ship a cart-then-commit mobile scanner so phone sessions stay on the camera.

Scan matches enqueue locally instead of auto-writing ownership, checkout happens in a sheet, and audit fixes cover stale commit detection, returnUrl open redirects, nested Escape, and ember detection chrome.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 20:20:43 -05:00

39 lines
1.4 KiB
JavaScript

// @vitest-environment jsdom
import { afterEach, describe, expect, it, vi } from 'vitest';
import { cleanup, render, screen } from '@testing-library/react';
import Login, { isSafeAppReturnUrl } from '../../pages/login.js';
vi.mock('next/router', () => ({
useRouter: () => ({ push: vi.fn() }),
}));
vi.mock('../../components/AuthLayout', () => ({
default: ({ children }) => <div>{children}</div>,
}));
vi.mock('../../components/AnimatedFireLogo', () => ({
default: () => <div aria-hidden="true">logo</div>,
}));
describe('Login page', () => {
afterEach(() => cleanup());
it('renders the sign-in CTA without dev quick-login credentials', () => {
render(<Login />);
expect(screen.getByRole('button', { name: /sign in to deck hearth/i })).toBeTruthy();
expect(screen.queryByText(/quick login/i)).toBeNull();
expect(document.body.textContent).not.toMatch(/alice123|bob123/);
});
it('accepts same-origin relative return URLs and rejects open redirects', () => {
const origin = 'https://deckhearth.com';
expect(isSafeAppReturnUrl('/scanner', origin)).toBe(true);
expect(isSafeAppReturnUrl('/login', origin)).toBe(true);
expect(isSafeAppReturnUrl('//evil.example', origin)).toBe(false);
expect(isSafeAppReturnUrl('/\\evil.example', origin)).toBe(false);
expect(isSafeAppReturnUrl('https://evil.example', origin)).toBe(false);
expect(isSafeAppReturnUrl(null, origin)).toBe(false);
});
});