Skip to main content

max / balanced_breakfast

5.1 KB · 121 lines History Blame Raw
1 const { describe, test } = require('node:test');
2 const assert = require('node:assert');
3 const { BB, resetMockElement } = require('./setup');
4
5 describe('BB.sources.select', () => {
6 test('sets currentSource state', async () => {
7 await BB.sources.select('s1');
8 assert.strictEqual(BB.state.currentSource, 's1');
9 });
10
11 test('resets pagination', async () => {
12 BB.state.set('currentPage', 5);
13 await BB.sources.select('s2');
14 assert.strictEqual(BB.state.currentPage, 0);
15 });
16
17 test('clears selectedItemId', async () => {
18 BB.state.set('selectedItemId', 'x');
19 await BB.sources.select('');
20 assert.strictEqual(BB.state.selectedItemId, null);
21 });
22
23 test('clears currentQueryFeed', async () => {
24 BB.state.set('currentQueryFeed', 'qf');
25 await BB.sources.select('s1');
26 assert.strictEqual(BB.state.currentQueryFeed, null);
27 });
28 });
29
30 describe('BB.sources.selectTag', () => {
31 test('sets currentTag', async () => {
32 await BB.sources.selectTag('tech');
33 assert.strictEqual(BB.state.currentTag, 'tech');
34 });
35
36 test('resets pagination', async () => {
37 BB.state.set('currentPage', 3);
38 await BB.sources.selectTag('news');
39 assert.strictEqual(BB.state.currentPage, 0);
40 });
41 });
42
43 describe('BB.sources.load', () => {
44 test('populates state', async () => {
45 await BB.sources.load();
46 assert.strictEqual(BB.state.sources.length, 2);
47 assert.deepStrictEqual(BB.state.allTags, ['news', 'tech']);
48 });
49 });
50
51 describe('BB.sources.render', () => {
52 test('renderSourceList creates correct number of source elements', () => {
53 resetMockElement('sources-list');
54 const sources = [
55 { id: 's1', name: 'Feed A', totalCount: 10, unreadCount: 3, tags: ['news'], health: 'green' },
56 { id: 's2', name: 'Feed B', totalCount: 5, unreadCount: 0, tags: [], health: 'yellow', lastError: 'timeout' },
57 { id: 's3', name: 'Feed C', totalCount: 0, unreadCount: 0, tags: [], health: 'red', lastError: 'dns fail' },
58 ];
59 BB.state.set('currentSource', '');
60 BB.state.set('queryFeeds', []);
61 BB.sources.render(sources);
62 const list = document.getElementById('sources-list');
63 // 1 All + 3 source items + 1 "+ Query Feed" button
64 assert.strictEqual(list.children.length, 5);
65 });
66
67 test('source health indicator shows correct class for yellow', () => {
68 resetMockElement('sources-list');
69 const sources = [
70 { id: 's1', name: 'Feed A', totalCount: 5, unreadCount: 0, tags: [], health: 'yellow', lastError: 'timeout' },
71 ];
72 BB.state.set('currentSource', '');
73 BB.state.set('queryFeeds', []);
74 BB.sources.render(sources);
75 const list = document.getElementById('sources-list');
76 const sourceItem = list.children[1]; // children[0] is "All", sources start at [1]
77 assert.ok(sourceItem.innerHTML.includes('data-health="yellow"'), 'Should have data-health="yellow" attribute');
78 });
79
80 test('source with unreadCount=0 shows total via all-read style (no slash, no checkmark)', () => {
81 resetMockElement('sources-list');
82 const sources = [
83 { id: 's1', name: 'Feed A', totalCount: 5, unreadCount: 0, tags: [], health: 'green' },
84 ];
85 BB.state.set('currentSource', '');
86 BB.state.set('queryFeeds', []);
87 BB.sources.render(sources);
88 const list = document.getElementById('sources-list');
89 const sourceItem = list.children[1]; // children[0] is "All"
90 assert.ok(sourceItem.innerHTML.includes('all-read'), 'Should mark the count all-read (green)');
91 assert.ok(sourceItem.innerHTML.includes('5'), 'Should show total count');
92 assert.ok(!sourceItem.innerHTML.includes('0/5'), 'Should not show 0/X format');
93 assert.ok(!sourceItem.innerHTML.includes('\u2713'), 'Should not show a checkmark');
94 });
95
96 test('source with lastError shows error text in health dot title', () => {
97 resetMockElement('sources-list');
98 const sources = [
99 { id: 's1', name: 'Feed A', totalCount: 5, unreadCount: 0, tags: [], health: 'red', lastError: 'dns fail' },
100 ];
101 BB.state.set('currentSource', '');
102 BB.state.set('queryFeeds', []);
103 BB.sources.render(sources);
104 const list = document.getElementById('sources-list');
105 const sourceItem = list.children[1]; // children[0] is "All"
106 assert.ok(sourceItem.innerHTML.includes('dns fail'), 'Should include error text');
107 });
108
109 test('empty sources array renders All item, onboarding, and + button', () => {
110 resetMockElement('sources-list');
111 BB.state.set('currentSource', '');
112 BB.state.set('queryFeeds', []);
113 BB.sources.render([]);
114 const list = document.getElementById('sources-list');
115 // All item + onboarding message + "+ Query Feed" button
116 assert.strictEqual(list.children.length, 3);
117 assert.ok(list.children[0].innerHTML.includes('All'), 'Should have All entry');
118 assert.ok(list.children[1].innerHTML.includes('Add your first feed'), 'Should have onboarding message');
119 });
120 });
121