7c48bab1f2
Adds co-located unit tests for ten targets (client → vitest *.test.ts(x), server → jest *.spec.ts), plus minimal behavior-preserving extractions/exports where the issue required a pure function to test: - encode-wav: WAV header + PCM16 clamping - editor-ext embed-provider / utils (sanitizeUrl, isInternalFileUrl) / indent (export clampIndent) - label.dto @Matches regex - move-page.dto vs generateJitteredKeyBetween parity (bug locked via test.failing) - new-note-button canCreatePage (extracted to can-create-page.ts) - history-editor diff (extracted pure computeHistoryDiff into history-diff.ts) - notification getTypesForTab + repo contract (direct-tab divergence locked via test.failing) - search buildTsQuery (extracted + sanitizes operator inputs so adversarial queries no longer risk a to_tsquery 500) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
3.1 KiB
TypeScript
78 lines
3.1 KiB
TypeScript
import {
|
|
NotificationType,
|
|
DIRECT_NOTIFICATION_TYPES,
|
|
UPDATES_NOTIFICATION_TYPES,
|
|
getTypesForTab,
|
|
} from './notification.constants';
|
|
|
|
// Contract tests for `getTypesForTab` (notification.constants.ts), which maps a
|
|
// notification tab to the set of notification types it should contain.
|
|
// - 'direct' -> a 5-type whitelist (mentions / comments / permission grants)
|
|
// - 'updates' -> exactly [PAGE_UPDATED]
|
|
// - 'all' -> undefined (no type filter)
|
|
|
|
describe('getTypesForTab', () => {
|
|
it("returns exactly the 5 whitelisted types for 'direct'", () => {
|
|
expect(getTypesForTab('direct')).toEqual([
|
|
NotificationType.COMMENT_USER_MENTION,
|
|
NotificationType.COMMENT_CREATED,
|
|
NotificationType.COMMENT_RESOLVED,
|
|
NotificationType.PAGE_USER_MENTION,
|
|
NotificationType.PAGE_PERMISSION_GRANTED,
|
|
]);
|
|
expect(getTypesForTab('direct')).toHaveLength(5);
|
|
expect(getTypesForTab('direct')).toBe(DIRECT_NOTIFICATION_TYPES);
|
|
});
|
|
|
|
it("returns [PAGE_UPDATED] for 'updates'", () => {
|
|
expect(getTypesForTab('updates')).toEqual([NotificationType.PAGE_UPDATED]);
|
|
expect(getTypesForTab('updates')).toBe(UPDATES_NOTIFICATION_TYPES);
|
|
});
|
|
|
|
it("returns undefined (no filter) for 'all'", () => {
|
|
expect(getTypesForTab('all')).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
// CONTRACT vs the repository query (notification.repo.ts ~line 57):
|
|
// direct -> WHERE type != PAGE_UPDATED
|
|
// updates -> WHERE type = PAGE_UPDATED
|
|
//
|
|
// For 'updates' the whitelist and the SQL agree exactly. For 'direct' they
|
|
// DIVERGE: the whitelist is a positive 5-type allow-list, but `type != PAGE_UPDATED`
|
|
// returns EVERY non-PAGE_UPDATED type — including verification/approval types that
|
|
// are NOT in the whitelist. So the repo would surface notifications the 'direct'
|
|
// tab is not supposed to contain. We model the repo predicate and assert it should
|
|
// match the whitelist; the 'direct' case genuinely fails today, so it is locked with
|
|
// `test.failing` (suite stays green, flips red once repo + whitelist are reconciled).
|
|
|
|
// What the repo's WHERE clause would actually return, given all known types.
|
|
const ALL_TYPES = Object.values(NotificationType);
|
|
function repoTypesForTab(tab: 'direct' | 'updates'): string[] {
|
|
if (tab === 'direct') {
|
|
return ALL_TYPES.filter((t) => t !== NotificationType.PAGE_UPDATED);
|
|
}
|
|
return ALL_TYPES.filter((t) => t === NotificationType.PAGE_UPDATED);
|
|
}
|
|
|
|
describe('getTypesForTab vs notification.repo query', () => {
|
|
it("'updates' whitelist matches the repo's `type = PAGE_UPDATED` filter", () => {
|
|
expect(new Set(repoTypesForTab('updates'))).toEqual(
|
|
new Set(getTypesForTab('updates')),
|
|
);
|
|
});
|
|
|
|
// BUG LOCK: the 'direct' whitelist (5 types) does not match what the repo's
|
|
// `type != PAGE_UPDATED` filter returns (all non-PAGE_UPDATED types). This SHOULD
|
|
// match; it currently does not. Flips green once the repo filters by the whitelist
|
|
// (e.g. `type IN (DIRECT_NOTIFICATION_TYPES)`).
|
|
test.failing(
|
|
"'direct' whitelist matches the repo's `type != PAGE_UPDATED` filter",
|
|
() => {
|
|
expect(new Set(repoTypesForTab('direct'))).toEqual(
|
|
new Set(getTypesForTab('direct')),
|
|
);
|
|
},
|
|
);
|
|
});
|