From 0abeb92627e4b606c8d9f7d3db0d4fb414ee1e90 Mon Sep 17 00:00:00 2001 From: Adam Fisk Date: Sat, 25 Jul 2026 11:50:44 -0600 Subject: [PATCH] ci: run the Dart test suite on pull_request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing ran `flutter test test/` on a PR. The only two references to `flutter test` live in build-linux.yml and build-windows.yml, both workflow_call-only and both scoped to integration_test/ — so the unit suite never executed in CI at all. That is part of why the user_failures deserialization break (#8929) reached three releases: a unit test would have caught it, and a unit test now pins it, but on `pull_request` nothing would have run it. flutter test needs no Go toolchain, Android SDK, or Java, so this gate is just checkout + flutter + pubget/gen + test. Deletes test/widget_test.dart, which had to go first: it is the stock `flutter create` counter template with `pumpWidget` commented out, so it asserts against an empty widget tree and fails unconditionally. It was never adapted to this app and tests nothing. Co-Authored-By: Claude --- .github/workflows/flutter-test.yml | 79 ++++++++++++++++++++++++++++++ test/widget_test.dart | 28 ----------- 2 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/flutter-test.yml delete mode 100644 test/widget_test.dart diff --git a/.github/workflows/flutter-test.yml b/.github/workflows/flutter-test.yml new file mode 100644 index 0000000000..c3dba788e2 --- /dev/null +++ b/.github/workflows/flutter-test.yml @@ -0,0 +1,79 @@ +name: Flutter Test + +# Runs the Dart unit/widget suite (test/) on PRs that touch Dart source. Until +# now nothing ran it: every other `flutter test` call in this repo targets +# integration_test/, and all of them sit behind workflow_call (build-linux.yml, +# build-windows.yml) or workflow_dispatch. So no PR-triggered workflow executed +# a single Dart test, and a regression pinned by a unit test could still merge. +# +# That gap is not hypothetical — lantern-box v0.0.101 changed the JSON shape of +# `user_failures` and broke Dart deserialization for every user with a recorded +# failure (#8929). The fix ships with tests, but on `pull_request` nothing would +# have run them. +# +# No Go toolchain, Android SDK, or Java here: `flutter test` runs on the Dart VM +# and builds no platform artifact, which keeps this gate to a couple of minutes. + +on: + workflow_dispatch: + pull_request: + paths: + - "lib/**" + - "test/**" + - "pubspec.yaml" + - "pubspec.lock" + - ".github/flutter-version.yaml" + # keep the self-trigger so edits to this workflow re-run it + - ".github/workflows/flutter-test.yml" + +concurrency: + group: flutter-test-${{ github.ref }} + cancel-in-progress: true + +jobs: + flutter-test: + permissions: + contents: "read" + runs-on: ubuntu-24.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Cache Flutter dependencies + uses: actions/cache@v4 + timeout-minutes: 5 + continue-on-error: true + with: + path: | + ~/.pub-cache + key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-flutter- + + - name: Install Flutter + uses: subosito/flutter-action@v2.22.0 + with: + channel: stable + flutter-version-file: .github/flutter-version.yaml + cache: true + + # Generated sources are committed, but regenerating means the suite tests + # the PR's own source rather than whatever .g.dart happened to be checked + # in — a model change with a forgotten `make gen` would otherwise pass + # against stale generated code. + - name: Flutter pub get + codegen + run: | + make pubget + make gen + + # app.env is a declared pubspec asset, normally decoded from a secret by + # the release workflow. Asset bundling runs before the tests do and fails + # outright if the file is absent, so an empty placeholder is enough — the + # suite reads nothing from it. Same treatment as android-compile-check.yml. + - name: Create placeholder app.env + run: touch app.env + + # Reporter is left unset: the Dart test runner defaults to its `github` + # reporter under Actions, which annotates failures inline on the PR. + - name: Run Flutter tests + run: flutter test diff --git a/test/widget_test.dart b/test/widget_test.dart deleted file mode 100644 index 9322cd7945..0000000000 --- a/test/widget_test.dart +++ /dev/null @@ -1,28 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - // await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -}