forked from Qortal/q-blog
102 lines
3.2 KiB
TypeScript
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');
|
|
});
|
|
});
|