Web app: foundation, brand, country pages, compare, rankings, indicators, regions, explore, changes, data, sources, methodology, API docs, admin
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
339 changed files +11,249 −329
added
apps/web/README.md
+219 −0
@@ -0,0 +1,219 @@ | ||
| 1 | +# CountryAtlas — web app (`@countryatlas/web`) | |
| 2 | + | |
| 3 | +Next.js 16.3.4 · React 19.2.8 · TypeScript strict · Tailwind v4 · own SVG chart kit (d3-geo/scale/shape only for math). | |
| 4 | +Mobile-first, editorial, provenance-first. The country is the primary unit of navigation. | |
| 5 | + | |
| 6 | +This README is the contract for whoever adds pages next (compare / rankings / indicators / regions / sources / | |
| 7 | +methodology / api / admin). Reuse what is here; do not add a second design system. | |
| 8 | + | |
| 9 | +## Run | |
| 10 | + | |
| 11 | +```bash | |
| 12 | +pnpm install # from the repo root (pnpm workspace: apps/*) | |
| 13 | +cd apps/web | |
| 14 | +pnpm dev # http://localhost:8290 — API_URL from .env.local (default http://127.0.0.1:8291) | |
| 15 | +pnpm typecheck && pnpm build && pnpm start # production: next start -p 8290 -H 0.0.0.0 | |
| 16 | +``` | |
| 17 | + | |
| 18 | +Env (see `.env.example`): `API_URL` (server-side base of the FastAPI service, loopback), `NEXT_PUBLIC_SITE_URL` | |
| 19 | +(canonical/OG/sitemap). Browser code never talks to the API host directly: `next.config.ts` rewrites | |
| 20 | +`/api/v1/:path*` → `${API_URL}/api/v1/:path*`. | |
| 21 | + | |
| 22 | +Without the real snapshot you can run the **fixture API** (synthetic, deterministic, every provenance says | |
| 23 | +"Fixture (mock data)"): `cd <repo> && .venv/bin/python apps/web/qa/mock_api.py` (port 8299) and set | |
| 24 | +`API_URL=http://127.0.0.1:8299` in `apps/web/.env.local`. Never point production at it. | |
| 25 | + | |
| 26 | +Real API once the DB exists: `cd <repo> && CA_DATA_DIR=~/countryatlas-data .venv/bin/python -m uvicorn countryatlas.api.main:app --port 8293` | |
| 27 | +then `API_URL=http://127.0.0.1:8293`. | |
| 28 | + | |
| 29 | +## QA | |
| 30 | + | |
| 31 | +```bash | |
| 32 | +node qa/screens.mjs [BASE_URL] # screenshots 320/360/375/390/414/430/1280/1440 → qa/screens/, report.json: | |
| 33 | + # overflow (scrollWidth>clientWidth), tap targets <44px, tab-bar/footer overlap, CLS, console errors | |
| 34 | +node qa/segments.mjs [BASE_URL] # viewport-sized segments (top + scroll offsets) → qa/screens/seg/ for visual review | |
| 35 | +node qa/favicons.mjs # re-rasterise src/app/icon.svg → icon.png (512) + apple-icon.png (180) | |
| 36 | +``` | |
| 37 | + | |
| 38 | +Playwright comes from `~/Desktop/uqo-eval/node_modules` (symlinked into `node_modules/playwright[-core]`; ESM ignores | |
| 39 | +`NODE_PATH`). Last run (2026-09-11, prod build, fixture API): 32 page×width renders, **0 overflow, 0 console errors, | |
| 40 | +0 layout shift**, only the sr-only skip link below 44 px. Unknown country / topic return a **true HTTP 404**. | |
| 41 | + | |
| 42 | +**Soft-404 gotcha (fixed here, keep it that way):** a `loading.tsx` that wraps a segment which calls `notFound()` | |
| 43 | +streams a 200 shell before the 404 is known. Loading files therefore live only in route groups that never contain | |
| 44 | +dynamic segments: `app/(home)/loading.tsx`, `app/countries/(list)/loading.tsx`. Do **not** add `loading.tsx` at | |
| 45 | +`app/`, `app/countries/` or inside `[slug]`. Same rule for your new dynamic routes. | |
| 46 | + | |
| 47 | +## Layout of `src/` | |
| 48 | + | |
| 49 | +``` | |
| 50 | +app/ | |
| 51 | + layout.tsx fonts, metadata template "%s — CountryAtlas", theme boot script, providers, header/footer/tab bar | |
| 52 | + globals.css design tokens (@theme inline) + chart chrome classes | |
| 53 | + (home)/page.tsx / countries/(list)/page.tsx /countries | |
| 54 | + countries/[slug]/page.tsx + [topic]/page.tsx + opengraph-image.tsx (dynamic per-country OG) | |
| 55 | + indicators/page.tsx (?topic=) indicators/[slug]/page.tsx + opengraph-image.tsx regions/page.tsx regions/[slug]/page.tsx | |
| 56 | + explore/ changes/ data/ sources/ + sources/[id]/ methodology/ api/ (developer landing, live examples) | |
| 57 | + admin/login/page.tsx + admin/actions.ts (server actions) + admin/(panel)/{layout,page,coverage,runs,issues,raw} (cookie gate) | |
| 58 | + opengraph-image.tsx twitter-image.tsx og-shared.tsx default social image (static) | |
| 59 | + icon.svg icon.png apple-icon.png manifest.ts robots.ts sitemap.ts not-found.tsx error.tsx | |
| 60 | +lib/ | |
| 61 | + api.ts server-only typed fetch: api.home() api.countries() api.country(id) api.countryTopic() api.countrySeries() | |
| 62 | + api.countryChanges/Events/Similar/Insights/Dna() api.indicatorMap() api.ranking() api.search() api.changes() | |
| 63 | + request<T>(path, query, {revalidate}) for new endpoints · ApiError · safe() · isNotBuilt() · isNotFound() | |
| 64 | + client-api.ts browser fetches to same-origin /api/v1 (search, series, similar) — keep small | |
| 65 | + api-explore.ts / client-api-explore.ts / types-explore.ts indicators, trend, series bundle, regions, changes, sources, | |
| 66 | + methodology, admin payloads (+ browser fetches for the map year slider, trend groups, compare, similar) | |
| 67 | + admin-auth.ts CA_ADMIN_TOKEN gate: constant-time compare, httpOnly cookie `ca_admin` (sha256 of the token, path /admin) | |
| 68 | + admin-api.ts X-Admin-Token fetches (no-store) to ADMIN_API_URL ?? API_URL — server components/actions only | |
| 69 | + types.ts mirror of src/countryatlas/api/schemas.py (see "Types") | |
| 70 | + format.ts formatValue / formatChange / formatPeriod / formatRank / formatDate / relativeFreshness / formatTick / compact | |
| 71 | + site.ts SITE_URL, SITE_NAME, TAGLINE, routes.* (every internal href goes through routes) | |
| 72 | + topics.ts static mirror of registry/topics.yaml (19 topics, HEADLINE_INDICATORS, HEADLINE_TOPIC) | |
| 73 | + regions.ts WB_REGIONS (7) + INCOME_GROUPS (4) with slugs/short names | |
| 74 | + map-geo.ts world-atlas 110m → Equal Earth paths (cached per process), classIndex(); iso-numeric.ts numeric→ISO3 | |
| 75 | + og.tsx Satori-safe building blocks for OG images (OgFrame, OgWordmark, OgMark, OgMeridians) | |
| 76 | + fonts.ts Inter (--font-ui) + Newsreader (--font-display) via next/font/google; fonts.system.ts = offline fallback | |
| 77 | + severity.ts 0–1 severity → high/medium/low + label | |
| 78 | +i18n/ | |
| 79 | + en.ts the dictionary (flat dotted keys) · index.ts: t(key, params), tOpt(dynamicKey, fallback), LOCALE='en-US' | |
| 80 | +components/ | |
| 81 | + brand/Logo.tsx Logo variant="full|mark|wordmark", LogoMark, Wordmark, logoMarkSvg() | |
| 82 | + layout/ SiteHeader (PRIMARY_NAV), NavLinks, MobileTabBar, SiteFooter (+ FooterCredits), ThemeToggle, | |
| 83 | + SearchProvider/useSearch/useOpenSearch, SearchTrigger (field|icon|hero), SearchDialog (lazy) | |
| 84 | + charts/ see "Chart kit" | |
| 85 | + data/ Section, Metric (+MetricGrid, payloadFor), ChangeChip, RankBadge, FreshnessBadge/StatusBadge, | |
| 86 | + TopicNav, CountryChip, DataTable, EmptyState/NotBuiltState, BottomSheet, ChangeList, | |
| 87 | + ProvenanceProvider/useProvenance/ProvenanceSheet | |
| 88 | + home/ Hero, SnapshotStrip, RegionChips, CompareTeaser (COMPARE_PRESETS), TopicsGrid, IndicatorList | |
| 89 | + countries/directory.tsx client filter/sort/A–Z directory (URL-synced) | |
| 90 | + indicators/ IndicatorDirectory (topic nav + filter), IndicatorMap (year slider → /map?year=), IndicatorTrend | |
| 91 | + (group selector → /trend), IndicatorCompare (≤ 5 countries → /series), map-geometry.ts (server) | |
| 92 | + regions/ MembersTable (sortable), MemberRanking (indicator picker → /rankings?group=), MemberMap (static SVG) | |
| 93 | + explore/ EntityPicker (typeahead country|indicator), EntityPickerNav, CopyButton/CodeBlock, PageHeader, | |
| 94 | + DownloadPicker, SimilarityPlayground | |
| 95 | + changes/changes-feed.tsx global feed: kind/indicator/region/severity filters (BottomSheet on phones), grouped by year | |
| 96 | + methodology/toc.tsx sticky TOC with IntersectionObserver highlight | |
| 97 | + admin/ AdminNav, admin-ui (AdminSection, Kv, AdminTable, Pill), CoverageTable (sortable) | |
| 98 | + country/ CountryHeader, ShareButton, SimilarPanel, KeyFacts, Timeline, CountryTopicsGrid, IndicatorRow | |
| 99 | +``` | |
| 100 | + | |
| 101 | +## Conventions (follow these on new pages) | |
| 102 | + | |
| 103 | +* **Server components fetch; client components interact.** One `await` for the primary payload, then | |
| 104 | + `Promise.all([safe(api.x()), …])` for optional panels — each tolerates failure (`null` → EmptyState). No client | |
| 105 | + fetch waterfalls. `export const revalidate = 900` on pages. | |
| 106 | +* **Errors:** `api.*` throws `ApiError`. Pattern used by every page: | |
| 107 | + ```ts | |
| 108 | + try { data = await api.thing(id) } catch (e) { if (isNotFound(e)) notFound(); if (isNotBuilt(e)) return <NotBuiltState/>; throw e } | |
| 109 | + ``` | |
| 110 | + `isNotBuilt` covers 503 ("Data not built yet") **and** an unreachable API — the site renders a calm state, never crashes. | |
| 111 | +* **Strings:** everything visible goes through `t('key')` in `src/i18n/en.ts`. Dynamic keys → `tOpt`. | |
| 112 | +* **Numbers/dates:** `lib/format.ts` only, fixed `en-US` locale (Intl hydration bug prevention). Prefer the API's | |
| 113 | + `formatted` string when present (`m.formatted ?? formatValue(m.value, m)`) so server and client agree. | |
| 114 | + `tnum` utility on columns of numbers, `pnum` on hero figures. | |
| 115 | +* **No cards.** `Section` (rule above, editorial heading, subtitle, right-side actions) + `divide-y divide-rule` lists. | |
| 116 | + Grid children that contain long text need `min-w-0` (Section already has it). | |
| 117 | +* **Never invent numbers.** Missing → `EmptyState` / "No data" (`t('common.noData')`). | |
| 118 | +* **Metadata:** `generateMetadata` uses the API; titles follow `"{Name} Data & Statistics"`; canonical via `routes.*`. | |
| 119 | +* **Provenance everywhere:** any value → `useProvenance().open(payload)`. Build payloads with `payloadFor(metricValue, | |
| 120 | + country)` or hand-roll `{ indicator: {slug,name,format,unit,…}, value: {value, period, provenance}, country }`. | |
| 121 | + Chart source lines take the same `payload` prop. | |
| 122 | +* **Touch targets ≥ 44 px on mobile** (`tap` utility or `min-h-[44px] md:min-h-[32px]`), `h-11 md:h-9` for chips. | |
| 123 | +* **Mobile:** bottom tab bar is fixed; `<body>` reserves `pb-[calc(56px+env(safe-area-inset-bottom))] md:pb-0`. | |
| 124 | + Filters on phones → `BottomSheet side="center"`. Horizontal scrollers use `scrollbar-none -mx-4 px-4`. | |
| 125 | +* **Reordering between breakpoints via CSS `order` is forbidden** for page sections (DOM order = visual order); it is | |
| 126 | + acceptable only inside a single small widget row (SimilarPanel bar). | |
| 127 | + | |
| 128 | +## Design tokens (`globals.css`) | |
| 129 | + | |
| 130 | +Raw values on `:root` / `.dark` (class toggled by `ThemeToggle`, stored in `localStorage['ca-theme']`, system default | |
| 131 | +applied before paint by `THEME_BOOT`). Tailwind reads them through `@theme inline`: | |
| 132 | + | |
| 133 | +| Token | Utility | Light / Dark | | |
| 134 | +|---|---|---| | |
| 135 | +| paper / surface / surface-2 | `bg-paper` `bg-surface` `bg-surface-2` | #fbfaf7 / #151513 · #fff / #1c1c1a · #f3f1ec / #24241f | | |
| 136 | +| ink / ink-2 / ink-3 | `text-ink*` | #1a1917 / #f2f0ea · #5c5a55 / #c9c6bd · #8a877f | | |
| 137 | +| rule / rule-strong | `border-rule` `divide-rule` | #e6e3dc / #2c2b28 · #c9c6bd / #3a3935 | | |
| 138 | +| accent / accent-soft / accent-ink | `text-accent` `bg-accent-soft` | #1c5cab / #5598e7 · #e8f0fb / #17304f | | |
| 139 | +| up / down / warn | `text-up` `text-down` | #006300 / #0ca30c · #b02a2a / #e66767 · #9a6a00 / #e0a100 | | |
| 140 | +| series-1…8 | `bg-series-1`, `seriesVar(i)` | validated dataviz palette (blue, orange, aqua, yellow, magenta, green, violet, red) | | |
| 141 | +| seq-1…7 | `seqVar(k)` | blue sequential ramp (choropleths); reversed in dark | | |
| 142 | +| nodata | `no-data-hatch` | hatched grey | | |
| 143 | + | |
| 144 | +Palette validated with the dataviz skill's `validate_palette.js` on both surfaces (adjacent ΔE ≥ 8.4, all-pairs OK for | |
| 145 | +the first 3 slots). Light-mode aqua/yellow/magenta are < 3:1 on paper → charts always ship direct labels + the table | |
| 146 | +toggle (relief rule). Positive/negative colours are never used alone: `ChangeChip` pairs them with ↑/↓ glyphs. | |
| 147 | + | |
| 148 | +Type: `display` (Newsreader) for headings, Inter for UI, scale `text-2xs … text-5xl`; utilities `eyebrow`, `hairline`, | |
| 149 | +`tap`, `tnum`, `pnum`, `scrollbar-none`, `safe-bottom`, `container-x`, `link-quiet`. Motion respects | |
| 150 | +`prefers-reduced-motion`. | |
| 151 | + | |
| 152 | +## Chart kit (`components/charts/`) | |
| 153 | + | |
| 154 | +All charts: SVG, `role="img"` + `<title>/<desc>` with an auto summary (`summary.ts`), a `ChartFrame` with source line | |
| 155 | +(`SourceLine`, clickable → provenance), accessible data-table toggle, legend only for ≥ 2 series. Colours via CSS vars | |
| 156 | +(`palette.ts`), fixed slot order — colour follows the entity, never its rank; never more than 8 series (fold/facet). | |
| 157 | +Marks per dataviz spec (`MARK`): 2 px lines, ≥ 8 px end dots with surface ring, bars ≤ 24 px with 4 px rounded end, | |
| 158 | +hairline solid grid. Points type: `SeriesPoint {period, year, value, is_forecast}` — build with | |
| 159 | +`pointsFromSpark(m.sparkline)` (API `[year,value]` pairs) or `pointsFromSeries(series.values)`. | |
| 160 | + | |
| 161 | +| Component | Kind | Notes | | |
| 162 | +|---|---|---| | |
| 163 | +| `LineChart` / `AreaChart` / `StackedArea` | client | multi-series, dashed `is_forecast`, `log`, crosshair + one tooltip for all series, end labels ≤ 4 series, auto left margin | | |
| 164 | +| `Sparkline` | server | tiny, no axes, end dot coloured by `direction` | | |
| 165 | +| `RankedBars` (+`rankedRowFromCountry`) | server, HTML | horizontal bars with flags, `highlightId`, values at the tip | | |
| 166 | +| `Scatter` | client | bubble `size`, labels for highlighted + extremes only, 24 px hit radius | | |
| 167 | +| `SlopeChart` | client | two periods, highlighted row in accent | | |
| 168 | +| `SmallMultiples` | server | grid wrapper (1 → 2 → 3/4 cols) | | |
| 169 | +| `PopulationPyramid` | server | 0–14 / 15–64 / 65+ stacked bar (ordinal ramp) | | |
| 170 | +| `DnaRadial` | server | 9 dims 0–100 fingerprint | | |
| 171 | +| `Choropleth` → `ChoroplethView` | server → client | Equal Earth 960×470, quantile classes from API `legend.breaks`, hatch for no data, hover / tap label / click → country | | |
| 172 | + | |
| 173 | +`useMeasure(defaultWidth)` gives responsive widths with a stable SSR width; reserve heights via `height`/`minHeight`. | |
| 174 | + | |
| 175 | +## Data components (`components/data/`) | |
| 176 | + | |
| 177 | +* `Metric` — label(link) + sparkline, big value (click → provenance), period, `ChangeChip`, `RankBadge`. `MetricGrid` | |
| 178 | + = 1 col ≤ 360 px, 2 on phones, 3 md, 4 xl. | |
| 179 | +* `ProvenanceSheet` is mounted once in the layout; open it from anywhere with `useProvenance().open(payload)`. | |
| 180 | +* `BottomSheet` (native `<dialog>`): `side="drawer"` (right drawer on md+), `"center"`, `"full"`; drag-down to close. | |
| 181 | +* `DataTable<T>` → definition list under `sm` (no horizontal overflow). `TopicNav` sticky under the header (52/56 px). | |
| 182 | +* `ChangeList` (feed with kind icon + severity chip) and `Timeline` (events by year) both take `ChangeItem[]`. | |
| 183 | +* `SiteFooter` renders `<FooterCredits/>` ("Made by Simon-Pierre Boucher · contact@spboucher.ai · Hosted on MacLustr") | |
| 184 | + — reuse `FooterCredits` on `/sources` and `/api`. | |
| 185 | + | |
| 186 | +## Types — `src/lib/types.ts` (extend this file) | |
| 187 | + | |
| 188 | +Aligned 2026-09-11 with `src/countryatlas/api/schemas.py`. Responses are flat with `meta`; collections are `items` | |
| 189 | +(`/countries`, `/changes`, `/events`, `/insights`), `hits` (`/search`), `peers` (`/similar`), `rows` (rankings/home | |
| 190 | +lists). Value objects: `MetricValue` (headline/topic), `SeriesValue` (series), `RankingRow`, `HomeListRow`; all carry | |
| 191 | +`provenance`. Sparklines are `SparkPoint = [year, value]`. Pydantic models already defined but **not yet mirrored** | |
| 192 | +(add them when you build the pages): `CompareResponse`, `CompareSnapshotResponse`, `RankingsListResponse`, | |
| 193 | +`RankHistoryResponse`, `IndicatorsResponse`, `IndicatorResponse` (+`IndicatorSource`, `WorldLatest`, `RankedValue`), | |
| 194 | +`TrendResponse`, `RegionsResponse`, `RegionResponse`, `SourcesResponse`, `SourceResponse`, methodology/admin payloads. | |
| 195 | +Add the matching `api.*` methods in `lib/api.ts` with `request<T>()`, routes in `lib/site.ts`, strings in `i18n/en.ts`, | |
| 196 | +and sitemap entries in `app/sitemap.ts`. | |
| 197 | + | |
| 198 | +## Brand | |
| 199 | + | |
| 200 | +`components/brand/Logo.tsx`: a globe ring whose equator is the crossbar of an "A" (two meridian-like legs to one apex). | |
| 201 | +Strokes only, `currentColor`, monochrome-capable. `src/app/icon.svg` (rounded paper tile) → `icon.png` 512 / | |
| 202 | +`apple-icon.png` 180 via `qa/favicons.mjs`; `manifest.ts` theme colour #1c5cab. Social images: `app/opengraph-image.tsx` | |
| 203 | +(+ `twitter-image.tsx`) and `app/countries/[slug]/opengraph-image.tsx` (flag + name + 3 headline values). Satori | |
| 204 | +gotchas: children of a multi-child `<div>` need `display:flex`; numeric children must be `String()`-ed. | |
| 205 | + | |
| 206 | +## Known issues / not in this round | |
| 207 | + | |
| 208 | +* `/admin` needs `CA_ADMIN_TOKEN` in the **web** process env (the mld manifest passes it); without it the login page says | |
| 209 | + the panel is disabled. `ADMIN_API_URL` (optional) points admin fetches at another API instance. QA for the explore | |
| 210 | + routes: `node qa/shots-explore.mjs` → `qa/screens/explore/` (+ report.json, touch test of the map year slider). | |
| 211 | +* Sitemap ≈ 4.9k URLs (countries × topics + indicators + regions + sources + rankings) — switch to `generateSitemaps` | |
| 212 | + before adding another per-country family. | |
| 213 | +* Search hit types `country_topic` / `country_indicator` render with the Topic/Indicator chip; `/topics/*` URLs the API | |
| 214 | + may emit for bare topics are mapped to `/indicators?topic=` client-side (`hrefFor`). | |
| 215 | +* The API `CountrySummary` has no `iso_numeric`; the choropleth uses the static numeric→ISO3 table (`lib/iso-numeric.ts`) | |
| 216 | + and will prefer `iso_numeric` automatically if the API adds it. | |
| 217 | +* Topic page renders the first 4 charts with server-fetched history; the rest fetch on scroll (client). With a slow API | |
| 218 | + the fold could show "Loading…" placeholders of reserved height (no CLS). | |
| 219 | +* Fixture screenshots contain synthetic values by design; re-run `qa/screens.mjs` against the real API before launch. | |
added
apps/web/qa/admin-explore.mjs
+73 −0
@@ -0,0 +1,73 @@ | ||
| 1 | +/** | |
| 2 | + * Admin panel QA: wrong token → error; right token (deploy/.admin-token) → cookie → overview/coverage/runs/issues/raw | |
| 3 | + * render; "Clear cache" server action round-trips; screenshots at 390 + 1440 → qa/screens/explore/admin_*.png. | |
| 4 | + * Needs CA_ADMIN_TOKEN on the web process (and ADMIN_API_URL → an API instance with the same token). | |
| 5 | + * Run: node qa/admin-explore.mjs [BASE_URL] | |
| 6 | + */ | |
| 7 | +import { chromium } from '/Users/simon-pierreboucher/Desktop/uqo-eval/node_modules/playwright/index.mjs'; | |
| 8 | +import { readFileSync } from 'node:fs'; | |
| 9 | + | |
| 10 | +const BASE = process.argv[2] ?? 'http://localhost:8290'; | |
| 11 | +const OUT = new URL('./screens/explore/', import.meta.url).pathname; | |
| 12 | +const TOKEN = readFileSync(new URL('../../../deploy/.admin-token', import.meta.url), 'utf8').trim(); | |
| 13 | + | |
| 14 | +const browser = await chromium.launch(); | |
| 15 | +for (const width of [390, 1440]) { | |
| 16 | + const mobile = width < 768; | |
| 17 | + const ctx = await browser.newContext({ viewport: { width, height: mobile ? 844 : 900 }, isMobile: mobile, hasTouch: mobile }); | |
| 18 | + const page = await ctx.newPage(); | |
| 19 | + const errors = []; | |
| 20 | + page.on('pageerror', (e) => errors.push(String(e))); | |
| 21 | + page.on('console', (m) => m.type() === 'error' && errors.push(m.text())); | |
| 22 | + | |
| 23 | + // unauthenticated → redirect to login | |
| 24 | + let res = await page.goto(BASE + '/admin/coverage', { waitUntil: 'networkidle' }); | |
| 25 | + console.log(width, 'gate:', page.url().endsWith('/admin/login') ? 'redirected to login OK' : `FAIL ${page.url()}`, res?.status()); | |
| 26 | + | |
| 27 | + // wrong token | |
| 28 | + await page.fill('input[name=token]', 'nope'); | |
| 29 | + await page.click('button[type=submit]'); | |
| 30 | + await page.waitForURL(/error=1/, { timeout: 60_000 }).catch(() => {}); | |
| 31 | + await page.waitForLoadState('networkidle'); | |
| 32 | + const err = await page.getByText('Invalid token.').count(); | |
| 33 | + const stillNoCookie = !(await ctx.cookies()).some((k) => k.name === 'ca_admin'); | |
| 34 | + console.log(width, 'wrong token:', err && stillNoCookie ? 'error shown, no cookie OK' : `FAIL url=${page.url()} err=${err} noCookie=${stillNoCookie}`); | |
| 35 | + | |
| 36 | + // right token | |
| 37 | + await page.fill('input[name=token]', TOKEN); | |
| 38 | + await page.click('button[type=submit]'); | |
| 39 | + await page.waitForURL(/\/admin(\?.*)?$/, { timeout: 60_000 }); | |
| 40 | + await page.waitForLoadState('networkidle'); | |
| 41 | + const cookies = await ctx.cookies(); | |
| 42 | + const c = cookies.find((k) => k.name === 'ca_admin'); | |
| 43 | + console.log(width, 'cookie:', c ? `httpOnly=${c.httpOnly} sameSite=${c.sameSite} path=${c.path} value≠token=${c.value !== TOKEN}` : 'MISSING'); | |
| 44 | + for (const p of ['/admin', '/admin/coverage', '/admin/runs', '/admin/issues', '/admin/raw']) { | |
| 45 | + res = await page.goto(BASE + p, { waitUntil: 'networkidle', timeout: 120_000 }); | |
| 46 | + const h = await page.locator('h2').first().textContent().catch(() => ''); | |
| 47 | + const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); | |
| 48 | + await page.screenshot({ path: `${OUT}admin${p.replace(/\//g, '_')}-${width}.png`, fullPage: true }); | |
| 49 | + console.log(width, p.padEnd(16), res?.status(), `h2="${h?.trim()}"`, overflow > 0 ? `OVERFLOW +${overflow}` : 'ok'); | |
| 50 | + } | |
| 51 | + // raw files for the latest run id from the runs page | |
| 52 | + await page.goto(BASE + '/admin/runs', { waitUntil: 'networkidle' }); | |
| 53 | + const runId = await page.locator('a[href*="run_id="]').first().textContent(); | |
| 54 | + await page.goto(BASE + `/admin/raw?run_id=${runId?.trim()}`, { waitUntil: 'networkidle' }); | |
| 55 | + const files = await page.locator('table').count(); | |
| 56 | + console.log(width, 'raw run', runId?.trim(), files ? `${files} tables OK` : 'no table'); | |
| 57 | + // clear cache action | |
| 58 | + await page.goto(BASE + '/admin', { waitUntil: 'networkidle' }); | |
| 59 | + await page.click('button:has-text("Clear cache")'); | |
| 60 | + await page.waitForURL(/[?&](ok|err)=/, { timeout: 60_000 }); | |
| 61 | + console.log(width, 'clear cache:', decodeURIComponent(page.url().split('?')[1] ?? '')); | |
| 62 | + // refresh now (expected 409 → err=: no scheduler pid on this dev machine) | |
| 63 | + await page.goto(BASE + '/admin', { waitUntil: 'networkidle' }); | |
| 64 | + await page.click('button:has-text("Refresh now")'); | |
| 65 | + await page.waitForURL(/[?&](ok|err)=/, { timeout: 60_000 }); | |
| 66 | + console.log(width, 'refresh now:', decodeURIComponent(page.url().split('?')[1] ?? '').slice(0, 120)); | |
| 67 | + // logout | |
| 68 | + await page.click('button:has-text("Sign out")'); | |
| 69 | + await page.waitForURL(/\/admin\/login/, { timeout: 30_000 }); | |
| 70 | + console.log(width, 'logout OK', errors.length ? `console errors: ${errors.slice(0, 3).join(' | ')}` : 'no console errors'); | |
| 71 | + await ctx.close(); | |
| 72 | +} | |
| 73 | +await browser.close(); | |
added
apps/web/qa/compare-rankings.mjs
+87 −0
@@ -0,0 +1,87 @@ | ||
| 1 | +/** | |
| 2 | + * QA for the Compare + Rankings pages: screenshots at 320/375/390/430/1280/1440 → qa/screens/compare-rankings/, | |
| 3 | + * plus checks: horizontal overflow, tap targets < 44 px (mobile), console errors, sticky controls height, | |
| 4 | + * URL state round-trip (reload keeps state), 404s. Run: node qa/compare-rankings.mjs [BASE_URL] | |
| 5 | + */ | |
| 6 | +import { chromium } from '/Users/simon-pierreboucher/Desktop/uqo-eval/node_modules/playwright/index.mjs'; | |
| 7 | +import { mkdirSync, writeFileSync } from 'node:fs'; | |
| 8 | + | |
| 9 | +const BASE = process.argv[2] ?? 'http://localhost:8290'; | |
| 10 | +const OUT = new URL('./screens/compare-rankings/', import.meta.url).pathname; | |
| 11 | +mkdirSync(OUT, { recursive: true }); | |
| 12 | + | |
| 13 | +const PAGES = [ | |
| 14 | + ['compare', '/compare'], | |
| 15 | + ['cmp-snapshot', '/compare/canada/united-states/france'], | |
| 16 | + ['cmp-economy', '/compare/canada/united-states/france?tab=economy'], | |
| 17 | + ['cmp-hero', '/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100'], | |
| 18 | + ['rankings', '/rankings'], | |
| 19 | + ['rk-gdppc', '/rankings/gdp-per-capita'], | |
| 20 | + ['rk-life-oecd', '/rankings/life-expectancy?group=oecd'], | |
| 21 | +]; | |
| 22 | +const WIDTHS = [320, 375, 390, 430, 1280, 1440]; | |
| 23 | +const report = []; | |
| 24 | +const browser = await chromium.launch(); | |
| 25 | + | |
| 26 | +for (const width of WIDTHS) { | |
| 27 | + const mobile = width < 768; | |
| 28 | + const ctx = await browser.newContext({ viewport: { width, height: mobile ? 800 : 900 }, deviceScaleFactor: 1, isMobile: mobile, hasTouch: mobile, colorScheme: 'light' }); | |
| 29 | + const page = await ctx.newPage(); | |
| 30 | + const errors = []; | |
| 31 | + page.on('pageerror', (e) => errors.push(String(e))); | |
| 32 | + page.on('console', (m) => { if (m.type() === 'error') errors.push(m.text()); }); | |
| 33 | + for (const [name, path] of PAGES) { | |
| 34 | + await page.goto(BASE + path, { waitUntil: 'networkidle' }); | |
| 35 | + await page.evaluate(() => document.fonts.ready); | |
| 36 | + await page.waitForTimeout(700); | |
| 37 | + const m = await page.evaluate(() => { | |
| 38 | + const de = document.documentElement; | |
| 39 | + const overflow = de.scrollWidth - de.clientWidth; | |
| 40 | + const wide = [...document.querySelectorAll('body *')].filter((el) => { const r = el.getBoundingClientRect(); return r.right > de.clientWidth + 1 && r.width > 0 && getComputedStyle(el).position !== 'fixed'; }).slice(0, 6).map((el) => `${el.tagName.toLowerCase()}.${String(el.className).split(' ').slice(0, 3).join('.')} right=${Math.round(el.getBoundingClientRect().right)}`); | |
| 41 | + const small = [...document.querySelectorAll('a,button,[role=button],input,select,summary')].filter((el) => { const r = el.getBoundingClientRect(); if (r.width === 0 || r.height === 0) return false; const cs = getComputedStyle(el); if (cs.visibility === 'hidden') return false; return r.height < 44 && r.width < 44; }).map((el) => `${el.tagName.toLowerCase()} "${(el.getAttribute('aria-label') || el.textContent || '').trim().slice(0, 30)}" ${Math.round(el.getBoundingClientRect().width)}x${Math.round(el.getBoundingClientRect().height)}`); | |
| 42 | + const smallH = [...document.querySelectorAll('a,button,[role=button],input,select,summary')].filter((el) => { const r = el.getBoundingClientRect(); return r.width > 0 && r.height > 0 && r.height < 32; }).map((el) => `${el.tagName.toLowerCase()} "${(el.getAttribute('aria-label') || el.textContent || '').trim().slice(0, 30)}" h=${Math.round(el.getBoundingClientRect().height)}`); | |
| 43 | + const sticky = [...document.querySelectorAll('.sticky')].filter((el) => el.getBoundingClientRect().height > 0).map((el) => Math.round(el.getBoundingClientRect().height)); | |
| 44 | + return { overflow, wide, small: small.slice(0, 12), smallH: smallH.slice(0, 12), sticky, docH: de.scrollHeight }; | |
| 45 | + }); | |
| 46 | + await page.screenshot({ path: `${OUT}${name}-${width}.png`, fullPage: true }); | |
| 47 | + report.push({ name, path, width, ...m, errors: errors.splice(0) }); | |
| 48 | + } | |
| 49 | + await ctx.close(); | |
| 50 | +} | |
| 51 | + | |
| 52 | +// URL state round-trip + 404s (desktop) | |
| 53 | +{ | |
| 54 | + const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } }); | |
| 55 | + const page = await ctx.newPage(); | |
| 56 | + const checks = []; | |
| 57 | + await page.goto(`${BASE}/compare/canada/united-states/france?tab=economy`, { waitUntil: 'networkidle' }); | |
| 58 | + await page.getByRole('radio', { name: 'Index = 100' }).click(); | |
| 59 | + await page.waitForTimeout(1200); | |
| 60 | + const url1 = page.url(); | |
| 61 | + await page.reload({ waitUntil: 'networkidle' }); | |
| 62 | + const modeChecked = await page.getByRole('radio', { name: 'Index = 100' }).getAttribute('aria-checked'); | |
| 63 | + checks.push({ check: 'compare mode round-trip', url: url1, ok: url1.includes('mode=index100') && modeChecked === 'true' }); | |
| 64 | + await page.getByRole('tab', { name: 'Population' }).click(); | |
| 65 | + await page.waitForTimeout(1200); | |
| 66 | + checks.push({ check: 'tab switch updates URL', url: page.url(), ok: page.url().includes('tab=population') }); | |
| 67 | + await page.goto(`${BASE}/rankings/gdp-per-capita`, { waitUntil: 'networkidle' }); | |
| 68 | + await page.locator('select[aria-label="Year"]:visible').first().selectOption('2015'); | |
| 69 | + await page.waitForTimeout(1500); | |
| 70 | + const url2 = page.url(); | |
| 71 | + await page.reload({ waitUntil: 'networkidle' }); | |
| 72 | + const yearVal = await page.locator('select[aria-label="Year"]:visible').first().inputValue(); | |
| 73 | + checks.push({ check: 'ranking year round-trip', url: url2, ok: url2.includes('year=2015') && yearVal === '2015' }); | |
| 74 | + for (const p of ['/compare/canada', '/rankings/not-a-thing', '/compare/canada/nowhere-land']) { | |
| 75 | + const res = await page.goto(BASE + p, { waitUntil: 'domcontentloaded' }); | |
| 76 | + checks.push({ check: `404 ${p}`, status: res?.status(), ok: res?.status() === 404 }); | |
| 77 | + } | |
| 78 | + report.push({ checks }); | |
| 79 | + await ctx.close(); | |
| 80 | +} | |
| 81 | +await browser.close(); | |
| 82 | +writeFileSync(`${OUT}report.json`, JSON.stringify(report, null, 2)); | |
| 83 | +for (const r of report) { | |
| 84 | + if (r.checks) { for (const c of r.checks) console.log(c.ok ? 'OK ' : 'FAIL', c.check, c.url ?? c.status ?? ''); continue; } | |
| 85 | + const flags = [r.overflow > 0 ? `OVERFLOW ${r.overflow}px ${r.wide.join(' | ')}` : '', r.width < 768 && r.small.length ? `small: ${r.small.join(' | ')}` : '', r.errors.length ? `errors: ${r.errors.join(' | ').slice(0, 300)}` : ''].filter(Boolean); | |
| 86 | + console.log(`${r.name}@${r.width} h=${r.docH} sticky=[${r.sticky.join(',')}] ${flags.join(' ; ')}`); | |
| 87 | +} | |
added
apps/web/qa/cr-interact.mjs
+21 −0
@@ -0,0 +1,21 @@ | ||
| 1 | +import { chromium } from '/Users/simon-pierreboucher/Desktop/uqo-eval/node_modules/playwright/index.mjs'; | |
| 2 | +const BASE = 'http://localhost:8290'; | |
| 3 | +const OUT = new URL('./screens/compare-rankings/seg/', import.meta.url).pathname; | |
| 4 | +const b = await chromium.launch(); | |
| 5 | +const errs = []; | |
| 6 | +async function ctx(w, dark=false){ const c = await b.newContext({ viewport: { width: w, height: w<768?844:900 }, isMobile: w<768, hasTouch: w<768, colorScheme: dark?'dark':'light' }); const p = await c.newPage(); p.on('pageerror',e=>errs.push(String(e))); p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); return [c,p]; } | |
| 7 | +// mobile: options sheet on compare | |
| 8 | +{ const [c,p] = await ctx(390); await p.goto(`${BASE}/compare/canada/united-states/france?tab=economy`, {waitUntil:'networkidle'}); await p.getByRole('button',{name:'Options'}).click(); await p.waitForTimeout(600); await p.screenshot({path:`${OUT}i-options-390.png`}); await c.close(); } | |
| 9 | +// mobile: add-country picker | |
| 10 | +{ const [c,p] = await ctx(390); await p.goto(`${BASE}/compare/canada/united-states/france`, {waitUntil:'networkidle'}); await p.getByRole('button',{name:'Add a country'}).first().click(); await p.waitForTimeout(500); await p.locator('dialog input[type=search]').fill('ger'); await p.waitForTimeout(400); await p.screenshot({path:`${OUT}i-picker-390.png`}); await p.locator('dialog button', {hasText:'Germany'}).click(); await p.waitForURL(/germany/); await p.waitForTimeout(1200); await p.screenshot({path:`${OUT}i-added-390.png`}); console.log('after add', p.url()); await c.close(); } | |
| 11 | +// desktop: custom tab + indicator picker | |
| 12 | +{ const [c,p] = await ctx(1280); await p.goto(`${BASE}/compare/canada/united-states/france?tab=custom&indicators=gdp-per-capita,life-expectancy`, {waitUntil:'networkidle'}); await p.waitForTimeout(600); await p.screenshot({path:`${OUT}i-custom-1280.png`}); await p.getByRole('button',{name:'Add an indicator'}).click(); await p.waitForTimeout(800); await p.locator('dialog input[type=search]').fill('unemploy'); await p.waitForTimeout(400); await p.screenshot({path:`${OUT}i-indpicker-1280.png`}); await p.locator('dialog li button').first().click(); await p.waitForTimeout(1500); console.log('custom url', p.url()); await c.close(); } | |
| 13 | +// desktop: snapshot cell provenance + indicator link | |
| 14 | +{ const [c,p] = await ctx(1280); await p.goto(`${BASE}/compare/canada/united-states/france`, {waitUntil:'networkidle'}); await p.getByRole('button',{name:'Show source and provenance'}).first().click(); await p.waitForTimeout(600); await p.screenshot({path:`${OUT}i-prov-1280.png`}); await p.keyboard.press('Escape'); await p.getByRole('link',{name:'Chart Life expectancy'}).click(); await p.waitForURL(/tab=health/); await p.waitForTimeout(1500); console.log('chart link', p.url()); await p.screenshot({path:`${OUT}i-health-hero-1280.png`}); await c.close(); } | |
| 15 | +// desktop: ranking highlight + group filter + dark mode | |
| 16 | +{ const [c,p] = await ctx(1280, true); await p.goto(`${BASE}/rankings/gdp-per-capita?highlight=canada`, {waitUntil:'networkidle'}); await p.waitForTimeout(600); await p.screenshot({path:`${OUT}i-rk-highlight-dark-1280.png`}); await p.locator('select[aria-label="Group"]:visible').selectOption('g20'); await p.waitForTimeout(1500); console.log('group url', p.url()); await p.screenshot({path:`${OUT}i-rk-g20-dark-1280.png`}); await c.close(); } | |
| 17 | +// mobile: ranking filters sheet + history panel | |
| 18 | +{ const [c,p] = await ctx(390); await p.goto(`${BASE}/rankings/life-expectancy?group=oecd&highlight=canada`, {waitUntil:'networkidle'}); await p.getByRole('button',{name:'Filters'}).click(); await p.waitForTimeout(600); await p.screenshot({path:`${OUT}i-rk-filters-390.png`}); await p.keyboard.press('Escape'); await p.evaluate(()=>document.getElementById('history')?.scrollIntoView()); await p.waitForTimeout(600); await p.screenshot({path:`${OUT}i-rk-history-390.png`}); await c.close(); } | |
| 19 | +// mobile dark compare economy | |
| 20 | +{ const [c,p] = await ctx(390, true); await p.goto(`${BASE}/compare/canada/united-states/france?tab=economy`, {waitUntil:'networkidle'}); await p.evaluate(()=>window.scrollTo(0,700)); await p.waitForTimeout(700); await p.screenshot({path:`${OUT}i-eco-dark-390.png`}); await c.close(); } | |
| 21 | +await b.close(); console.log('errors', errs.length, errs.slice(0,5)); | |
added
apps/web/qa/cr-segments.mjs
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +import { chromium } from '/Users/simon-pierreboucher/Desktop/uqo-eval/node_modules/playwright/index.mjs'; | |
| 2 | +const BASE = process.argv[2] ?? 'http://localhost:8290'; | |
| 3 | +const OUT = new URL('./screens/compare-rankings/seg/', import.meta.url).pathname; | |
| 4 | +import { mkdirSync } from 'node:fs'; mkdirSync(OUT, { recursive: true }); | |
| 5 | +const SHOTS = [ | |
| 6 | + ['cmp-snapshot', '/compare/canada/united-states/france', 390, [0, 700]], | |
| 7 | + ['cmp-economy', '/compare/canada/united-states/france?tab=economy', 390, [0, 900, 1800]], | |
| 8 | + ['cmp-hero', '/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100', 390, [0, 700]], | |
| 9 | + ['cmp-economy', '/compare/canada/united-states/france?tab=economy', 1280, [0, 900, 1800]], | |
| 10 | + ['cmp-hero', '/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100', 1280, [0]], | |
| 11 | + ['rankings', '/rankings', 390, [0, 800]], | |
| 12 | + ['rankings', '/rankings', 1280, [0, 900]], | |
| 13 | + ['rk-gdppc', '/rankings/gdp-per-capita', 390, [0, 800, 2600, 3600]], | |
| 14 | + ['rk-gdppc', '/rankings/gdp-per-capita', 1280, [900, 1800]], | |
| 15 | + ['rk-life-oecd', '/rankings/life-expectancy?group=oecd', 390, [0, 1200]], | |
| 16 | + ['rk-life-oecd', '/rankings/life-expectancy?group=oecd', 1280, [0, 1600]], | |
| 17 | +]; | |
| 18 | +const b = await chromium.launch(); | |
| 19 | +for (const [name, path, w, offsets] of SHOTS) { | |
| 20 | + const mobile = w < 768; | |
| 21 | + const ctx = await b.newContext({ viewport: { width: w, height: mobile ? 844 : 900 }, isMobile: mobile, hasTouch: mobile, deviceScaleFactor: 1 }); | |
| 22 | + const pg = await ctx.newPage(); | |
| 23 | + await pg.goto(BASE + path, { waitUntil: 'networkidle' }); | |
| 24 | + await pg.waitForTimeout(600); | |
| 25 | + for (const y of offsets) { | |
| 26 | + await pg.evaluate((yy) => window.scrollTo(0, yy), y); | |
| 27 | + await pg.waitForTimeout(700); | |
| 28 | + await pg.screenshot({ path: `${OUT}${name}-${w}-y${y}.png` }); | |
| 29 | + } | |
| 30 | + await ctx.close(); | |
| 31 | +} | |
| 32 | +await b.close(); | |
| 33 | +console.log('done'); | |
added
apps/web/qa/favicons.mjs
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +// Rasterise src/app/icon.svg → icon.png (512) + apple-icon.png (180). Run after editing the SVG. | |
| 2 | +import { chromium } from 'playwright'; | |
| 3 | +import { readFileSync } from 'node:fs'; | |
| 4 | +const svg = readFileSync(new URL('../src/app/icon.svg', import.meta.url), 'utf8'); | |
| 5 | +const browser = await chromium.launch(); | |
| 6 | +for (const [size, file] of [[512, '../src/app/icon.png'], [180, '../src/app/apple-icon.png']]) { | |
| 7 | + const ctx = await browser.newContext({ viewport: { width: size, height: size }, deviceScaleFactor: 1 }); | |
| 8 | + const page = await ctx.newPage(); | |
| 9 | + await page.setContent(`<html><body style="margin:0;background:transparent">${svg.replace(/width="\d+" height="\d+"/, `width="${size}" height="${size}"`)}</body></html>`); | |
| 10 | + await page.screenshot({ path: new URL(file, import.meta.url).pathname, omitBackground: true, clip: { x: 0, y: 0, width: size, height: size } }); | |
| 11 | + await ctx.close(); | |
| 12 | +} | |
| 13 | +await browser.close(); | |
| 14 | +console.log('favicons written'); | |
added
apps/web/qa/screens/compare-rankings/cmp-economy-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-economy-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-economy-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-economy-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-economy-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-economy-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-hero-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-hero-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-hero-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-hero-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-hero-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-hero-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-snapshot-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-snapshot-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-snapshot-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-snapshot-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-snapshot-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/cmp-snapshot-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/compare-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/compare-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/compare-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/compare-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/compare-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/compare-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rankings-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rankings-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rankings-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rankings-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rankings-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rankings-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/report.json
+1222 −0
@@ -0,0 +1,1222 @@ | ||
| 1 | +[ | |
| 2 | + { | |
| 3 | + "name": "compare", | |
| 4 | + "path": "/compare", | |
| 5 | + "width": 320, | |
| 6 | + "overflow": 0, | |
| 7 | + "wide": [], | |
| 8 | + "small": [ | |
| 9 | + "a \"Skip to content\" 1x1" | |
| 10 | + ], | |
| 11 | + "smallH": [ | |
| 12 | + "a \"Skip to content\" h=1", | |
| 13 | + "a \"contact@spboucher.ai\" h=15", | |
| 14 | + "a \"MacLustr\" h=15" | |
| 15 | + ], | |
| 16 | + "sticky": [ | |
| 17 | + 53, | |
| 18 | + 61 | |
| 19 | + ], | |
| 20 | + "docH": 2569, | |
| 21 | + "errors": [] | |
| 22 | + }, | |
| 23 | + { | |
| 24 | + "name": "cmp-snapshot", | |
| 25 | + "path": "/compare/canada/united-states/france", | |
| 26 | + "width": 320, | |
| 27 | + "overflow": 0, | |
| 28 | + "wide": [ | |
| 29 | + "li.group/chip.shrink-0 right=329", | |
| 30 | + "span.inline-flex.h-11.items-center right=329", | |
| 31 | + "button.grid.h-11.w-9 right=328", | |
| 32 | + "li.group/chip.shrink-0 right=465", | |
| 33 | + "span.inline-flex.h-11.items-center right=465", | |
| 34 | + "span.h-2.w-2.shrink-0 right=352" | |
| 35 | + ], | |
| 36 | + "small": [ | |
| 37 | + "a \"Skip to content\" 1x1" | |
| 38 | + ], | |
| 39 | + "smallH": [ | |
| 40 | + "a \"Skip to content\" h=1", | |
| 41 | + "a \"contact@spboucher.ai\" h=15", | |
| 42 | + "a \"MacLustr\" h=15" | |
| 43 | + ], | |
| 44 | + "sticky": [ | |
| 45 | + 53, | |
| 46 | + 105 | |
| 47 | + ], | |
| 48 | + "docH": 4083, | |
| 49 | + "errors": [] | |
| 50 | + }, | |
| 51 | + { | |
| 52 | + "name": "cmp-economy", | |
| 53 | + "path": "/compare/canada/united-states/france?tab=economy", | |
| 54 | + "width": 320, | |
| 55 | + "overflow": 0, | |
| 56 | + "wide": [ | |
| 57 | + "li.group/chip.shrink-0 right=329", | |
| 58 | + "span.inline-flex.h-11.items-center right=329", | |
| 59 | + "button.grid.h-11.w-9 right=328", | |
| 60 | + "li.group/chip.shrink-0 right=465", | |
| 61 | + "span.inline-flex.h-11.items-center right=465", | |
| 62 | + "span.h-2.w-2.shrink-0 right=352" | |
| 63 | + ], | |
| 64 | + "small": [ | |
| 65 | + "a \"Skip to content\" 1x1" | |
| 66 | + ], | |
| 67 | + "smallH": [ | |
| 68 | + "a \"Skip to content\" h=1", | |
| 69 | + "a \"GDP (current US$)\" h=17", | |
| 70 | + "button \"Source for Canada, United Stat\" h=28", | |
| 71 | + "button \"Source for Canada, United Stat\" h=28", | |
| 72 | + "a \"GDP per capita (current US$)\" h=17", | |
| 73 | + "button \"Source for Canada, United Stat\" h=28", | |
| 74 | + "button \"Source for Canada, United Stat\" h=28", | |
| 75 | + "a \"Real GDP growth\" h=17", | |
| 76 | + "button \"Source for Canada, United Stat\" h=28", | |
| 77 | + "a \"GDP per capita growth\" h=17", | |
| 78 | + "button \"Source for Canada, United Stat\" h=28", | |
| 79 | + "a \"GDP (constant 2015 US$)\" h=17" | |
| 80 | + ], | |
| 81 | + "sticky": [ | |
| 82 | + 53, | |
| 83 | + 105 | |
| 84 | + ], | |
| 85 | + "docH": 18787, | |
| 86 | + "errors": [] | |
| 87 | + }, | |
| 88 | + { | |
| 89 | + "name": "cmp-hero", | |
| 90 | + "path": "/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100", | |
| 91 | + "width": 320, | |
| 92 | + "overflow": 0, | |
| 93 | + "wide": [ | |
| 94 | + "li.group/chip.shrink-0 right=329", | |
| 95 | + "span.inline-flex.h-11.items-center right=329", | |
| 96 | + "button.grid.h-11.w-9 right=328", | |
| 97 | + "li.group/chip.shrink-0 right=465", | |
| 98 | + "span.inline-flex.h-11.items-center right=465", | |
| 99 | + "span.h-2.w-2.shrink-0 right=352" | |
| 100 | + ], | |
| 101 | + "small": [ | |
| 102 | + "a \"Skip to content\" 1x1" | |
| 103 | + ], | |
| 104 | + "smallH": [ | |
| 105 | + "a \"Skip to content\" h=1", | |
| 106 | + "button \"Source for Canada, United Stat\" h=28", | |
| 107 | + "a \"GDP (current US$)\" h=17", | |
| 108 | + "button \"Source for Canada, United Stat\" h=28", | |
| 109 | + "button \"Source for Canada, United Stat\" h=28", | |
| 110 | + "button \"Source for Canada, United Stat\" h=28", | |
| 111 | + "a \"Real GDP growth\" h=17", | |
| 112 | + "button \"Source for Canada, United Stat\" h=28", | |
| 113 | + "a \"GDP per capita growth\" h=17", | |
| 114 | + "button \"Source for Canada, United Stat\" h=28", | |
| 115 | + "a \"GDP (constant 2015 US$)\" h=17", | |
| 116 | + "button \"Source for Canada, United Stat\" h=28" | |
| 117 | + ], | |
| 118 | + "sticky": [ | |
| 119 | + 53, | |
| 120 | + 105 | |
| 121 | + ], | |
| 122 | + "docH": 19052, | |
| 123 | + "errors": [] | |
| 124 | + }, | |
| 125 | + { | |
| 126 | + "name": "rankings", | |
| 127 | + "path": "/rankings", | |
| 128 | + "width": 320, | |
| 129 | + "overflow": 0, | |
| 130 | + "wide": [], | |
| 131 | + "small": [ | |
| 132 | + "a \"Skip to content\" 1x1" | |
| 133 | + ], | |
| 134 | + "smallH": [ | |
| 135 | + "a \"Skip to content\" h=1", | |
| 136 | + "a \"contact@spboucher.ai\" h=15", | |
| 137 | + "a \"MacLustr\" h=15" | |
| 138 | + ], | |
| 139 | + "sticky": [ | |
| 140 | + 53, | |
| 141 | + 61 | |
| 142 | + ], | |
| 143 | + "docH": 26234, | |
| 144 | + "errors": [] | |
| 145 | + }, | |
| 146 | + { | |
| 147 | + "name": "rk-gdppc", | |
| 148 | + "path": "/rankings/gdp-per-capita", | |
| 149 | + "width": 320, | |
| 150 | + "overflow": 0, | |
| 151 | + "wide": [], | |
| 152 | + "small": [ | |
| 153 | + "a \"Skip to content\" 1x1" | |
| 154 | + ], | |
| 155 | + "smallH": [ | |
| 156 | + "a \"Skip to content\" h=1", | |
| 157 | + "select \"Year\" h=19", | |
| 158 | + "a \"contact@spboucher.ai\" h=15", | |
| 159 | + "a \"MacLustr\" h=15" | |
| 160 | + ], | |
| 161 | + "sticky": [ | |
| 162 | + 53, | |
| 163 | + 61 | |
| 164 | + ], | |
| 165 | + "docH": 4759, | |
| 166 | + "errors": [] | |
| 167 | + }, | |
| 168 | + { | |
| 169 | + "name": "rk-life-oecd", | |
| 170 | + "path": "/rankings/life-expectancy?group=oecd", | |
| 171 | + "width": 320, | |
| 172 | + "overflow": 0, | |
| 173 | + "wide": [], | |
| 174 | + "small": [ | |
| 175 | + "a \"Skip to content\" 1x1" | |
| 176 | + ], | |
| 177 | + "smallH": [ | |
| 178 | + "a \"Skip to content\" h=1", | |
| 179 | + "select \"Year\" h=19", | |
| 180 | + "a \"contact@spboucher.ai\" h=15", | |
| 181 | + "a \"MacLustr\" h=15" | |
| 182 | + ], | |
| 183 | + "sticky": [ | |
| 184 | + 53, | |
| 185 | + 61 | |
| 186 | + ], | |
| 187 | + "docH": 4689, | |
| 188 | + "errors": [] | |
| 189 | + }, | |
| 190 | + { | |
| 191 | + "name": "compare", | |
| 192 | + "path": "/compare", | |
| 193 | + "width": 375, | |
| 194 | + "overflow": 0, | |
| 195 | + "wide": [], | |
| 196 | + "small": [ | |
| 197 | + "a \"Skip to content\" 1x1" | |
| 198 | + ], | |
| 199 | + "smallH": [ | |
| 200 | + "a \"Skip to content\" h=1", | |
| 201 | + "a \"contact@spboucher.ai\" h=15", | |
| 202 | + "a \"MacLustr\" h=15" | |
| 203 | + ], | |
| 204 | + "sticky": [ | |
| 205 | + 53, | |
| 206 | + 61 | |
| 207 | + ], | |
| 208 | + "docH": 2508, | |
| 209 | + "errors": [] | |
| 210 | + }, | |
| 211 | + { | |
| 212 | + "name": "cmp-snapshot", | |
| 213 | + "path": "/compare/canada/united-states/france", | |
| 214 | + "width": 375, | |
| 215 | + "overflow": 0, | |
| 216 | + "wide": [ | |
| 217 | + "li.group/chip.shrink-0 right=465", | |
| 218 | + "span.inline-flex.h-11.items-center right=465", | |
| 219 | + "span.max-w-[8rem].truncate.text-ink right=424", | |
| 220 | + "button.grid.h-11.w-9 right=464", | |
| 221 | + "svg.[object.SVGAnimatedString] right=453", | |
| 222 | + "path.[object.SVGAnimatedString] right=449" | |
| 223 | + ], | |
| 224 | + "small": [ | |
| 225 | + "a \"Skip to content\" 1x1" | |
| 226 | + ], | |
| 227 | + "smallH": [ | |
| 228 | + "a \"Skip to content\" h=1", | |
| 229 | + "a \"contact@spboucher.ai\" h=15", | |
| 230 | + "a \"MacLustr\" h=15" | |
| 231 | + ], | |
| 232 | + "sticky": [ | |
| 233 | + 53, | |
| 234 | + 105 | |
| 235 | + ], | |
| 236 | + "docH": 4049, | |
| 237 | + "errors": [] | |
| 238 | + }, | |
| 239 | + { | |
| 240 | + "name": "cmp-economy", | |
| 241 | + "path": "/compare/canada/united-states/france?tab=economy", | |
| 242 | + "width": 375, | |
| 243 | + "overflow": 0, | |
| 244 | + "wide": [ | |
| 245 | + "li.group/chip.shrink-0 right=465", | |
| 246 | + "span.inline-flex.h-11.items-center right=465", | |
| 247 | + "span.max-w-[8rem].truncate.text-ink right=424", | |
| 248 | + "button.grid.h-11.w-9 right=464", | |
| 249 | + "svg.[object.SVGAnimatedString] right=453", | |
| 250 | + "path.[object.SVGAnimatedString] right=449" | |
| 251 | + ], | |
| 252 | + "small": [ | |
| 253 | + "a \"Skip to content\" 1x1" | |
| 254 | + ], | |
| 255 | + "smallH": [ | |
| 256 | + "a \"Skip to content\" h=1", | |
| 257 | + "a \"GDP (current US$)\" h=17", | |
| 258 | + "button \"Source for Canada, United Stat\" h=28", | |
| 259 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 260 | + "button \"Source for Canada, United Stat\" h=28", | |
| 261 | + "a \"GDP per capita (current US$)\" h=17", | |
| 262 | + "button \"Source for Canada, United Stat\" h=28", | |
| 263 | + "button \"Source for Canada, United Stat\" h=28", | |
| 264 | + "a \"Real GDP growth\" h=17", | |
| 265 | + "button \"Source for Canada, United Stat\" h=28", | |
| 266 | + "a \"GDP per capita growth\" h=17", | |
| 267 | + "button \"Source for Canada, United Stat\" h=28" | |
| 268 | + ], | |
| 269 | + "sticky": [ | |
| 270 | + 53, | |
| 271 | + 105 | |
| 272 | + ], | |
| 273 | + "docH": 18042, | |
| 274 | + "errors": [] | |
| 275 | + }, | |
| 276 | + { | |
| 277 | + "name": "cmp-hero", | |
| 278 | + "path": "/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100", | |
| 279 | + "width": 375, | |
| 280 | + "overflow": 0, | |
| 281 | + "wide": [ | |
| 282 | + "li.group/chip.shrink-0 right=465", | |
| 283 | + "span.inline-flex.h-11.items-center right=465", | |
| 284 | + "span.max-w-[8rem].truncate.text-ink right=424", | |
| 285 | + "button.grid.h-11.w-9 right=464", | |
| 286 | + "svg.[object.SVGAnimatedString] right=453", | |
| 287 | + "path.[object.SVGAnimatedString] right=449" | |
| 288 | + ], | |
| 289 | + "small": [ | |
| 290 | + "a \"Skip to content\" 1x1" | |
| 291 | + ], | |
| 292 | + "smallH": [ | |
| 293 | + "a \"Skip to content\" h=1", | |
| 294 | + "button \"Source for Canada, United Stat\" h=28", | |
| 295 | + "a \"GDP (current US$)\" h=17", | |
| 296 | + "button \"Source for Canada, United Stat\" h=28", | |
| 297 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 298 | + "button \"Source for Canada, United Stat\" h=28", | |
| 299 | + "button \"Source for Canada, United Stat\" h=28", | |
| 300 | + "a \"Real GDP growth\" h=17", | |
| 301 | + "button \"Source for Canada, United Stat\" h=28", | |
| 302 | + "a \"GDP per capita growth\" h=17", | |
| 303 | + "button \"Source for Canada, United Stat\" h=28", | |
| 304 | + "a \"GDP (constant 2015 US$)\" h=17" | |
| 305 | + ], | |
| 306 | + "sticky": [ | |
| 307 | + 53, | |
| 308 | + 105 | |
| 309 | + ], | |
| 310 | + "docH": 18307, | |
| 311 | + "errors": [] | |
| 312 | + }, | |
| 313 | + { | |
| 314 | + "name": "rankings", | |
| 315 | + "path": "/rankings", | |
| 316 | + "width": 375, | |
| 317 | + "overflow": 0, | |
| 318 | + "wide": [], | |
| 319 | + "small": [ | |
| 320 | + "a \"Skip to content\" 1x1" | |
| 321 | + ], | |
| 322 | + "smallH": [ | |
| 323 | + "a \"Skip to content\" h=1", | |
| 324 | + "a \"contact@spboucher.ai\" h=15", | |
| 325 | + "a \"MacLustr\" h=15" | |
| 326 | + ], | |
| 327 | + "sticky": [ | |
| 328 | + 53, | |
| 329 | + 61 | |
| 330 | + ], | |
| 331 | + "docH": 24751, | |
| 332 | + "errors": [] | |
| 333 | + }, | |
| 334 | + { | |
| 335 | + "name": "rk-gdppc", | |
| 336 | + "path": "/rankings/gdp-per-capita", | |
| 337 | + "width": 375, | |
| 338 | + "overflow": 0, | |
| 339 | + "wide": [], | |
| 340 | + "small": [ | |
| 341 | + "a \"Skip to content\" 1x1" | |
| 342 | + ], | |
| 343 | + "smallH": [ | |
| 344 | + "a \"Skip to content\" h=1", | |
| 345 | + "select \"Year\" h=19", | |
| 346 | + "a \"contact@spboucher.ai\" h=15", | |
| 347 | + "a \"MacLustr\" h=15" | |
| 348 | + ], | |
| 349 | + "sticky": [ | |
| 350 | + 53, | |
| 351 | + 61 | |
| 352 | + ], | |
| 353 | + "docH": 4695, | |
| 354 | + "errors": [] | |
| 355 | + }, | |
| 356 | + { | |
| 357 | + "name": "rk-life-oecd", | |
| 358 | + "path": "/rankings/life-expectancy?group=oecd", | |
| 359 | + "width": 375, | |
| 360 | + "overflow": 0, | |
| 361 | + "wide": [], | |
| 362 | + "small": [ | |
| 363 | + "a \"Skip to content\" 1x1" | |
| 364 | + ], | |
| 365 | + "smallH": [ | |
| 366 | + "a \"Skip to content\" h=1", | |
| 367 | + "select \"Year\" h=19", | |
| 368 | + "a \"contact@spboucher.ai\" h=15", | |
| 369 | + "a \"MacLustr\" h=15" | |
| 370 | + ], | |
| 371 | + "sticky": [ | |
| 372 | + 53, | |
| 373 | + 61 | |
| 374 | + ], | |
| 375 | + "docH": 4614, | |
| 376 | + "errors": [] | |
| 377 | + }, | |
| 378 | + { | |
| 379 | + "name": "compare", | |
| 380 | + "path": "/compare", | |
| 381 | + "width": 390, | |
| 382 | + "overflow": 0, | |
| 383 | + "wide": [], | |
| 384 | + "small": [ | |
| 385 | + "a \"Skip to content\" 1x1" | |
| 386 | + ], | |
| 387 | + "smallH": [ | |
| 388 | + "a \"Skip to content\" h=1", | |
| 389 | + "a \"contact@spboucher.ai\" h=15", | |
| 390 | + "a \"MacLustr\" h=15" | |
| 391 | + ], | |
| 392 | + "sticky": [ | |
| 393 | + 53, | |
| 394 | + 61 | |
| 395 | + ], | |
| 396 | + "docH": 2491, | |
| 397 | + "errors": [] | |
| 398 | + }, | |
| 399 | + { | |
| 400 | + "name": "cmp-snapshot", | |
| 401 | + "path": "/compare/canada/united-states/france", | |
| 402 | + "width": 390, | |
| 403 | + "overflow": 0, | |
| 404 | + "wide": [ | |
| 405 | + "li.group/chip.shrink-0 right=465", | |
| 406 | + "span.inline-flex.h-11.items-center right=465", | |
| 407 | + "span.max-w-[8rem].truncate.text-ink right=424", | |
| 408 | + "button.grid.h-11.w-9 right=464", | |
| 409 | + "svg.[object.SVGAnimatedString] right=453", | |
| 410 | + "path.[object.SVGAnimatedString] right=449" | |
| 411 | + ], | |
| 412 | + "small": [ | |
| 413 | + "a \"Skip to content\" 1x1" | |
| 414 | + ], | |
| 415 | + "smallH": [ | |
| 416 | + "a \"Skip to content\" h=1", | |
| 417 | + "a \"contact@spboucher.ai\" h=15", | |
| 418 | + "a \"MacLustr\" h=15" | |
| 419 | + ], | |
| 420 | + "sticky": [ | |
| 421 | + 53, | |
| 422 | + 105 | |
| 423 | + ], | |
| 424 | + "docH": 4031, | |
| 425 | + "errors": [] | |
| 426 | + }, | |
| 427 | + { | |
| 428 | + "name": "cmp-economy", | |
| 429 | + "path": "/compare/canada/united-states/france?tab=economy", | |
| 430 | + "width": 390, | |
| 431 | + "overflow": 0, | |
| 432 | + "wide": [ | |
| 433 | + "li.group/chip.shrink-0 right=465", | |
| 434 | + "span.inline-flex.h-11.items-center right=465", | |
| 435 | + "span.max-w-[8rem].truncate.text-ink right=424", | |
| 436 | + "button.grid.h-11.w-9 right=464", | |
| 437 | + "svg.[object.SVGAnimatedString] right=453", | |
| 438 | + "path.[object.SVGAnimatedString] right=449" | |
| 439 | + ], | |
| 440 | + "small": [ | |
| 441 | + "a \"Skip to content\" 1x1" | |
| 442 | + ], | |
| 443 | + "smallH": [ | |
| 444 | + "a \"Skip to content\" h=1", | |
| 445 | + "a \"GDP (current US$)\" h=17", | |
| 446 | + "button \"Source for Canada, United Stat\" h=28", | |
| 447 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 448 | + "button \"Source for Canada, United Stat\" h=28", | |
| 449 | + "a \"GDP per capita (current US$)\" h=17", | |
| 450 | + "button \"Source for Canada, United Stat\" h=28", | |
| 451 | + "button \"Source for Canada, United Stat\" h=28", | |
| 452 | + "a \"Real GDP growth\" h=17", | |
| 453 | + "button \"Source for Canada, United Stat\" h=28", | |
| 454 | + "a \"GDP per capita growth\" h=17", | |
| 455 | + "button \"Source for Canada, United Stat\" h=28" | |
| 456 | + ], | |
| 457 | + "sticky": [ | |
| 458 | + 53, | |
| 459 | + 105 | |
| 460 | + ], | |
| 461 | + "docH": 17834, | |
| 462 | + "errors": [] | |
| 463 | + }, | |
| 464 | + { | |
| 465 | + "name": "cmp-hero", | |
| 466 | + "path": "/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100", | |
| 467 | + "width": 390, | |
| 468 | + "overflow": 0, | |
| 469 | + "wide": [ | |
| 470 | + "li.group/chip.shrink-0 right=465", | |
| 471 | + "span.inline-flex.h-11.items-center right=465", | |
| 472 | + "span.max-w-[8rem].truncate.text-ink right=424", | |
| 473 | + "button.grid.h-11.w-9 right=464", | |
| 474 | + "svg.[object.SVGAnimatedString] right=453", | |
| 475 | + "path.[object.SVGAnimatedString] right=449" | |
| 476 | + ], | |
| 477 | + "small": [ | |
| 478 | + "a \"Skip to content\" 1x1" | |
| 479 | + ], | |
| 480 | + "smallH": [ | |
| 481 | + "a \"Skip to content\" h=1", | |
| 482 | + "button \"Source for Canada, United Stat\" h=28", | |
| 483 | + "a \"GDP (current US$)\" h=17", | |
| 484 | + "button \"Source for Canada, United Stat\" h=28", | |
| 485 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 486 | + "button \"Source for Canada, United Stat\" h=28", | |
| 487 | + "button \"Source for Canada, United Stat\" h=28", | |
| 488 | + "a \"Real GDP growth\" h=17", | |
| 489 | + "button \"Source for Canada, United Stat\" h=28", | |
| 490 | + "a \"GDP per capita growth\" h=17", | |
| 491 | + "button \"Source for Canada, United Stat\" h=28", | |
| 492 | + "a \"GDP (constant 2015 US$)\" h=17" | |
| 493 | + ], | |
| 494 | + "sticky": [ | |
| 495 | + 53, | |
| 496 | + 105 | |
| 497 | + ], | |
| 498 | + "docH": 18171, | |
| 499 | + "errors": [] | |
| 500 | + }, | |
| 501 | + { | |
| 502 | + "name": "rankings", | |
| 503 | + "path": "/rankings", | |
| 504 | + "width": 390, | |
| 505 | + "overflow": 0, | |
| 506 | + "wide": [], | |
| 507 | + "small": [ | |
| 508 | + "a \"Skip to content\" 1x1" | |
| 509 | + ], | |
| 510 | + "smallH": [ | |
| 511 | + "a \"Skip to content\" h=1", | |
| 512 | + "a \"contact@spboucher.ai\" h=15", | |
| 513 | + "a \"MacLustr\" h=15" | |
| 514 | + ], | |
| 515 | + "sticky": [ | |
| 516 | + 53, | |
| 517 | + 61 | |
| 518 | + ], | |
| 519 | + "docH": 24327, | |
| 520 | + "errors": [] | |
| 521 | + }, | |
| 522 | + { | |
| 523 | + "name": "rk-gdppc", | |
| 524 | + "path": "/rankings/gdp-per-capita", | |
| 525 | + "width": 390, | |
| 526 | + "overflow": 0, | |
| 527 | + "wide": [], | |
| 528 | + "small": [ | |
| 529 | + "a \"Skip to content\" 1x1" | |
| 530 | + ], | |
| 531 | + "smallH": [ | |
| 532 | + "a \"Skip to content\" h=1", | |
| 533 | + "select \"Year\" h=19", | |
| 534 | + "a \"contact@spboucher.ai\" h=15", | |
| 535 | + "a \"MacLustr\" h=15" | |
| 536 | + ], | |
| 537 | + "sticky": [ | |
| 538 | + 53, | |
| 539 | + 61 | |
| 540 | + ], | |
| 541 | + "docH": 4623, | |
| 542 | + "errors": [] | |
| 543 | + }, | |
| 544 | + { | |
| 545 | + "name": "rk-life-oecd", | |
| 546 | + "path": "/rankings/life-expectancy?group=oecd", | |
| 547 | + "width": 390, | |
| 548 | + "overflow": 0, | |
| 549 | + "wide": [], | |
| 550 | + "small": [ | |
| 551 | + "a \"Skip to content\" 1x1" | |
| 552 | + ], | |
| 553 | + "smallH": [ | |
| 554 | + "a \"Skip to content\" h=1", | |
| 555 | + "select \"Year\" h=19", | |
| 556 | + "a \"contact@spboucher.ai\" h=15", | |
| 557 | + "a \"MacLustr\" h=15" | |
| 558 | + ], | |
| 559 | + "sticky": [ | |
| 560 | + 53, | |
| 561 | + 61 | |
| 562 | + ], | |
| 563 | + "docH": 4603, | |
| 564 | + "errors": [] | |
| 565 | + }, | |
| 566 | + { | |
| 567 | + "name": "compare", | |
| 568 | + "path": "/compare", | |
| 569 | + "width": 430, | |
| 570 | + "overflow": 0, | |
| 571 | + "wide": [], | |
| 572 | + "small": [ | |
| 573 | + "a \"Skip to content\" 1x1" | |
| 574 | + ], | |
| 575 | + "smallH": [ | |
| 576 | + "a \"Skip to content\" h=1", | |
| 577 | + "a \"contact@spboucher.ai\" h=15", | |
| 578 | + "a \"MacLustr\" h=15" | |
| 579 | + ], | |
| 580 | + "sticky": [ | |
| 581 | + 53, | |
| 582 | + 61 | |
| 583 | + ], | |
| 584 | + "docH": 2454, | |
| 585 | + "errors": [] | |
| 586 | + }, | |
| 587 | + { | |
| 588 | + "name": "cmp-snapshot", | |
| 589 | + "path": "/compare/canada/united-states/france", | |
| 590 | + "width": 430, | |
| 591 | + "overflow": 0, | |
| 592 | + "wide": [ | |
| 593 | + "li.group/chip.shrink-0 right=465", | |
| 594 | + "span.inline-flex.h-11.items-center right=465", | |
| 595 | + "button.grid.h-11.w-9 right=464", | |
| 596 | + "svg.[object.SVGAnimatedString] right=453", | |
| 597 | + "path.[object.SVGAnimatedString] right=449", | |
| 598 | + "path.[object.SVGAnimatedString] right=449" | |
| 599 | + ], | |
| 600 | + "small": [ | |
| 601 | + "a \"Skip to content\" 1x1" | |
| 602 | + ], | |
| 603 | + "smallH": [ | |
| 604 | + "a \"Skip to content\" h=1", | |
| 605 | + "a \"contact@spboucher.ai\" h=15", | |
| 606 | + "a \"MacLustr\" h=15" | |
| 607 | + ], | |
| 608 | + "sticky": [ | |
| 609 | + 53, | |
| 610 | + 105 | |
| 611 | + ], | |
| 612 | + "docH": 3998, | |
| 613 | + "errors": [] | |
| 614 | + }, | |
| 615 | + { | |
| 616 | + "name": "cmp-economy", | |
| 617 | + "path": "/compare/canada/united-states/france?tab=economy", | |
| 618 | + "width": 430, | |
| 619 | + "overflow": 0, | |
| 620 | + "wide": [ | |
| 621 | + "li.group/chip.shrink-0 right=465", | |
| 622 | + "span.inline-flex.h-11.items-center right=465", | |
| 623 | + "button.grid.h-11.w-9 right=464", | |
| 624 | + "svg.[object.SVGAnimatedString] right=453", | |
| 625 | + "path.[object.SVGAnimatedString] right=449", | |
| 626 | + "path.[object.SVGAnimatedString] right=449" | |
| 627 | + ], | |
| 628 | + "small": [ | |
| 629 | + "a \"Skip to content\" 1x1" | |
| 630 | + ], | |
| 631 | + "smallH": [ | |
| 632 | + "a \"Skip to content\" h=1", | |
| 633 | + "a \"GDP (current US$)\" h=17", | |
| 634 | + "button \"Source for Canada, United Stat\" h=28", | |
| 635 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 636 | + "button \"Source for Canada, United Stat\" h=28", | |
| 637 | + "a \"GDP per capita (current US$)\" h=17", | |
| 638 | + "button \"Source for Canada, United Stat\" h=28", | |
| 639 | + "a \"GDP per capita, PPP (current i\" h=17", | |
| 640 | + "button \"Source for Canada, United Stat\" h=28", | |
| 641 | + "a \"Real GDP growth\" h=17", | |
| 642 | + "button \"Source for Canada, United Stat\" h=28", | |
| 643 | + "a \"GDP per capita growth\" h=17" | |
| 644 | + ], | |
| 645 | + "sticky": [ | |
| 646 | + 53, | |
| 647 | + 105 | |
| 648 | + ], | |
| 649 | + "docH": 16968, | |
| 650 | + "errors": [] | |
| 651 | + }, | |
| 652 | + { | |
| 653 | + "name": "cmp-hero", | |
| 654 | + "path": "/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100", | |
| 655 | + "width": 430, | |
| 656 | + "overflow": 0, | |
| 657 | + "wide": [ | |
| 658 | + "li.group/chip.shrink-0 right=465", | |
| 659 | + "span.inline-flex.h-11.items-center right=465", | |
| 660 | + "button.grid.h-11.w-9 right=464", | |
| 661 | + "svg.[object.SVGAnimatedString] right=453", | |
| 662 | + "path.[object.SVGAnimatedString] right=449", | |
| 663 | + "path.[object.SVGAnimatedString] right=449" | |
| 664 | + ], | |
| 665 | + "small": [ | |
| 666 | + "a \"Skip to content\" 1x1" | |
| 667 | + ], | |
| 668 | + "smallH": [ | |
| 669 | + "a \"Skip to content\" h=1", | |
| 670 | + "button \"Source for Canada, United Stat\" h=28", | |
| 671 | + "a \"GDP (current US$)\" h=17", | |
| 672 | + "button \"Source for Canada, United Stat\" h=28", | |
| 673 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 674 | + "button \"Source for Canada, United Stat\" h=28", | |
| 675 | + "a \"GDP per capita, PPP (current i\" h=17", | |
| 676 | + "button \"Source for Canada, United Stat\" h=28", | |
| 677 | + "a \"Real GDP growth\" h=17", | |
| 678 | + "button \"Source for Canada, United Stat\" h=28", | |
| 679 | + "a \"GDP per capita growth\" h=17", | |
| 680 | + "button \"Source for Canada, United Stat\" h=28" | |
| 681 | + ], | |
| 682 | + "sticky": [ | |
| 683 | + 53, | |
| 684 | + 105 | |
| 685 | + ], | |
| 686 | + "docH": 17269, | |
| 687 | + "errors": [] | |
| 688 | + }, | |
| 689 | + { | |
| 690 | + "name": "rankings", | |
| 691 | + "path": "/rankings", | |
| 692 | + "width": 430, | |
| 693 | + "overflow": 0, | |
| 694 | + "wide": [], | |
| 695 | + "small": [ | |
| 696 | + "a \"Skip to content\" 1x1" | |
| 697 | + ], | |
| 698 | + "smallH": [ | |
| 699 | + "a \"Skip to content\" h=1", | |
| 700 | + "a \"contact@spboucher.ai\" h=15", | |
| 701 | + "a \"MacLustr\" h=15" | |
| 702 | + ], | |
| 703 | + "sticky": [ | |
| 704 | + 53, | |
| 705 | + 61 | |
| 706 | + ], | |
| 707 | + "docH": 23937, | |
| 708 | + "errors": [] | |
| 709 | + }, | |
| 710 | + { | |
| 711 | + "name": "rk-gdppc", | |
| 712 | + "path": "/rankings/gdp-per-capita", | |
| 713 | + "width": 430, | |
| 714 | + "overflow": 0, | |
| 715 | + "wide": [], | |
| 716 | + "small": [ | |
| 717 | + "a \"Skip to content\" 1x1" | |
| 718 | + ], | |
| 719 | + "smallH": [ | |
| 720 | + "a \"Skip to content\" h=1", | |
| 721 | + "select \"Year\" h=19", | |
| 722 | + "a \"contact@spboucher.ai\" h=15", | |
| 723 | + "a \"MacLustr\" h=15" | |
| 724 | + ], | |
| 725 | + "sticky": [ | |
| 726 | + 53, | |
| 727 | + 61 | |
| 728 | + ], | |
| 729 | + "docH": 4583, | |
| 730 | + "errors": [] | |
| 731 | + }, | |
| 732 | + { | |
| 733 | + "name": "rk-life-oecd", | |
| 734 | + "path": "/rankings/life-expectancy?group=oecd", | |
| 735 | + "width": 430, | |
| 736 | + "overflow": 0, | |
| 737 | + "wide": [], | |
| 738 | + "small": [ | |
| 739 | + "a \"Skip to content\" 1x1" | |
| 740 | + ], | |
| 741 | + "smallH": [ | |
| 742 | + "a \"Skip to content\" h=1", | |
| 743 | + "select \"Year\" h=19", | |
| 744 | + "a \"contact@spboucher.ai\" h=15", | |
| 745 | + "a \"MacLustr\" h=15" | |
| 746 | + ], | |
| 747 | + "sticky": [ | |
| 748 | + 53, | |
| 749 | + 61 | |
| 750 | + ], | |
| 751 | + "docH": 4562, | |
| 752 | + "errors": [] | |
| 753 | + }, | |
| 754 | + { | |
| 755 | + "name": "compare", | |
| 756 | + "path": "/compare", | |
| 757 | + "width": 1280, | |
| 758 | + "overflow": 0, | |
| 759 | + "wide": [], | |
| 760 | + "small": [ | |
| 761 | + "a \"Skip to content\" 1x1", | |
| 762 | + "a \"API\" 22x32" | |
| 763 | + ], | |
| 764 | + "smallH": [ | |
| 765 | + "a \"Skip to content\" h=1", | |
| 766 | + "a \"contact@spboucher.ai\" h=15", | |
| 767 | + "a \"MacLustr\" h=15" | |
| 768 | + ], | |
| 769 | + "sticky": [ | |
| 770 | + 57, | |
| 771 | + 40 | |
| 772 | + ], | |
| 773 | + "docH": 1359, | |
| 774 | + "errors": [] | |
| 775 | + }, | |
| 776 | + { | |
| 777 | + "name": "cmp-snapshot", | |
| 778 | + "path": "/compare/canada/united-states/france", | |
| 779 | + "width": 1280, | |
| 780 | + "overflow": 0, | |
| 781 | + "wide": [], | |
| 782 | + "small": [ | |
| 783 | + "a \"Skip to content\" 1x1", | |
| 784 | + "button \"Move Canada up\" 24x36", | |
| 785 | + "button \"Move Canada down\" 24x36", | |
| 786 | + "button \"Remove Canada from the compari\" 28x36", | |
| 787 | + "button \"Move United States up\" 24x36", | |
| 788 | + "button \"Move United States down\" 24x36", | |
| 789 | + "button \"Remove United States from the \" 28x36", | |
| 790 | + "button \"Move France up\" 24x36", | |
| 791 | + "button \"Move France down\" 24x36", | |
| 792 | + "button \"Remove France from the compari\" 28x36", | |
| 793 | + "a \"API\" 22x32" | |
| 794 | + ], | |
| 795 | + "smallH": [ | |
| 796 | + "a \"Skip to content\" h=1", | |
| 797 | + "a \"🇨🇦Canada\" h=18", | |
| 798 | + "a \"🇺🇸United States\" h=18", | |
| 799 | + "a \"🇫🇷France\" h=18", | |
| 800 | + "a \"contact@spboucher.ai\" h=15", | |
| 801 | + "a \"MacLustr\" h=15" | |
| 802 | + ], | |
| 803 | + "sticky": [ | |
| 804 | + 57, | |
| 805 | + 142 | |
| 806 | + ], | |
| 807 | + "docH": 1759, | |
| 808 | + "errors": [] | |
| 809 | + }, | |
| 810 | + { | |
| 811 | + "name": "cmp-economy", | |
| 812 | + "path": "/compare/canada/united-states/france?tab=economy", | |
| 813 | + "width": 1280, | |
| 814 | + "overflow": 0, | |
| 815 | + "wide": [], | |
| 816 | + "small": [ | |
| 817 | + "a \"Skip to content\" 1x1", | |
| 818 | + "button \"Move Canada up\" 24x36", | |
| 819 | + "button \"Move Canada down\" 24x36", | |
| 820 | + "button \"Remove Canada from the compari\" 28x36", | |
| 821 | + "button \"Move United States up\" 24x36", | |
| 822 | + "button \"Move United States down\" 24x36", | |
| 823 | + "button \"Remove United States from the \" 28x36", | |
| 824 | + "button \"Move France up\" 24x36", | |
| 825 | + "button \"Move France down\" 24x36", | |
| 826 | + "button \"Remove France from the compari\" 28x36", | |
| 827 | + "input \"\" 13x13", | |
| 828 | + "a \"API\" 22x32" | |
| 829 | + ], | |
| 830 | + "smallH": [ | |
| 831 | + "a \"Skip to content\" h=1", | |
| 832 | + "select \"From\" h=19", | |
| 833 | + "select \"To\" h=19", | |
| 834 | + "input \"\" h=13", | |
| 835 | + "a \"GDP (current US$)\" h=17", | |
| 836 | + "button \"Source for Canada, United Stat\" h=28", | |
| 837 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 838 | + "button \"Source for Canada, United Stat\" h=28", | |
| 839 | + "a \"GDP per capita (current US$)\" h=17", | |
| 840 | + "button \"Source for Canada, United Stat\" h=28", | |
| 841 | + "a \"GDP per capita, PPP (current i\" h=17", | |
| 842 | + "button \"Source for Canada, United Stat\" h=28" | |
| 843 | + ], | |
| 844 | + "sticky": [ | |
| 845 | + 57, | |
| 846 | + 142 | |
| 847 | + ], | |
| 848 | + "docH": 7715, | |
| 849 | + "errors": [] | |
| 850 | + }, | |
| 851 | + { | |
| 852 | + "name": "cmp-hero", | |
| 853 | + "path": "/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100", | |
| 854 | + "width": 1280, | |
| 855 | + "overflow": 0, | |
| 856 | + "wide": [], | |
| 857 | + "small": [ | |
| 858 | + "a \"Skip to content\" 1x1", | |
| 859 | + "button \"Move Canada up\" 24x36", | |
| 860 | + "button \"Move Canada down\" 24x36", | |
| 861 | + "button \"Remove Canada from the compari\" 28x36", | |
| 862 | + "button \"Move United States up\" 24x36", | |
| 863 | + "button \"Move United States down\" 24x36", | |
| 864 | + "button \"Remove United States from the \" 28x36", | |
| 865 | + "button \"Move France up\" 24x36", | |
| 866 | + "button \"Move France down\" 24x36", | |
| 867 | + "button \"Remove France from the compari\" 28x36", | |
| 868 | + "input \"\" 13x13", | |
| 869 | + "button \"10 y\" 42x32" | |
| 870 | + ], | |
| 871 | + "smallH": [ | |
| 872 | + "a \"Skip to content\" h=1", | |
| 873 | + "select \"From\" h=19", | |
| 874 | + "select \"To\" h=19", | |
| 875 | + "input \"\" h=13", | |
| 876 | + "a \"GDP per capita (current US$)\" h=26", | |
| 877 | + "button \"Source for Canada, United Stat\" h=28", | |
| 878 | + "a \"GDP (current US$)\" h=17", | |
| 879 | + "button \"Source for Canada, United Stat\" h=28", | |
| 880 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 881 | + "button \"Source for Canada, United Stat\" h=28", | |
| 882 | + "a \"GDP per capita, PPP (current i\" h=17", | |
| 883 | + "button \"Source for Canada, United Stat\" h=28" | |
| 884 | + ], | |
| 885 | + "sticky": [ | |
| 886 | + 57, | |
| 887 | + 142 | |
| 888 | + ], | |
| 889 | + "docH": 8304, | |
| 890 | + "errors": [] | |
| 891 | + }, | |
| 892 | + { | |
| 893 | + "name": "rankings", | |
| 894 | + "path": "/rankings", | |
| 895 | + "width": 1280, | |
| 896 | + "overflow": 0, | |
| 897 | + "wide": [], | |
| 898 | + "small": [ | |
| 899 | + "a \"Skip to content\" 1x1", | |
| 900 | + "a \"API\" 22x32" | |
| 901 | + ], | |
| 902 | + "smallH": [ | |
| 903 | + "a \"Skip to content\" h=1", | |
| 904 | + "a \"contact@spboucher.ai\" h=15", | |
| 905 | + "a \"MacLustr\" h=15" | |
| 906 | + ], | |
| 907 | + "sticky": [ | |
| 908 | + 57, | |
| 909 | + 64 | |
| 910 | + ], | |
| 911 | + "docH": 10330, | |
| 912 | + "errors": [] | |
| 913 | + }, | |
| 914 | + { | |
| 915 | + "name": "rk-gdppc", | |
| 916 | + "path": "/rankings/gdp-per-capita", | |
| 917 | + "width": 1280, | |
| 918 | + "overflow": 0, | |
| 919 | + "wide": [], | |
| 920 | + "small": [ | |
| 921 | + "a \"Skip to content\" 1x1", | |
| 922 | + "button \"Remove Luxembourg\" 28x36", | |
| 923 | + "button \"Remove Ireland\" 28x36", | |
| 924 | + "button \"Remove Switzerland\" 28x36", | |
| 925 | + "a \"API\" 22x32" | |
| 926 | + ], | |
| 927 | + "smallH": [ | |
| 928 | + "a \"Skip to content\" h=1", | |
| 929 | + "a \"Rankings\" h=18", | |
| 930 | + "a \"Economy\" h=18", | |
| 931 | + "select \"Year\" h=19", | |
| 932 | + "select \"Group\" h=19", | |
| 933 | + "a \"contact@spboucher.ai\" h=15", | |
| 934 | + "a \"MacLustr\" h=15" | |
| 935 | + ], | |
| 936 | + "sticky": [ | |
| 937 | + 57 | |
| 938 | + ], | |
| 939 | + "docH": 2667, | |
| 940 | + "errors": [] | |
| 941 | + }, | |
| 942 | + { | |
| 943 | + "name": "rk-life-oecd", | |
| 944 | + "path": "/rankings/life-expectancy?group=oecd", | |
| 945 | + "width": 1280, | |
| 946 | + "overflow": 0, | |
| 947 | + "wide": [], | |
| 948 | + "small": [ | |
| 949 | + "a \"Skip to content\" 1x1", | |
| 950 | + "a \"Health\" 37x18", | |
| 951 | + "button \"Remove Switzerland\" 28x36", | |
| 952 | + "button \"Remove Sweden\" 28x36", | |
| 953 | + "button \"Remove Japan\" 28x36", | |
| 954 | + "a \"API\" 22x32" | |
| 955 | + ], | |
| 956 | + "smallH": [ | |
| 957 | + "a \"Skip to content\" h=1", | |
| 958 | + "a \"Rankings\" h=18", | |
| 959 | + "a \"Health\" h=18", | |
| 960 | + "select \"Year\" h=19", | |
| 961 | + "select \"Group\" h=19", | |
| 962 | + "a \"contact@spboucher.ai\" h=15", | |
| 963 | + "a \"MacLustr\" h=15" | |
| 964 | + ], | |
| 965 | + "sticky": [ | |
| 966 | + 57 | |
| 967 | + ], | |
| 968 | + "docH": 2667, | |
| 969 | + "errors": [] | |
| 970 | + }, | |
| 971 | + { | |
| 972 | + "name": "compare", | |
| 973 | + "path": "/compare", | |
| 974 | + "width": 1440, | |
| 975 | + "overflow": 0, | |
| 976 | + "wide": [], | |
| 977 | + "small": [ | |
| 978 | + "a \"Skip to content\" 1x1", | |
| 979 | + "a \"API\" 22x32" | |
| 980 | + ], | |
| 981 | + "smallH": [ | |
| 982 | + "a \"Skip to content\" h=1", | |
| 983 | + "a \"contact@spboucher.ai\" h=15", | |
| 984 | + "a \"MacLustr\" h=15" | |
| 985 | + ], | |
| 986 | + "sticky": [ | |
| 987 | + 57, | |
| 988 | + 40 | |
| 989 | + ], | |
| 990 | + "docH": 1359, | |
| 991 | + "errors": [] | |
| 992 | + }, | |
| 993 | + { | |
| 994 | + "name": "cmp-snapshot", | |
| 995 | + "path": "/compare/canada/united-states/france", | |
| 996 | + "width": 1440, | |
| 997 | + "overflow": 0, | |
| 998 | + "wide": [], | |
| 999 | + "small": [ | |
| 1000 | + "a \"Skip to content\" 1x1", | |
| 1001 | + "button \"Move Canada up\" 24x36", | |
| 1002 | + "button \"Move Canada down\" 24x36", | |
| 1003 | + "button \"Remove Canada from the compari\" 28x36", | |
| 1004 | + "button \"Move United States up\" 24x36", | |
| 1005 | + "button \"Move United States down\" 24x36", | |
| 1006 | + "button \"Remove United States from the \" 28x36", | |
| 1007 | + "button \"Move France up\" 24x36", | |
| 1008 | + "button \"Move France down\" 24x36", | |
| 1009 | + "button \"Remove France from the compari\" 28x36", | |
| 1010 | + "a \"API\" 22x32" | |
| 1011 | + ], | |
| 1012 | + "smallH": [ | |
| 1013 | + "a \"Skip to content\" h=1", | |
| 1014 | + "a \"🇨🇦Canada\" h=18", | |
| 1015 | + "a \"🇺🇸United States\" h=18", | |
| 1016 | + "a \"🇫🇷France\" h=18", | |
| 1017 | + "a \"contact@spboucher.ai\" h=15", | |
| 1018 | + "a \"MacLustr\" h=15" | |
| 1019 | + ], | |
| 1020 | + "sticky": [ | |
| 1021 | + 57, | |
| 1022 | + 142 | |
| 1023 | + ], | |
| 1024 | + "docH": 1759, | |
| 1025 | + "errors": [] | |
| 1026 | + }, | |
| 1027 | + { | |
| 1028 | + "name": "cmp-economy", | |
| 1029 | + "path": "/compare/canada/united-states/france?tab=economy", | |
| 1030 | + "width": 1440, | |
| 1031 | + "overflow": 0, | |
| 1032 | + "wide": [], | |
| 1033 | + "small": [ | |
| 1034 | + "a \"Skip to content\" 1x1", | |
| 1035 | + "button \"Move Canada up\" 24x36", | |
| 1036 | + "button \"Move Canada down\" 24x36", | |
| 1037 | + "button \"Remove Canada from the compari\" 28x36", | |
| 1038 | + "button \"Move United States up\" 24x36", | |
| 1039 | + "button \"Move United States down\" 24x36", | |
| 1040 | + "button \"Remove United States from the \" 28x36", | |
| 1041 | + "button \"Move France up\" 24x36", | |
| 1042 | + "button \"Move France down\" 24x36", | |
| 1043 | + "button \"Remove France from the compari\" 28x36", | |
| 1044 | + "input \"\" 13x13", | |
| 1045 | + "a \"API\" 22x32" | |
| 1046 | + ], | |
| 1047 | + "smallH": [ | |
| 1048 | + "a \"Skip to content\" h=1", | |
| 1049 | + "select \"From\" h=19", | |
| 1050 | + "select \"To\" h=19", | |
| 1051 | + "input \"\" h=13", | |
| 1052 | + "a \"GDP (current US$)\" h=17", | |
| 1053 | + "button \"Source for Canada, United Stat\" h=28", | |
| 1054 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 1055 | + "button \"Source for Canada, United Stat\" h=28", | |
| 1056 | + "a \"GDP per capita (current US$)\" h=17", | |
| 1057 | + "button \"Source for Canada, United Stat\" h=28", | |
| 1058 | + "a \"GDP per capita, PPP (current i\" h=17", | |
| 1059 | + "button \"Source for Canada, United Stat\" h=28" | |
| 1060 | + ], | |
| 1061 | + "sticky": [ | |
| 1062 | + 57, | |
| 1063 | + 142 | |
| 1064 | + ], | |
| 1065 | + "docH": 7705, | |
| 1066 | + "errors": [] | |
| 1067 | + }, | |
| 1068 | + { | |
| 1069 | + "name": "cmp-hero", | |
| 1070 | + "path": "/compare/canada/united-states/france?tab=economy&indicator=gdp-per-capita&from=1990&mode=index100", | |
| 1071 | + "width": 1440, | |
| 1072 | + "overflow": 0, | |
| 1073 | + "wide": [], | |
| 1074 | + "small": [ | |
| 1075 | + "a \"Skip to content\" 1x1", | |
| 1076 | + "button \"Move Canada up\" 24x36", | |
| 1077 | + "button \"Move Canada down\" 24x36", | |
| 1078 | + "button \"Remove Canada from the compari\" 28x36", | |
| 1079 | + "button \"Move United States up\" 24x36", | |
| 1080 | + "button \"Move United States down\" 24x36", | |
| 1081 | + "button \"Remove United States from the \" 28x36", | |
| 1082 | + "button \"Move France up\" 24x36", | |
| 1083 | + "button \"Move France down\" 24x36", | |
| 1084 | + "button \"Remove France from the compari\" 28x36", | |
| 1085 | + "input \"\" 13x13", | |
| 1086 | + "button \"10 y\" 42x32" | |
| 1087 | + ], | |
| 1088 | + "smallH": [ | |
| 1089 | + "a \"Skip to content\" h=1", | |
| 1090 | + "select \"From\" h=19", | |
| 1091 | + "select \"To\" h=19", | |
| 1092 | + "input \"\" h=13", | |
| 1093 | + "a \"GDP per capita (current US$)\" h=26", | |
| 1094 | + "button \"Source for Canada, United Stat\" h=28", | |
| 1095 | + "a \"GDP (current US$)\" h=17", | |
| 1096 | + "button \"Source for Canada, United Stat\" h=28", | |
| 1097 | + "a \"GDP, PPP (current internationa\" h=17", | |
| 1098 | + "button \"Source for Canada, United Stat\" h=28", | |
| 1099 | + "a \"GDP per capita, PPP (current i\" h=17", | |
| 1100 | + "button \"Source for Canada, United Stat\" h=28" | |
| 1101 | + ], | |
| 1102 | + "sticky": [ | |
| 1103 | + 57, | |
| 1104 | + 142 | |
| 1105 | + ], | |
| 1106 | + "docH": 8294, | |
| 1107 | + "errors": [] | |
| 1108 | + }, | |
| 1109 | + { | |
| 1110 | + "name": "rankings", | |
| 1111 | + "path": "/rankings", | |
| 1112 | + "width": 1440, | |
| 1113 | + "overflow": 0, | |
| 1114 | + "wide": [], | |
| 1115 | + "small": [ | |
| 1116 | + "a \"Skip to content\" 1x1", | |
| 1117 | + "a \"API\" 22x32" | |
| 1118 | + ], | |
| 1119 | + "smallH": [ | |
| 1120 | + "a \"Skip to content\" h=1", | |
| 1121 | + "a \"contact@spboucher.ai\" h=15", | |
| 1122 | + "a \"MacLustr\" h=15" | |
| 1123 | + ], | |
| 1124 | + "sticky": [ | |
| 1125 | + 57, | |
| 1126 | + 64 | |
| 1127 | + ], | |
| 1128 | + "docH": 10106, | |
| 1129 | + "errors": [] | |
| 1130 | + }, | |
| 1131 | + { | |
| 1132 | + "name": "rk-gdppc", | |
| 1133 | + "path": "/rankings/gdp-per-capita", | |
| 1134 | + "width": 1440, | |
| 1135 | + "overflow": 0, | |
| 1136 | + "wide": [], | |
| 1137 | + "small": [ | |
| 1138 | + "a \"Skip to content\" 1x1", | |
| 1139 | + "button \"Remove Luxembourg\" 28x36", | |
| 1140 | + "button \"Remove Ireland\" 28x36", | |
| 1141 | + "button \"Remove Switzerland\" 28x36", | |
| 1142 | + "a \"API\" 22x32" | |
| 1143 | + ], | |
| 1144 | + "smallH": [ | |
| 1145 | + "a \"Skip to content\" h=1", | |
| 1146 | + "a \"Rankings\" h=18", | |
| 1147 | + "a \"Economy\" h=18", | |
| 1148 | + "select \"Year\" h=19", | |
| 1149 | + "select \"Group\" h=19", | |
| 1150 | + "a \"contact@spboucher.ai\" h=15", | |
| 1151 | + "a \"MacLustr\" h=15" | |
| 1152 | + ], | |
| 1153 | + "sticky": [ | |
| 1154 | + 57 | |
| 1155 | + ], | |
| 1156 | + "docH": 2667, | |
| 1157 | + "errors": [] | |
| 1158 | + }, | |
| 1159 | + { | |
| 1160 | + "name": "rk-life-oecd", | |
| 1161 | + "path": "/rankings/life-expectancy?group=oecd", | |
| 1162 | + "width": 1440, | |
| 1163 | + "overflow": 0, | |
| 1164 | + "wide": [], | |
| 1165 | + "small": [ | |
| 1166 | + "a \"Skip to content\" 1x1", | |
| 1167 | + "a \"Health\" 37x18", | |
| 1168 | + "button \"Remove Switzerland\" 28x36", | |
| 1169 | + "button \"Remove Sweden\" 28x36", | |
| 1170 | + "button \"Remove Japan\" 28x36", | |
| 1171 | + "a \"API\" 22x32" | |
| 1172 | + ], | |
| 1173 | + "smallH": [ | |
| 1174 | + "a \"Skip to content\" h=1", | |
| 1175 | + "a \"Rankings\" h=18", | |
| 1176 | + "a \"Health\" h=18", | |
| 1177 | + "select \"Year\" h=19", | |
| 1178 | + "select \"Group\" h=19", | |
| 1179 | + "a \"contact@spboucher.ai\" h=15", | |
| 1180 | + "a \"MacLustr\" h=15" | |
| 1181 | + ], | |
| 1182 | + "sticky": [ | |
| 1183 | + 57 | |
| 1184 | + ], | |
| 1185 | + "docH": 2667, | |
| 1186 | + "errors": [] | |
| 1187 | + }, | |
| 1188 | + { | |
| 1189 | + "checks": [ | |
| 1190 | + { | |
| 1191 | + "check": "compare mode round-trip", | |
| 1192 | + "url": "http://localhost:8290/compare/canada/united-states/france?tab=economy&mode=index100", | |
| 1193 | + "ok": true | |
| 1194 | + }, | |
| 1195 | + { | |
| 1196 | + "check": "tab switch updates URL", | |
| 1197 | + "url": "http://localhost:8290/compare/canada/united-states/france?tab=population&mode=index100", | |
| 1198 | + "ok": true | |
| 1199 | + }, | |
| 1200 | + { | |
| 1201 | + "check": "ranking year round-trip", | |
| 1202 | + "url": "http://localhost:8290/rankings/gdp-per-capita?year=2015", | |
| 1203 | + "ok": true | |
| 1204 | + }, | |
| 1205 | + { | |
| 1206 | + "check": "404 /compare/canada", | |
| 1207 | + "status": 404, | |
| 1208 | + "ok": true | |
| 1209 | + }, | |
| 1210 | + { | |
| 1211 | + "check": "404 /rankings/not-a-thing", | |
| 1212 | + "status": 404, | |
| 1213 | + "ok": true | |
| 1214 | + }, | |
| 1215 | + { | |
| 1216 | + "check": "404 /compare/canada/nowhere-land", | |
| 1217 | + "status": 404, | |
| 1218 | + "ok": true | |
| 1219 | + } | |
| 1220 | + ] | |
| 1221 | + } | |
| 1222 | +] | |
| \ No newline at end of file | ||
added
apps/web/qa/screens/compare-rankings/rk-gdppc-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-gdppc-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-gdppc-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-gdppc-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-gdppc-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-gdppc-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-life-oecd-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-life-oecd-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-life-oecd-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-life-oecd-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-life-oecd-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/rk-life-oecd-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-economy-1280-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-economy-1280-y1800.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-economy-1280-y900.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-economy-390-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-economy-390-y1800.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-economy-390-y900.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-hero-1280-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-hero-390-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-hero-390-y700.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-snapshot-390-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/cmp-snapshot-390-y700.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-added-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-custom-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-eco-dark-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-health-hero-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-indpicker-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-options-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-picker-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-prov-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-rk-filters-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-rk-g20-dark-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-rk-highlight-dark-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/i-rk-history-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rankings-1280-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rankings-1280-y900.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rankings-390-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rankings-390-y800.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-gdppc-1280-y1800.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-gdppc-1280-y900.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-gdppc-390-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-gdppc-390-y2600.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-gdppc-390-y3600.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-gdppc-390-y800.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-life-oecd-1280-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-life-oecd-1280-y1600.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-life-oecd-390-y0.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/compare-rankings/seg/rk-life-oecd-390-y1200.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-1280.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-1440.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-320.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-360.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-375.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-390.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-414.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries-430.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-1280.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-1440.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-320.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-360.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-375.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-390-dark.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-390.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-414.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada-430.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-1280.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-1440.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-320.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-360.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-375.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-390.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-414.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/countries_canada_economy-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_coverage-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_coverage-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_issues-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_issues-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_raw-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_raw-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_runs-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_admin_runs-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_login-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_login-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_login-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_login-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_login-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/admin_login-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/api-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/api-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/api-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/api-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/api-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/api-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/changes-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/changes-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/changes-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/changes-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/changes-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/changes-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/data-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/data-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/data-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/data-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/data-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/data-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/explore-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/explore-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/explore-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/explore-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/explore-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/explore-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_gdp-per-capita-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_gdp-per-capita-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_gdp-per-capita-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_gdp-per-capita-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_gdp-per-capita-390-dark.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_gdp-per-capita-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_gdp-per-capita-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_life-expectancy-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_life-expectancy-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_life-expectancy-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_life-expectancy-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_life-expectancy-390-touch.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_life-expectancy-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_life-expectancy-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_topic_health-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_topic_health-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_topic_health-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_topic_health-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_topic_health-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/indicators_topic_health-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/methodology-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/methodology-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/methodology-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/methodology-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/methodology-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/methodology-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions_oecd-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions_oecd-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions_oecd-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions_oecd-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions_oecd-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/regions_oecd-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/report.json
+1141 −0
added
apps/web/qa/screens/explore/sources-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources-430.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources_worldbank-1280.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources_worldbank-1440.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources_worldbank-320.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources_worldbank-375.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources_worldbank-390.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/explore/sources_worldbank-430.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/home-320.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/home-360.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/home-375.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/home-390.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/home-414.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/home-430.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/report.json
+227 −299
added
apps/web/qa/screens/seg/canada-1440-dna.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/seg/canada-320-similar.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-1440-0.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-1440-1.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-1440-2.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-1440-3.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-1440-4.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-390-1.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-390-2.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-390-3.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries-390-4.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-1440-0.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-1440-1.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-1440-2.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-1440-3.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-1440-4.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-390-0.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-390-1.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-390-2.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-390-3.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada-390-4.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-1440-0.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-1440-1.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-1440-2.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-1440-3.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-1440-4.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-390-0.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-390-1.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-390-2.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-390-3.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/countries_canada_economy-390-4.png
+0 −0
Binary file not shown.
added
apps/web/qa/screens/seg/economy-390-dark.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/home-390-0.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/home-390-1.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/home-390-2.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/home-390-3.png
+0 −0
Binary file not shown.
modified
apps/web/qa/screens/seg/home-390-4.png
+0 −0
Binary file not shown.
added
apps/web/qa/shots-explore.mjs
+120 −0
added
apps/web/qa/shots-real.mjs
+8 −0
added
apps/web/src/app/admin/(panel)/coverage/page.tsx
+20 −0
added
apps/web/src/app/admin/(panel)/issues/page.tsx
+73 −0
added
apps/web/src/app/admin/(panel)/layout.tsx
+31 −0
added
apps/web/src/app/admin/(panel)/page.tsx
+135 −0
added
apps/web/src/app/admin/(panel)/raw/page.tsx
+65 −0
added
apps/web/src/app/admin/(panel)/runs/page.tsx
+52 −0
added
apps/web/src/app/admin/actions.ts
+61 −0
added
apps/web/src/app/admin/login/page.tsx
+37 −0
added
apps/web/src/app/api/page.tsx
+253 −0
modified
apps/web/src/app/apple-icon.png
+0 −0
Binary file not shown.
added
apps/web/src/app/changes/page.tsx
+51 −0
added
apps/web/src/app/compare/[...slugs]/page.tsx
+197 −0
added
apps/web/src/app/compare/og/route.tsx
+50 −0
added
apps/web/src/app/compare/page.tsx
+45 −0
modified
apps/web/src/app/countries/[slug]/[topic]/page.tsx
+4 −3
modified
apps/web/src/app/countries/[slug]/page.tsx
+2 −1
added
apps/web/src/app/explore/page.tsx
+159 −0
modified
apps/web/src/app/icon.png
+0 −0
Binary file not shown.