Files

102 lines
3.2 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { canEdit, isAuthorized, selectCanonical, BlogSettings, RevisionMeta } from '@/utils/wiki';
describe('wiki auth', () => {
const owner = 'alice';
it('owner always allowed (auth + edit)', () => {
const s: BlogSettings = { wikiEnabled: false };
expect(isAuthorized(owner, s, owner)).toBe(true);
expect(canEdit(owner, s, owner)).toBe(true);
});
it('wiki disabled: only owner allowed', () => {
const s: BlogSettings = { wikiEnabled: false };
expect(isAuthorized('bob', s, owner)).toBe(false);
expect(canEdit('bob', s, owner)).toBe(false);
});
it('blacklist blocks even with whitelist', () => {
const s: BlogSettings = {
wikiEnabled: true,
editorWhitelist: ['bob'],
editorBlacklist: ['bob'],
};
expect(isAuthorized('bob', s, owner)).toBe(false);
expect(canEdit('bob', s, owner)).toBe(false);
});
it('whitelist gates when non-empty', () => {
const s: BlogSettings = { wikiEnabled: true, editorWhitelist: ['bob'] };
expect(isAuthorized('bob', s, owner)).toBe(true);
expect(isAuthorized('carol', s, owner)).toBe(false);
});
it('global allow when whitelist empty', () => {
const s: BlogSettings = { wikiEnabled: true };
expect(isAuthorized('bob', s, owner)).toBe(true);
expect(canEdit('carol', s, owner)).toBe(true);
});
});
describe('wiki canonical selection', () => {
const owner = 'alice';
const settings: BlogSettings = { wikiEnabled: true };
const revs: RevisionMeta[] = [
{
id: 'q-blog-a-post-1-1',
originPostId: 'q-blog-a-post-1-0',
lineageBlogId: 'q-blog-a',
authorName: 'bob',
updatedAt: '2025-08-20T10:00:00Z',
published: true,
},
{
id: 'q-blog-a-post-1-2',
originPostId: 'q-blog-a-post-1-0',
lineageBlogId: 'q-blog-a',
authorName: 'carol',
updatedAt: '2025-08-21T09:00:00Z',
published: true,
},
{
id: 'q-blog-a-post-1-3',
originPostId: 'q-blog-a-post-1-0',
lineageBlogId: 'q-blog-a',
authorName: owner,
updatedAt: '2025-08-21T09:00:00Z', // tie with carol; owner should win
published: true,
},
{
id: 'q-blog-a-post-1-4',
originPostId: 'q-blog-a-post-1-0',
lineageBlogId: 'q-blog-a',
authorName: 'dave',
updatedAt: '2025-08-19T00:00:00Z',
published: false, // hidden
},
];
it('picks newest; owner wins tie; filters unpublished', () => {
const sel = selectCanonical(revs, settings, owner, { expectedLineageBlogId: 'q-blog-a' });
expect(sel?.id).toBe('q-blog-a-post-1-3');
});
it('blacklist does not override owner precedence', () => {
const sel = selectCanonical(revs, { wikiEnabled: true, editorBlacklist: [owner] }, owner, {
expectedLineageBlogId: 'q-blog-a',
});
// Owner always allowed even if listed
expect(sel?.id).toBe('q-blog-a-post-1-3');
});
it('respects whitelist', () => {
const sel = selectCanonical(revs, { wikiEnabled: true, editorWhitelist: ['bob'] }, owner, {
expectedLineageBlogId: 'q-blog-a',
});
// only bob + owner allowed; bob newer than bob? owner at same time but owner wins tie → owner
expect(sel?.id).toBe('q-blog-a-post-1-3');
});
});