Something went wrong. Try again.
Browser extension: detect and subscribe to standard.site publications on ATProto
Something went wrong. Try again.
8.8 kB · 237 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238import { describe, expect, it } from 'vitest'import { statusMessagesFor } from './status'import type { PageState, PubInfo } from './types'
function pub(verified: boolean, url = 'https://blog.example.com'): PubInfo { return { uri: 'at://did:plc:abc123/site.standard.publication/3kpubrkey', did: 'did:plc:abc123', pds: 'https://pds.example.com', record: { $type: 'site.standard.publication', url, name: 'Example Blog' }, verified, }}
function state(overrides: Partial<PageState>): PageState { return { url: 'https://reader.example.com/p/x', fetchedAt: 0, ...overrides }}
const base = { httpPage: true, signedIn: false }
describe('statusMessagesFor', () => { it('explains that non-http pages are not checked, and says nothing else', () => { const msgs = statusMessagesFor({ state: undefined, httpPage: false, signedIn: false }) expect(msgs).toHaveLength(1) expect(msgs[0]?.tone).toBe('info') expect(msgs[0]?.text).toMatch(/regular web pages/) })
it('reports a failed background request as an error', () => { const msgs = statusMessagesFor({ ...base, state: undefined, requestFailed: true }) expect(msgs[0]?.tone).toBe('error') expect(msgs[0]?.text).toMatch(/Refresh/) })
it('shows checking while no state is known yet, and marks it as not an answer', () => { const checking = statusMessagesFor({ ...base, state: undefined })[0] expect(checking?.text).toMatch(/Checking/) // The popup turns this into aria-busy on the status region; a screenshot // taken while it is up is a screenshot of detection that has not finished // (scripts/capture-status-docs.mjs). expect(checking?.pending).toBe(true) })
it('marks nothing else pending: every other line is an answer', () => { const answers = [ statusMessagesFor({ ...base, state: undefined, requestFailed: true }), statusMessagesFor({ ...base, state: undefined, httpPage: false }), statusMessagesFor({ ...base, state: state({ error: 'offline' }) }), statusMessagesFor({ ...base, state: state({}), sessionExpired: true }), ] for (const msgs of answers) { expect(msgs.some((msg) => msg.pending)).toBe(false) } })
it('distinguishes offline from a record fetch failure', () => { const offline = statusMessagesFor({ ...base, state: state({ error: 'offline' }) }) expect(offline[0]?.tone).toBe('error') expect(offline[0]?.text).toMatch(/offline/)
const failed = statusMessagesFor({ ...base, state: state({ error: 'fetch-failed' }) }) expect(failed[0]?.tone).toBe('error') expect(failed[0]?.text).toMatch(/records/) expect(failed[0]?.text).not.toMatch(/offline/) })
it('states plainly when no publication was found', () => { const msgs = statusMessagesFor({ ...base, state: state({}) }) expect(msgs).toHaveLength(1) expect(msgs[0]?.tone).toBe('info') expect(msgs[0]?.text).toMatch(/No standard\.site publication/) })
it('names the publication and links its real home when the site is not the verified publisher', () => { const msgs = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(false), subscriptionRkey: null }), }) expect(msgs).toHaveLength(1) expect(msgs[0]?.tone).toBe('warn') expect(msgs[0]?.text).toMatch(/isn’t the verified publisher for “Example Blog”/) expect(msgs[0]?.link).toEqual({ text: 'blog.example.com', href: 'https://blog.example.com' }) })
it('omits the home host and link when the record url is unparseable', () => { const msgs = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(false, 'not a url'), subscriptionRkey: null }), }) expect(msgs[0]?.tone).toBe('warn') expect(msgs[0]?.link).toBeUndefined() })
it('names the blocked account as an alert, and links its profile', () => { const msgs = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: { ...pub(true), handle: 'blocked.example.com' }, blocked: true, subscriptionRkey: null, }), }) expect(msgs).toHaveLength(1) expect(msgs[0]?.tone).toBe('alert') expect(msgs[0]?.text).toMatch(/You have blocked @blocked\.example\.com/) expect(msgs[0]?.link).toEqual({ text: '@blocked.example.com', href: 'https://bsky.app/profile/blocked.example.com', }) })
it('falls back to the did when the publication has no handle', () => { const msgs = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(true), blocked: true, subscriptionRkey: null }), }) expect(msgs[0]?.text).toMatch(/You have blocked did:plc:abc123/) expect(msgs[0]?.link?.href).toBe('https://bsky.app/profile/did:plc:abc123') })
it('says nothing about blocks when the block list is unknown or the account is not blocked', () => { for (const blocked of [undefined, false]) { const msgs = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(true), blocked, subscriptionRkey: null }), }) expect(msgs).toEqual([]) } })
it('ranks the block above the unverified-publisher warning', () => { const msgs = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(false), blocked: true, subscriptionRkey: null }), }) // Not just insertion order: the block outranks it by tone as well. expect(msgs.map((m) => m.tone)).toEqual(['alert', 'warn']) expect(msgs[0]?.text).toMatch(/You have blocked/) expect(msgs[1]?.text).toMatch(/verified publisher/) })
it('warns when signed in but the subscription list could not be fetched', () => { const msgs = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(true), subscriptionRkey: undefined }), }) expect(msgs).toHaveLength(1) expect(msgs[0]?.tone).toBe('warn') expect(msgs[0]?.text).toMatch(/subscriptions/) })
it('stacks every applicable message, most severe first', () => { // Expired session (info, pushed first) + failed worker request (error): // the error must still come out on top. const msgs = statusMessagesFor({ ...base, state: undefined, requestFailed: true, sessionExpired: true, }) expect(msgs.map((m) => m.tone)).toEqual(['error', 'info'])
// Unverified publisher (warn) + unloadable subscription list (warn) keep // their insertion order within the tone. const warns = statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(false), subscriptionRkey: undefined }), }) expect(warns.map((m) => m.tone)).toEqual(['warn', 'warn']) expect(warns[0]?.text).toMatch(/verified publisher/) expect(warns[1]?.text).toMatch(/subscriptions/)
// A block (alert) sits between the two: above every warning, below a // failure of the extension itself. const ranked = statusMessagesFor({ ...base, signedIn: true, sessionExpired: true, state: state({ pub: pub(false), blocked: true, subscriptionRkey: null }), }) expect(ranked.map((m) => m.tone)).toEqual(['alert', 'warn', 'info']) })
it('stays quiet for a signed-out visitor until the Subscribe button is clicked', () => { expect(statusMessagesFor({ ...base, state: state({ pub: pub(true) }) })).toEqual([]) })
it('answers a signed-out Subscribe click with the Atmosphere sign-in pill', () => { const msgs = statusMessagesFor({ ...base, signinNudge: true, state: state({ pub: pub(true) }) }) expect(msgs).toHaveLength(1) expect(msgs[0]?.tone).toBe('warn') expect(msgs[0]?.text).toMatch(/Atmosphere account/) expect(msgs[0]?.link?.href).toMatch(/atmosphereaccount\.com/) })
it('ignores the nudge once signed in', () => { const msgs = statusMessagesFor({ ...base, signedIn: true, signinNudge: true, state: state({ pub: pub(true), subscriptionRkey: null }), }) expect(msgs).toEqual([]) })
it('shows the nudge alongside the expired-session notice, ranked above it', () => { const msgs = statusMessagesFor({ ...base, sessionExpired: true, signinNudge: true, state: state({ pub: pub(true) }), }) expect(msgs.map((m) => m.tone)).toEqual(['warn', 'info']) expect(msgs[0]?.text).toMatch(/Atmosphere account/) expect(msgs[1]?.text).toMatch(/session expired/i) })
it('stays quiet for a verified publication with known subscription state', () => { for (const rkey of ['3ksub', null] as const) { expect( statusMessagesFor({ ...base, signedIn: true, state: state({ pub: pub(true), subscriptionRkey: rkey }), }), ).toEqual([]) } })})