Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

105 lines
3.6 KiB
JavaScript

/**
* Tests for security/auth-validation.js
*
* window.validatePasswordViaAPI must NEVER block submit on transport failures —
* server-side validation is the source of truth, this is just a UX hint. So
* every failure mode (non-OK response, network error) should resolve to
* { valid: true, errors: [] }.
*/
import '@js/security/auth-validation.js';
describe('validatePasswordViaAPI', () => {
let originalFetch;
beforeEach(() => {
originalFetch = globalThis.fetch;
});
afterEach(() => {
globalThis.fetch = originalFetch;
});
it('returns the parsed JSON on a 200 response', async () => {
const apiResult = { valid: false, errors: ['too short', 'no digits'] };
globalThis.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve(apiResult),
});
const r = await window.validatePasswordViaAPI('weak', 'csrf-abc');
expect(r).toEqual(apiResult);
});
it('returns valid:true on 403 (CSRF expiry) so submit is not blocked', async () => {
globalThis.fetch = vi.fn().mockResolvedValue({
ok: false,
status: 403,
json: () => Promise.resolve({ error: 'CSRF expired' }),
});
const r = await window.validatePasswordViaAPI('whatever', 'stale');
expect(r).toEqual({ valid: true, errors: [] });
});
it('returns valid:true on 500 (server error)', async () => {
globalThis.fetch = vi.fn().mockResolvedValue({
ok: false,
status: 500,
json: () => Promise.resolve({}),
});
const r = await window.validatePasswordViaAPI('x', 't');
expect(r).toEqual({ valid: true, errors: [] });
});
it('returns valid:true when fetch rejects (network error)', async () => {
globalThis.fetch = vi.fn().mockRejectedValue(new Error('Network down'));
const r = await window.validatePasswordViaAPI('x', 't');
expect(r).toEqual({ valid: true, errors: [] });
});
it('POSTs FormData with password and csrf_token fields', async () => {
globalThis.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ valid: true, errors: [] }),
});
await window.validatePasswordViaAPI('hunter2', 'token-xyz');
expect(globalThis.fetch).toHaveBeenCalledTimes(1);
const [url, opts] = globalThis.fetch.mock.calls[0];
expect(url).toBe('/auth/validate-password');
expect(opts.method).toBe('POST');
expect(opts.body).toBeInstanceOf(FormData);
expect(opts.body.get('password')).toBe('hunter2');
expect(opts.body.get('csrf_token')).toBe('token-xyz');
});
it('does not set Content-Type header (FormData sets its own multipart boundary)', async () => {
globalThis.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ valid: true, errors: [] }),
});
await window.validatePasswordViaAPI('x', 't');
const [, opts] = globalThis.fetch.mock.calls[0];
// Either no headers at all, or no Content-Type override
expect(opts.headers).toBeUndefined();
});
it('returns valid:true when JSON parsing throws on a 200 response', async () => {
// If the server returns 200 but body is malformed, json() throws
// and the catch returns the safe default
globalThis.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.reject(new Error('bad JSON')),
});
const r = await window.validatePasswordViaAPI('x', 't');
expect(r).toEqual({ valid: true, errors: [] });
});
});