import 'dart:io'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; import '../../tool/src/release/apps.dart'; import '../../tool/src/release/version.dart'; import '../../tool/src/release/whats_new.dart'; import 'fixtures.dart'; void main() { test('the drafts list the features, then the fixes, without types, scopes ' 'and closing references, as sentences; German marked to translate', () { final drafts = draftWhatsNew( const [ Commit(hash: 'a', subject: 'fix(sync): no lost rating'), Commit(hash: 'b', subject: 'docs: why'), Commit( hash: 'c', subject: 'feat(train): tabs folding into the title (ADR 0030, D60)', ), Commit(hash: 'd', subject: 'perf!: faster library.'), Commit(hash: 'e', subject: 'chore(release): notes-v0.18.0'), ], first: false, app: 'notes', apps: _apps, ); expect(drafts['en'], ''' - Tabs folding into the title. - No lost rating. - Faster library. '''); expect(drafts['de'], ''' - TRANSLATE: Tabs folding into the title. - TRANSLATE: No lost rating. - TRANSLATE: Faster library. '''); }); test('the first release says so', () { expect( draftWhatsNew(const [], first: true, app: 'notes', apps: _apps)['en'], '- The first release.\n', ); }); test("commits scoped to other apps don't count; a shared package's do", () { final drafts = draftWhatsNew( const [ Commit(hash: 'a', subject: 'feat(diary): the first diary'), Commit(hash: 'b', subject: 'feat(notes,diary): a lock on both'), Commit(hash: 'c', subject: 'feat(app): a profile everywhere'), Commit(hash: 'd', subject: 'fix(deploy): the image builds'), ], first: false, app: 'notes', apps: _apps, ); expect(drafts['en'], ''' - A lock on both. - A profile everywhere. - The image builds. '''); }); group('the trailers', () { const commits = [ Commit( hash: 'a', subject: 'fix(notes): the sync no longer loses a rating', body: 'Why it did.\n\n' 'Whats-New: Ratings are kept when syncing.\n' 'Whats-New-De: Bewertungen bleiben beim Synchronisieren.\n' 'Signed-off-by: A \n', ), Commit(hash: 'b', subject: 'feat(notes): a refactor nobody sees'), Commit( hash: 'c', subject: 'feat(app): tabs folding into the title (ADR 0030, D60)', body: 'Whats-New: Tabs fold into the title.\n' 'Whats-New: Search: in every list.\n' 'Whats-New-De: Tabs falten sich in den Titel.\n', ), Commit( hash: 'd', subject: 'feat(diary): a diary', body: 'Whats-New: A diary.\nWhats-New-De: Ein Tagebuch.\n', ), ]; test("are what's new where a commit has them: the features' first, " 'commits without them left out, those of other apps too', () { final drafts = draftWhatsNew( commits, first: false, app: 'notes', apps: _apps, ); expect(drafts['en'], ''' - Tabs fold into the title. - Search: in every list. - Ratings are kept when syncing. '''); expect(drafts['de'], ''' - Tabs falten sich in den Titel. - TRANSLATE: Search: in every list. - Bewertungen bleiben beim Synchronisieren. '''); }); test('are left alone in the first release', () { expect( draftWhatsNew(commits, first: true, app: 'notes', apps: _apps)['de'], '- TRANSLATE: The first release.\n', ); }); }); test("a text's changes are its lines starting with '- '", () { expect(whatsNewChanges('- One\n\n - Two \n'), ['One', 'Two']); expect(whatsNewList('- One\n\n - Two \n'), '- One\n- Two'); }); group('problems', () { test('none in an edited text', () { expect(whatsNewProblems('x', '- One.\n- Two.\n'), isEmpty); }); test('a text listing nothing', () { expect(whatsNewProblems('x', '\n'), ['x lists no change.']); }); test('a line not starting with a dash', () { expect(whatsNewProblems('x', '- One.\nTwo.\n'), [ "x, line 2: doesn't start with '- '.", ]); }); test('a line still to be translated', () { expect(whatsNewProblems('x', '- TRANSLATE: One.\n'), [ 'x is still to be translated (TRANSLATE:).', ]); }); test("more than F-Droid's 500 characters", () { expect(whatsNewProblems('x', '- ${'a' * 499}\n'), [ "x has 501 characters, more than F-Droid's 500.", ]); }); }); test("the files are the app's, F-Droid's changelog its listing's", () { expect( whatsNewFile(testApp, const Version(0, 19, 0), 'de'), 'apps/notes/halkyon_notes_flutter/assets/whats_new/0.19.0.de.txt', ); expect( fdroidChangelogFile(testApp, 23, 'en'), 'app.halkyon.notes/en-US/changelogs/23.txt', ); expect( fdroidChangelogFile(testApp, 23, 'de'), 'app.halkyon.notes/de/changelogs/23.txt', ); }); // The texts every app bundles, as a release would take them. for (final app in releasedApps.values) { test("${app.name}'s texts of what's new are each release's in every " 'language, and as a release takes them', () { final folder = Directory(app.whatsNewDirectory); final byVersion = >{}; for (final file in folder.listSync().whereType()) { final name = p.basename(file.path); final match = whatsNewName.firstMatch(name); expect(match, isNotNull, reason: '$name: ..txt'); (byVersion[match![1]!] ??= {}).add(match[2]!); expect(whatsNewProblems(name, file.readAsStringSync()), isEmpty); } expect(byVersion, isNotEmpty); for (final MapEntry(key: version, value: languages) in byVersion.entries) { expect(languages, whatsNewLanguages.toSet(), reason: version); } }); } } const _apps = {'notes', 'diary'};