// FE-OAUTH-SCOPES-001 to FE-OAUTH-SCOPES-010 import { describe, it, expect } from 'vitest' import { SCOPE_GROUPS, ALL_SCOPES, SCOPE_GROUP_NAMES, getScopesByGroup } from './oauthScopes' describe('SCOPE_GROUPS', () => { it('FE-OAUTH-SCOPES-001: contains all expected scope keys', () => { const expected = [ 'trips:read', 'trips:write', 'trips:delete', 'trips:share', 'places:read', 'places:write', 'atlas:read', 'atlas:write', 'packing:read', 'packing:write', 'todos:read', 'todos:write', 'budget:read', 'budget:write', 'reservations:read', 'reservations:write', 'collab:read', 'collab:write', 'notifications:read', 'notifications:write', 'vacay:read', 'vacay:write', 'geo:read', 'weather:read', ] for (const scope of expected) { expect(SCOPE_GROUPS).toHaveProperty(scope) } }) it('FE-OAUTH-SCOPES-002: each scope entry has labelKey, descriptionKey, groupKey', () => { for (const [scope, keys] of Object.entries(SCOPE_GROUPS)) { expect(keys.labelKey, `${scope} missing labelKey`).toBeTruthy() expect(keys.descriptionKey, `${scope} missing descriptionKey`).toBeTruthy() expect(keys.groupKey, `${scope} missing groupKey`).toBeTruthy() } }) }) describe('ALL_SCOPES', () => { it('FE-OAUTH-SCOPES-003: contains exactly 24 scopes', () => { expect(ALL_SCOPES).toHaveLength(24) }) it('FE-OAUTH-SCOPES-004: matches Object.keys(SCOPE_GROUPS)', () => { expect(ALL_SCOPES).toEqual(Object.keys(SCOPE_GROUPS)) }) }) describe('SCOPE_GROUP_NAMES', () => { it('FE-OAUTH-SCOPES-005: contains no duplicate group names', () => { expect(SCOPE_GROUP_NAMES).toHaveLength(new Set(SCOPE_GROUP_NAMES).size) }) it('FE-OAUTH-SCOPES-006: contains expected groups', () => { const expected = [ 'oauth.scope.group.trips', 'oauth.scope.group.places', 'oauth.scope.group.packing', 'oauth.scope.group.budget', ] for (const g of expected) { expect(SCOPE_GROUP_NAMES).toContain(g) } }) }) describe('getScopesByGroup', () => { const identity = (key: string) => key it('FE-OAUTH-SCOPES-007: groups all scopes under the correct group key', () => { const groups = getScopesByGroup(identity) // Every scope must appear exactly once across all groups const allScopesInGroups = Object.values(groups).flat().map(s => s.scope) expect(allScopesInGroups).toHaveLength(ALL_SCOPES.length) for (const scope of ALL_SCOPES) { expect(allScopesInGroups).toContain(scope) } }) it('FE-OAUTH-SCOPES-008: each item has scope, label, description, group', () => { const groups = getScopesByGroup(identity) for (const items of Object.values(groups)) { for (const item of items) { expect(item.scope).toBeTruthy() expect(item.label).toBeTruthy() expect(item.description).toBeTruthy() expect(item.group).toBeTruthy() } } }) it('FE-OAUTH-SCOPES-009: trips group contains trips:read and trips:write', () => { const groups = getScopesByGroup(identity) const tripsGroup = groups['oauth.scope.group.trips'] expect(tripsGroup).toBeDefined() const scopeNames = tripsGroup.map(s => s.scope) expect(scopeNames).toContain('trips:read') expect(scopeNames).toContain('trips:write') }) it('FE-OAUTH-SCOPES-010: uses translated group name as key', () => { const t = (key: string) => key === 'oauth.scope.group.trips' ? 'Trips' : key const groups = getScopesByGroup(t) expect(groups['Trips']).toBeDefined() expect(groups['oauth.scope.group.trips']).toBeUndefined() }) })