mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
da39b570eb
- Add Journey addon tools (list, get, entries, contributors, suggestions, available trips, create/update/delete journey and entries, reorder, contributors CRUD, preferences, share link management) - Add Journey resources (trek://journeys and sub-resources) - Split transport (flight/train/car/cruise) into dedicated tools with endpoints[] and needs_review support; narrow reservation types to non-transport only - Add airport lookup tools (search_airports, get_airport) under geo:read - Add import_places_from_url and bulk_delete_places to places tools - Add journey:read/write/share OAuth scopes (27 total) with translations across all 15 locales - Default end_day to start_day when creating a transport (MCP + UI) - Fix MCP.md drift: addon gates, removed files resource, corrected get_trip_summary description, todos under Packing addon
103 lines
3.6 KiB
TypeScript
103 lines
3.6 KiB
TypeScript
// 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 27 scopes', () => {
|
|
expect(ALL_SCOPES).toHaveLength(27)
|
|
})
|
|
|
|
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()
|
|
})
|
|
})
|