import 'package:flutter_test/flutter_test.dart'; import 'package:mews/mews/document.dart'; import 'package:mews/presentation/reader/oklch.dart'; import 'package:mews/presentation/reader/palettes.dart'; import 'package:mews/presentation/reader/site_palette.dart'; /// A wide sample of what the generator can produce: enough hosts to cover all /// 24 hues, 3 background tints and both foregrounds. Iterable _allPalettes(bool dark) => [ for (var i = 0; i < 2000; i++) sitePalette('gemini://h$i.example/', dark: dark)!, ]; void main() { group('seed', () { test('comes from the host', () { expect(siteSeed('gemini://example.org/page'), 'example.org'); expect(siteSeed('gemini://Example.ORG/page'), 'example.org'); }); test('names the user on a personal page', () { expect(siteSeed('gemini://example.org/~alice/'), 'alice@example.org'); expect(siteSeed('gemini://example.org/users/alice/x.gmi'), 'alice@example.org'); expect(siteSeed('gemini://example.org/Users/Alice'), 'alice@example.org'); }); test('is empty without a host', () { expect(siteSeed('mews:settings'), ''); expect(siteSeed('not a url'), ''); }); }); group('palette', () { test('is the same every time for one address', () { expect(sitePalette('gemini://example.org/a', dark: false), same(sitePalette('gemini://example.org/b', dark: false))); }); test('differs between two users on one host', () { final alice = sitePalette('gemini://example.org/~alice/', dark: false)!; final bob = sitePalette('gemini://example.org/~bob/', dark: false)!; expect(alice.link, isNot(bob.link)); }); test('is null for an address with no host', () { expect(sitePalette('mews:settings', dark: false), isNull); }); test('falls back to plain when the reader asks for host colors', () { expect( paletteFor( pageVariant: MewsVariant.plain, readerVariant: 'host', dark: false, url: 'mews:settings'), paletteFor(pageVariant: MewsVariant.plain, readerVariant: 'plain', dark: false), ); }); // Spec 5.1: every text and link color meets 7:1 against its background. for (final dark in [false, true]) { test('meets 7:1 contrast in ${dark ? 'dark' : 'light'} mode', () { for (final palette in _allPalettes(dark)) { expect(contrastRatio(palette.background, palette.foreground), greaterThanOrEqualTo(7.0)); expect(contrastRatio(palette.background, palette.link), greaterThanOrEqualTo(7.0)); expect(contrastRatio(palette.background, palette.visited), greaterThanOrEqualTo(7.0)); } }); test('stays no louder than the fixed palettes in ${dark ? 'dark' : 'light'} mode', () { // Cool holds the most saturated link of the fixed palettes, so no // generated color may pass it. final cool = paletteFor( pageVariant: MewsVariant.cool, readerVariant: 'cool', dark: dark); final limit = chromaOf(cool.link); for (final palette in _allPalettes(dark)) { expect(chromaOf(palette.link), lessThanOrEqualTo(limit)); expect(chromaOf(palette.background), lessThanOrEqualTo(0.03)); } }); } }); }