egregoros compat

This commit is contained in:
Moon.eth
2026-07-29 20:59:52 +09:00
parent 081460c7f6
commit 5b7b4360d2
16 changed files with 713 additions and 137 deletions
+108
View File
@@ -0,0 +1,108 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { Session } from './session.svelte'
const SESSION_KEY = 'plspace:session'
const APP_KEY = 'plspace:oauth:apps'
function json(body: unknown, status = 200): Response {
return new Response(JSON.stringify(body), {
status,
headers: { 'Content-Type': 'application/json' },
})
}
afterEach(() => {
vi.unstubAllGlobals()
})
describe('Session Egregoros compatibility', () => {
it('persists and automatically rotates a refresh token after an expired API request', async () => {
localStorage.setItem(
SESSION_KEY,
JSON.stringify({
host: 'egregoros.example',
token: 'expired-access-token',
refreshToken: 'first-refresh-token',
}),
)
localStorage.setItem(
APP_KEY,
JSON.stringify({
'egregoros.example': {
id: 'app-1',
name: 'plspace',
client_id: 'client-id',
client_secret: 'client-secret',
redirect_uri: `${window.location.origin}${window.location.pathname}`,
plspace_redirect_uri: `${window.location.origin}${window.location.pathname}`,
},
}),
)
const verifyCalls: string[] = []
vi.stubGlobal(
'fetch',
vi.fn(async (url: string, init?: RequestInit) => {
if (url.endsWith('/api/v2/instance')) {
return json({ title: 'Egregoros', version: 'egregoros/0.1.0' })
}
if (url.endsWith('/oauth/token')) {
expect(Object.fromEntries(new URLSearchParams(String(init?.body)))).toMatchObject({
grant_type: 'refresh_token',
refresh_token: 'first-refresh-token',
})
return json({
access_token: 'fresh-access-token',
refresh_token: 'rotated-refresh-token',
token_type: 'Bearer',
scope: 'read write follow',
created_at: 123,
expires_in: 3600,
})
}
if (url.endsWith('/api/v1/accounts/verify_credentials')) {
const authorization = (init?.headers as Headers).get('Authorization') ?? ''
verifyCalls.push(authorization)
if (authorization === 'Bearer expired-access-token') {
return json({ error: 'Invalid or expired token' }, 401)
}
return json({
id: 'account-1',
username: 'alice',
acct: 'alice',
display_name: 'Alice',
note: '',
url: 'https://egregoros.example/@alice',
avatar: '',
avatar_static: '',
header: '',
header_static: '',
locked: false,
created_at: '2026-01-01T00:00:00Z',
statuses_count: 0,
followers_count: 0,
following_count: 0,
fields: [],
emojis: [],
})
}
throw new Error(`Unexpected request: ${url}`)
}),
)
const session = new Session()
await session.restore()
expect(verifyCalls).toEqual([
'Bearer expired-access-token',
'Bearer fresh-access-token',
])
expect(session.token).toBe('fresh-access-token')
expect(session.signedIn).toBe(true)
expect(JSON.parse(String(localStorage.getItem(SESSION_KEY)))).toEqual({
host: 'egregoros.example',
token: 'fresh-access-token',
refreshToken: 'rotated-refresh-token',
})
})
})