import 'dart:io'; import 'package:test/test.dart'; import '../tool/src/check_files.dart'; void main() { test("our own Dart files are formatted: the apps', the shared packages', the " "tools'", () { for (final path in [ 'apps/learn/halkyon_learn_flutter/lib/main.dart', 'apps/learn/halkyon_learn_server/lib/server.dart', 'apps/learn/halkyon_learn_server/test/integration/auth/account_test.dart', 'apps/todo/halkyon_todo_flutter/lib/main.dart', 'packages/halkyon_app/lib/halkyon_app.dart', 'packages/halkyon_base_server/lib/src/auth/email.dart', // SRP's client half, written by hand beside the module's generated // client, and its tests. 'packages/halkyon_base_client/lib/srp.dart', 'packages/halkyon_base_client/lib/src/srp/srp_client.dart', 'packages/halkyon_base_client/test/srp_client_test.dart', 'packages/halkyon_keys/lib/src/account_keys.dart', 'tool/check.dart', ]) { expect(isOwnDartFile(path), isTrue, reason: path); } }); test('what a generator writes is left as it wrote it', () { for (final path in [ // The client packages, Serverpod's from top to bottom, but for the // module's SRP. 'apps/learn/halkyon_learn_client/lib/src/protocol/client.dart', 'apps/todo/halkyon_todo_client/lib/halkyon_todo_client.dart', 'packages/halkyon_base_client/lib/src/protocol/protocol.dart', 'packages/halkyon_base_client/lib/halkyon_base_client.dart', // A server's generated sources and test tools. 'apps/learn/halkyon_learn_server/lib/src/generated/protocol.dart', 'packages/halkyon_base_server/lib/src/generated/endpoints.dart', 'apps/learn/halkyon_learn_server/test/integration/test_tools/serverpod_test_tools.dart', // gen-l10n's localizations, the app's and the shared packages'. 'apps/learn/halkyon_learn_flutter/lib/l10n/app_localizations.dart', 'apps/learn/halkyon_learn_flutter/lib/l10n/app_localizations_de.dart', 'packages/halkyon_ui/lib/l10n/halkyon_ui_localizations_en.dart', 'packages/halkyon_app/lib/l10n/halkyon_app_localizations.dart', ]) { expect(isOwnDartFile(path), isFalse, reason: path); } }); test('the files of other languages are no Dart files', () { expect(isOwnDartFile('tool/app_icons.py'), isFalse); expect( isOwnDartFile('packages/halkyon_app/lib/l10n/halkyon_app_en.arb'), isFalse, ); }); group('what changed since a commit', () { const packages = { 'halkyon_app': 'packages/halkyon_app', 'halkyon_ui': 'packages/halkyon_ui', 'halkyon_ui_example': 'packages/halkyon_ui/example', 'halkyon_learn_flutter': 'apps/learn/halkyon_learn_flutter', }; test('touches the packages its files are in, the innermost one', () { expect( packagesTouched([ 'packages/halkyon_app/lib/src/app/app_frame.dart', 'packages/halkyon_app/test/app/instance_gate_test.dart', 'packages/halkyon_ui/example/lib/main.dart', ], packages), ['halkyon_app', 'halkyon_ui_example'], ); }); test("files of no package (docs, tools, deploy) touch none: the tools' " 'own tests run anyway', () { expect( packagesTouched([ 'docs/adr/0015-one-repository.md', 'tool/check.dart', 'deploy/compose.learn.yaml', ], packages), isEmpty, ); }); test("the root's pubspec, lock or lint rules touch every package", () { for (final path in [ 'pubspec.yaml', 'pubspec.lock', 'analysis_options.yaml', ]) { expect(packagesTouched([path], packages), isNull, reason: path); } }); }); test("Melos' filters take every package, or those touched and what " 'depends on them', () { expect(melosFilters(), isEmpty); expect(melosFilters(touched: ['halkyon_app', 'halkyon_ui']), [ '--scope=halkyon_app', '--scope=halkyon_ui', '--include-dependents', ]); }); group('the generated code', () { test("the CLI's version is the one the lock holds Serverpod at", () { const lock = ''' packages: serverpod: dependency: transitive description: name: serverpod sha256: "0" url: "https://pub.dev" source: hosted version: "4.0.4" sdks: dart: ">=3.13.0 <4.0.0" '''; expect(lockedVersion(lock, 'serverpod'), '4.0.4'); expect(lockedVersion(lock, 'serverpod_cli'), isNull); expect( serverpodCliVersion('Some notice\nServerpod version: 4.0.4\n'), '4.0.4', ); expect(serverpodCliVersion('serverpod: command not found'), isNull); }); test('CI installs the CLI at the version the lock holds Serverpod at, so ' "check.dart's comparison holds there too", () { final pinned = RegExp( r'^\s*SERVERPOD_VERSION: (\S+)$', multiLine: true, ).firstMatch(File('.forgejo/workflows/ci.yaml').readAsStringSync()); expect( pinned?.group(1), lockedVersion(File('pubspec.lock').readAsStringSync(), 'serverpod'), ); }); test('differs where the generator changed, removed or added a file', () { final before = { 'apps/learn/halkyon_learn_server/lib/src/studyset/studyset.spy.yaml': 'a', 'apps/learn/halkyon_learn_server/lib/src/generated/protocol.dart': 'b', }; final after = { ...before, // Written anew from the changed model. 'apps/learn/halkyon_learn_server/lib/src/generated/protocol.dart': 'c', // A model's class no longer generated. 'apps/learn/halkyon_learn_client/lib/src/protocol/gone.dart': absentFile, // A new model's class. 'apps/learn/halkyon_learn_client/lib/src/protocol/new.dart': 'd', }; expect(differingFiles(before, after), [ 'apps/learn/halkyon_learn_client/lib/src/protocol/gone.dart', 'apps/learn/halkyon_learn_client/lib/src/protocol/new.dart', 'apps/learn/halkyon_learn_server/lib/src/generated/protocol.dart', ]); }); test('a file written back as committed differs from its change before, ' 'and changes the generator left alone count for nothing', () { expect( differingFiles( { 'apps/todo/halkyon_todo_client/lib/src/protocol/client.dart': 'a', 'apps/todo/halkyon_todo_server/lib/src/greeting.dart': 'b', }, {'apps/todo/halkyon_todo_server/lib/src/greeting.dart': 'b'}, ), ['apps/todo/halkyon_todo_client/lib/src/protocol/client.dart'], ); }); }); }