import 'package:flutter_test/flutter_test.dart'; import 'package:mews/mews/document.dart'; import 'package:mews/mews/parser.dart'; const conformingPage = ''' Signal Bars

Signal Bars

Notes on old phones and the about page.

'''; void main() { test('parses a conforming Mews page', () { final page = parseMewsPage(source: conformingPage, url: 'https://example.com/index.html'); expect(page.isMews, isTrue); expect(page.specVersion, '0.1'); expect(page.title, 'Signal Bars'); expect(page.description, 'Notes on old phones.'); expect(page.variant, MewsVariant.green); expect(page.lang, 'en'); expect(page.entries, hasLength(2)); expect(page.entries.first.url, 'https://example.com/2026-10-08-retro-phones.html'); expect(page.entries.first.title, 'Collecting retro phones'); expect(page.entries.first.date, DateTime(2026, 10, 8)); // Entries are listed newest first. expect(page.entries.last.date, DateTime(2026, 9, 21)); expect(page.body, hasLength(3)); expect(page.body[0], isA()); final paragraph = page.body[1] as ParagraphBlock; expect(paragraph.inline, hasLength(5)); final link = paragraph.inline[3] as MewsLink; expect(link.href, 'https://example.com/about.html'); }); test('rejects a page that is not well-formed', () { expect( () => parseMewsPage( source: 'x

oops', url: 'https://example.com/'), throwsA(isA()), ); }); test('treats a page without the conformance marker as non-Mews', () { final source = ''' Plain

Just XHTML.

'''; final page = parseMewsPage(source: source, url: 'https://example.com/plain.html'); expect(page.isMews, isFalse); expect(page.specVersion, isNull); expect(page.variant, MewsVariant.plain); }); test('resolves relative URLs against the page', () { final page = parseMewsPage(source: conformingPage, url: 'https://example.com/posts/index.html'); final paragraph = page.body[1] as ParagraphBlock; final link = paragraph.inline[3] as MewsLink; expect(link.href, 'https://example.com/posts/about.html'); }); test('allows same-site images and refuses off-site and data URIs', () { final source = ''' Pics

A cat and A dog

A bird

Inline

'''; final page = parseMewsPage(source: source, url: 'https://example.com/pics.html'); final images = page.body.whereType().toList(); expect(images, hasLength(4)); expect(images[0].src, 'https://example.com/cat.png'); expect(images[0].allowed, isTrue); expect(images[1].src, 'https://img.example.com/dog.png'); expect(images[1].allowed, isTrue, reason: 'subdomains share the registered domain'); expect(images[2].allowed, isFalse, reason: 'another site'); expect(images[3].allowed, isFalse, reason: 'data URI'); }); test('drops scripts and styles entirely', () { final source = ''' Spooky

Keep this.

'''; final page = parseMewsPage(source: source, url: 'https://example.com/spooky.html'); expect(page.body, hasLength(1)); final paragraph = page.body[0] as ParagraphBlock; expect((paragraph.inline[0] as MewsText).text, 'Keep this.'); }); test('honors dir=rtl', () { final source = ''' Shalom

Text.

'''; final page = parseMewsPage(source: source, url: 'https://example.com/he.html'); expect(page.direction, TextDirection.rtl); }); test('builds form fields with labels', () { final source = ''' Guestbook
'''; final page = parseMewsPage(source: source, url: 'https://example.com/guest.html'); final form = page.body.single as FormBlock; expect(form.action, 'https://example.com/sign'); expect(form.method, 'post'); final nameField = form.fields[0] as MewsTextField; expect(nameField.name, 'name'); expect(nameField.label, 'Your name'); final hidden = form.fields[1] as MewsHiddenField; expect(hidden.value, '1'); final submit = form.fields[2] as MewsSubmitField; expect(submit.label, 'Sign guestbook'); }); test('pretty-printed markup leaves no phantom blank content', () { final source = ''' Indent

No blank line above this.

And none between paragraphs.

A paragraph with wrapped lines.

'''; final page = parseMewsPage(source: source, url: 'https://example.com/indent.html'); // The quote holds its two paragraphs and nothing else. final quote = page.body[0] as QuoteBlock; expect(quote.children, hasLength(2)); expect((quote.children.first as ParagraphBlock).inline.single, isA()); // The list item starts directly with the link, no blank run before it. final list = page.body[1] as ListBlock; final item = (list.items.single.blocks.single as ParagraphBlock).inline; final link = item.single as MewsLink; expect((link.children.single as MewsText).text, '2026-10-08 A dated link'); // Interior line breaks collapse to single spaces, like in browsers. final paragraph = (page.body[2] as ParagraphBlock).inline; expect((paragraph.single as MewsText).text, 'A paragraph with wrapped lines.'); }); test('keeps bare inline content in list items and quotes', () { final source = ''' Bare
Quoted words verbatim.
'''; final page = parseMewsPage(source: source, url: 'https://example.com/bare.html'); final list = page.body[0] as ListBlock; final first = (list.items[0].blocks.single as ParagraphBlock).inline; final link = first.single as MewsLink; expect(link.href, 'https://example.com/2026-10-08-post.html'); expect((link.children.single as MewsText).text, '2026-10-08 A dated link'); expect((list.items[1].blocks.single as ParagraphBlock).inline.single, isA()); // Text before a nested list stays with the item; the list becomes a block. expect(list.items[2].blocks, hasLength(2)); expect(list.items[2].blocks[0], isA()); expect(list.items[2].blocks[1], isA()); final quote = page.body[1] as QuoteBlock; final quoteText = (quote.children.single as ParagraphBlock).inline; expect(quoteText, hasLength(3)); expect((quoteText[0] as MewsText).text, 'Quoted words '); }); group('the atom feed link', () { String pageWith(String link) => ''' Signal Bars $link

Signal Bars

'''; test('resolves against the page, so a relative href is usable', () { final page = parseMewsPage( source: pageWith( ''), url: 'https://example.com/posts/index.html', ); expect(page.atomFeedHref, 'https://example.com/posts/feed.xml'); }); test('is refused when it points at another site', () { // A client must not load another site's resources on its own // (specs 7.4 and 8.1). final page = parseMewsPage( source: pageWith( ''), url: 'https://example.com/index.html', ); expect(page.atomFeedHref, isNull); }); test('is null when the page declares none', () { final page = parseMewsPage( source: pageWith(''), url: 'https://example.com/index.html'); expect(page.atomFeedHref, isNull); }); }); }