Say what is written about a world, when asked
Every figure this map shows is a measurement or something derived from one, and it says which. What it could not do was tell you what a place is — a radius and an eccentricity do not say that Titan is the only moon with a dense atmosphere. An About control on a body's panel now fetches the Wikipedia lead, and it is labelled as what it is: prose from another site, credited and linked back, below the line where this map's own figures end. Only on the press. Nothing is fetched while a body loads, and nothing is fetched twice. Three things the encyclopedia does that had to be handled, all found by asking it rather than by guessing: It redirects, generously — "Proxima Cen b" lands on "Proxima Centauri b" and "Kepler-22 b" on "Kepler-22b" — so the catalogue's own names can be sent as they are, with no mapping table to maintain. It disambiguates. "Titan" is a list of everything called Titan, and so are "Mercury" and "Io". Wikipedia says so in the response, and this app happens to know the kind, so a disambiguation is retried as "Titan (moon)". Only in English: every wiki words its own qualifiers, and inventing a translation of one would be inventing an article title. And it rate-limits, which it did to me while I was checking the above. A refusal to answer is not an empty answer, so the two are separate outcomes: "Wikipedia has no article on this" is about the world, "Wikipedia could not be reached" is about this minute — and only the first is remembered, so a second press is allowed to try again. The extract is capped and scrollable. A lead can run a dozen lines, and this panel is anchored to the top of a viewport that may be shorter than the prose. Verified: build clean, 606/606 unit including twelve for the lookup chain, 16/16 end-to-end including three that stub the encyclopedia — this suite tests the panel, not Wikipedia — design detector clean, and the real thing exercised by hand against Earth, Titan and Proxima Cen b at three viewport sizes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jxMkwA2rbicdGxHosecYi
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
/** Every request the article service makes, whichever language it is asking in. */
|
||||
const isWikipedia = (url: URL): boolean => url.hostname.endsWith('wikipedia.org');
|
||||
|
||||
/** The article Wikipedia would send, stubbed: this suite tests the panel, not the encyclopedia. */
|
||||
const SUMMARY = {
|
||||
type: 'standard',
|
||||
titles: { normalized: 'Titan (moon)' },
|
||||
extract: 'Titan is the largest moon of Saturn.',
|
||||
content_urls: { desktop: { page: 'https://en.wikipedia.org/wiki/Titan_(moon)' } }
|
||||
};
|
||||
|
||||
test.describe('About', () => {
|
||||
test('fetches an article only when asked, and says where it came from', async ({ page }) => {
|
||||
let requests = 0;
|
||||
await page.route(isWikipedia, async (route) => {
|
||||
requests++;
|
||||
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(SUMMARY) });
|
||||
});
|
||||
|
||||
await page.goto('/body/titan');
|
||||
await expect(page.getByRole('heading', { name: 'Titan' })).toBeVisible({ timeout: 30_000 });
|
||||
|
||||
// Nothing has been fetched yet: the panel is measurements until a reader asks for prose.
|
||||
expect(requests).toBe(0);
|
||||
await expect(page.getByText('Titan is the largest moon')).toHaveCount(0);
|
||||
|
||||
await page.getByRole('button', { name: 'About', exact: true }).click();
|
||||
|
||||
await expect(page.getByText('Titan is the largest moon of Saturn.')).toBeVisible();
|
||||
const credit = page.getByRole('link', { name: /Wikipedia/ });
|
||||
await expect(credit).toHaveAttribute('href', 'https://en.wikipedia.org/wiki/Titan_(moon)');
|
||||
expect(requests).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('says nothing is written rather than leaving the press unanswered', async ({ page }) => {
|
||||
await page.route(isWikipedia, (route) => route.fulfill({ status: 404, body: '{}' }));
|
||||
|
||||
await page.goto('/body/titan');
|
||||
await expect(page.getByRole('heading', { name: 'Titan' })).toBeVisible({ timeout: 30_000 });
|
||||
await page.getByRole('button', { name: 'About', exact: true }).click();
|
||||
|
||||
await expect(page.getByText(/Wikipedia has no article on Titan/)).toBeVisible();
|
||||
});
|
||||
|
||||
test('tells being unable to ask apart from there being no answer, and offers to try again', async ({ page }) => {
|
||||
await page.route(isWikipedia, (route) => route.abort('failed'));
|
||||
|
||||
await page.goto('/body/titan');
|
||||
await expect(page.getByRole('heading', { name: 'Titan' })).toBeVisible({ timeout: 30_000 });
|
||||
await page.getByRole('button', { name: 'About', exact: true }).click();
|
||||
await expect(page.getByText(/could not be reached/)).toBeVisible();
|
||||
|
||||
// And the retry actually retries, rather than reading back a remembered failure.
|
||||
await page.unroute(isWikipedia);
|
||||
await page.route(isWikipedia, (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(SUMMARY) }));
|
||||
await page.getByRole('button', { name: 'Try again' }).click();
|
||||
|
||||
await expect(page.getByText('Titan is the largest moon of Saturn.')).toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user