Favicon, level file icons, and a feed error mark in the triangle's column
- The logo as favicon, squared up (it is 128x121), at /favicon.png and at /favicon.ico outside the auth layer, where a browser asking on its own got a 401; an apple-touch-icon on white (#32). - An item not yet downloaded had its download bar on a line of its own under the file icon, lifting the icon above its row's; the bar now sits under it without taking space (#31). - A feed error is Font Awesome's exclamation, hung in the margin where a folder's triangle is, in the same column; a folder holding a failing feed has its triangle turn red. Closes #31, #32. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1085,3 +1085,47 @@ test.describe('on a phone', () => {
|
||||
.toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
test('a file not yet downloaded has its icon in line with the rest of its row', async ({ page }) => {
|
||||
await page.locator('#feedlist .place', { hasText: 'All Subscriptions' }).click();
|
||||
await expect(page.locator('.ep .dlbar').first()).toBeAttached({ timeout: 20_000 });
|
||||
// The icon's middle against the date's, downloaded or not. The download bar used to take a
|
||||
// line of its own and lift the icon of every pending file (issue #31).
|
||||
const offsets = await page.$$eval('.ep', rows => rows.map(r => {
|
||||
const k = r.querySelector('.file .kind'), d = r.querySelector('.date');
|
||||
if (!k || !d) return null;
|
||||
const a = k.getBoundingClientRect(), b = d.getBoundingClientRect();
|
||||
return Math.round((a.top + a.height / 2) - (b.top + b.height / 2));
|
||||
}).filter(x => x !== null));
|
||||
expect(offsets.length).toBeGreaterThan(1);
|
||||
for (const o of offsets) expect(Math.abs(o)).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
test('the favicon is the logo, square, from both pages', async ({ page }) => {
|
||||
await expect(page.locator('link[rel="icon"]')).toHaveAttribute('href', '/favicon.png');
|
||||
// A browser asks for /favicon.ico on its own, signed in or not.
|
||||
for (const path of ['/favicon.ico', '/favicon.png', '/apple-touch-icon.png']) {
|
||||
const r = await page.request.get(path, { headers: { cookie: '' } });
|
||||
expect(r.status(), path).toBe(200);
|
||||
expect(r.headers()['content-type'], path).toBe('image/png');
|
||||
}
|
||||
});
|
||||
|
||||
test('a feed error is marked in the same column as the folder triangles', async ({ page }) => {
|
||||
await expect(page.locator('.feed.group .chev').first()).toBeVisible();
|
||||
if ((await page.locator('.feed.group .chev').first().getAttribute('aria-expanded')) !== 'true')
|
||||
await page.locator('.feed.group .chev').first().click();
|
||||
// Faked in the page: no fixture feed fails. A feed on its own, and one inside a folder.
|
||||
await page.evaluate(() => {
|
||||
S.feeds.find(f => f.group).last_error = 'HTTP 404';
|
||||
S.feeds.find(f => !f.group && !S.feeds.some(c => c.group === f.id)).last_error = 'timed out';
|
||||
renderFeeds();
|
||||
});
|
||||
await expect(page.locator('.ferr')).toHaveCount(2);
|
||||
await expect(page.locator('.ferr svg')).toHaveCount(2); // the icon, not a "!"
|
||||
await expect(page.locator('.chev.bad')).toHaveCount(1); // the folder holding one
|
||||
const xs = await page.$$eval('.chev, .ferr', els =>
|
||||
els.map(e => { const r = e.getBoundingClientRect(); return Math.round(r.left + r.width / 2); }));
|
||||
expect(new Set(xs).size, JSON.stringify(xs)).toBe(1);
|
||||
await page.reload(); // put the real list back
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user