// @vitest-environment happy-dom import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import FeedStatusRibbon from '../../src/components/posts/FeedStatusRibbon.vue' import { useSourcesStore } from '../../src/stores/sources.js' import { mountWithStore } from '../support/mountComponent.js' // #387 B3. This ribbon is the ONLY place phase A's work reaches someone who // wasn't already looking for it, so what it does and does not say is the whole // feature. These pin: it stays silent when it has nothing true to report, it // keeps "failing" and "no access" as separate claims, and it never renders a // zero — a "0 failing" on the front door is noise that trains you to ignore // the line, which is exactly what would hide the real number later. const mountWith = (status) => mountWithStore(FeedStatusRibbon, () => { useSourcesStore().scheduleStatus = status }) describe('FeedStatusRibbon', () => { beforeEach(() => { // The component fetches on mount and swallows failures by design; stub it // so the assertions are about the seeded state, not a race with the call. globalThis.fetch = vi.fn(async () => { throw new Error('offline') }) }) afterEach(() => vi.restoreAllMocks()) it('renders nothing before it has a status', () => { const w = mountWith(null) expect(w.find('.fc-ribbon').exists()).toBe(false) }) it('a healthy instance is one quiet line, with no zeroes', () => { const w = mountWith({ last_tick_at: new Date().toISOString(), failing_sources: 0, no_access_sources: 0, }) expect(w.find('.fc-ribbon').exists()).toBe(true) expect(w.text()).toContain('Checked') // Assert on the claims, not on the digit — a just-now timestamp can render // its own "0 minutes ago" and a substring check would catch that instead. expect(w.text()).not.toContain('failing') expect(w.text()).not.toContain("can't see") expect(w.find('.fc-ribbon__item--err').exists()).toBe(false) expect(w.find('.fc-ribbon__item--gated').exists()).toBe(false) }) it('reports failing and no-access as two separate claims', () => { const w = mountWith({ last_tick_at: new Date().toISOString(), failing_sources: 2, no_access_sources: 5, }) expect(w.find('.fc-ribbon__item--err').text()).toContain('2 sources are failing') expect(w.find('.fc-ribbon__item--gated').text()).toContain("5 you can't see") }) it('no-access alone does not light the failing item', () => { // The whole point of phase A: a paywalled creator is not a broken one. const w = mountWith({ last_tick_at: new Date().toISOString(), failing_sources: 0, no_access_sources: 3, }) expect(w.find('.fc-ribbon__item--err').exists()).toBe(false) expect(w.find('.fc-ribbon__item--gated').exists()).toBe(true) }) it('says "never" rather than a blank when nothing has ever run', () => { const w = mountWith({ last_tick_at: null, failing_sources: 0, no_access_sources: 0 }) expect(w.text()).toContain('never') }) it('singularises one failing source', () => { const w = mountWith({ last_tick_at: new Date().toISOString(), failing_sources: 1, no_access_sources: 0, }) expect(w.find('.fc-ribbon__item--err').text()).toContain('1 source is failing') }) })