add world opinions project
All checks were successful
Test and deploy staging / staging (push) Successful in 1m49s

World map with switchable layers (what "liberal" means, what left vs right
is about, traditional/secular and survival/self-expression values), country
cards, a shared-scale party compass, a values scatter and national
narratives of major events.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 16:24:40 +00:00
parent 499dd94cbb
commit afb1f191df
16 changed files with 2338 additions and 2 deletions

View File

@@ -0,0 +1,44 @@
import { describe, expect, it } from 'vitest';
import world from 'world-atlas/countries-110m.json';
import { countries, countryById, narratives, parties, partyCountries, profiles } from './data';
describe('world opinions data', () => {
it('has unique country ids and ISO codes', () => {
expect(new Set(countries.map((country) => country.id)).size).toBe(countries.length);
expect(new Set(countries.map((country) => country.iso)).size).toBe(countries.length);
});
it('matches every country to a shape on the map', () => {
const shapes = new Set(
world.objects.countries.geometries.map((shape: { id?: string }) => String(shape.id))
);
for (const country of countries) expect(shapes.has(country.iso), country.name).toBe(true);
});
it('only references known countries', () => {
const referenced = [
...profiles.map((profile) => profile.id),
...partyCountries,
...parties.map((party) => party.country),
...narratives.flatMap((narrative) => narrative.views.map((view) => view.country))
];
for (const id of referenced) expect(countryById.has(id), id).toBe(true);
});
it('keeps party positions on the 0–10 scale with unique keys', () => {
const keys = new Set(parties.map((party) => `${party.country}-${party.short}`));
expect(keys.size).toBe(parties.length);
for (const party of parties) {
for (const value of [party.econ, party.social]) {
expect(value).toBeGreaterThanOrEqual(0);
expect(value).toBeLessThanOrEqual(10);
}
}
for (const id of partyCountries) {
expect(
parties.some((party) => party.country === id),
id
).toBe(true);
}
});
});