Barazo AppView backend
barazo.forum
1import { describe, it, expect } from 'vitest'
2import {
3 BARAZO_BASE_SCOPES,
4 CROSSPOST_ADDITIONAL_SCOPES,
5 BARAZO_CROSSPOST_SCOPES,
6 FALLBACK_SCOPE,
7 hasCrossPostScopes,
8 isFallbackScope,
9} from '../../../src/auth/scopes.js'
10
11describe('scope constants', () => {
12 it('BARAZO_BASE_SCOPES includes all forum collections', () => {
13 expect(BARAZO_BASE_SCOPES).toContain('repo:forum.barazo.topic.post')
14 expect(BARAZO_BASE_SCOPES).toContain('repo:forum.barazo.topic.reply')
15 expect(BARAZO_BASE_SCOPES).toContain('repo:forum.barazo.interaction.reaction')
16 expect(BARAZO_BASE_SCOPES.startsWith('atproto ')).toBe(true)
17 })
18
19 it('BARAZO_BASE_SCOPES does not include cross-post collections', () => {
20 expect(BARAZO_BASE_SCOPES).not.toContain('app.bsky.feed.post')
21 expect(BARAZO_BASE_SCOPES).not.toContain('fyi.frontpage.post')
22 })
23
24 it('CROSSPOST_ADDITIONAL_SCOPES includes Bluesky and Frontpage', () => {
25 expect(CROSSPOST_ADDITIONAL_SCOPES).toContain('repo:app.bsky.feed.post?action=create')
26 expect(CROSSPOST_ADDITIONAL_SCOPES).toContain('repo:fyi.frontpage.post?action=create')
27 expect(CROSSPOST_ADDITIONAL_SCOPES).toContain('blob:image/*')
28 })
29
30 it('BARAZO_CROSSPOST_SCOPES combines base and cross-post scopes', () => {
31 expect(BARAZO_CROSSPOST_SCOPES).toContain(BARAZO_BASE_SCOPES)
32 expect(BARAZO_CROSSPOST_SCOPES).toContain(CROSSPOST_ADDITIONAL_SCOPES)
33 })
34
35 it('FALLBACK_SCOPE is the legacy generic scope', () => {
36 expect(FALLBACK_SCOPE).toBe('atproto transition:generic')
37 })
38})
39
40describe('hasCrossPostScopes', () => {
41 it('returns true for full cross-post scopes', () => {
42 expect(hasCrossPostScopes(BARAZO_CROSSPOST_SCOPES)).toBe(true)
43 })
44
45 it('returns true for fallback scope (transition:generic)', () => {
46 expect(hasCrossPostScopes(FALLBACK_SCOPE)).toBe(true)
47 })
48
49 it('returns false for base scopes only', () => {
50 expect(hasCrossPostScopes(BARAZO_BASE_SCOPES)).toBe(false)
51 })
52
53 it('returns false when only Bluesky scope is present', () => {
54 const partial = `${BARAZO_BASE_SCOPES} repo:app.bsky.feed.post?action=create`
55 expect(hasCrossPostScopes(partial)).toBe(false)
56 })
57
58 it('returns false when only Frontpage scope is present', () => {
59 const partial = `${BARAZO_BASE_SCOPES} repo:fyi.frontpage.post?action=create`
60 expect(hasCrossPostScopes(partial)).toBe(false)
61 })
62
63 it('returns true when both cross-post scopes are present without action qualifier', () => {
64 const scope = 'atproto repo:app.bsky.feed.post repo:fyi.frontpage.post'
65 expect(hasCrossPostScopes(scope)).toBe(true)
66 })
67
68 it('returns false for empty string', () => {
69 expect(hasCrossPostScopes('')).toBe(false)
70 })
71})
72
73describe('isFallbackScope', () => {
74 it('returns true for transition:generic', () => {
75 expect(isFallbackScope(FALLBACK_SCOPE)).toBe(true)
76 })
77
78 it('returns true when transition:generic is part of larger scope', () => {
79 expect(isFallbackScope('atproto transition:generic repo:extra')).toBe(true)
80 })
81
82 it('returns false for granular scopes', () => {
83 expect(isFallbackScope(BARAZO_BASE_SCOPES)).toBe(false)
84 })
85
86 it('returns false for cross-post scopes', () => {
87 expect(isFallbackScope(BARAZO_CROSSPOST_SCOPES)).toBe(false)
88 })
89
90 it('returns false for empty string', () => {
91 expect(isFallbackScope('')).toBe(false)
92 })
93})