taskflare 0.2.0
taskflare: ^0.2.0 copied to clipboard
A Dart CLI tool that wraps dart test, parses JSON output, and notifies you of the result — success, failure, or crash.
taskflare #
A Dart CLI tool that runs your dev commands, parses their output to determine a single unambiguous result, and notifies you when they're done. Currently wraps dart test / flutter test; designed to grow to other commands (lint, build, codegen, …) behind a single menu-driven entry point.
Outcomes #
Every run ends with exactly one of three outcomes:
| Outcome | Meaning |
|---|---|
[SUCCESS] |
All tests passed |
[FAILURE] |
At least one test failed |
[CRASH] |
Tests did not run or the process crashed before completing |
Usage #
Run it from the root of any Dart or Flutter project.
Interactive menu #
dart run taskflare
Opens the main menu with options for Help, Config, and Run command. Designed for exploring taskflare for the first time.
Run tests directly #
dart run taskflare test
dart run taskflare test --name "my test"
dart run taskflare test test/parser/
Help #
dart run taskflare help # Interactive command list
dart run taskflare help test # Print test command help directly
Config #
dart run taskflare config # Interactive configuration menu
Example output:
FAIL ▶ parses failure when done reports failure test/parser/json_event_parser_test.dart:42
THROW ▶ throws when input is malformed test/parser/json_event_parser_test.dart:91
SKIP ▶ skipped scenario
[FAILURE] passed: 108 failed: 2 skipped: 1 (14.3s)
FAIL— assertion error (expectfailed)THROW— uncaught exception thrown during the testSKIP— test was skipped- File references are printed as
path/to/file.dart:line— Ctrl+click in most terminals and IDEs to jump directly to the test
The progress line updates in-place while tests run and is erased when the run completes, leaving only the permanent failure/skip lines and the final summary.
Windows notifications #
On Windows, taskflare sends a native desktop toast notification at the end of each run and an immediate toast when a test fails.
On first run, taskflare automatically:
- Writes the bundled app icon to
%LOCALAPPDATA%\Taskflare\taskflare.ico - Registers
Taskflare.AppinHKCU\Software\Classes\AppUserModelId\ - Creates a Start Menu shortcut (
Taskflare.lnk) with the AppUserModelID set
This is what makes the Taskflare icon appear next to the app name in the notification header. No manual setup required. Re-registration happens automatically if any of the three components is missing (e.g. after a clean install or manual deletion).
To replace the icon, overwrite %LOCALAPPDATA%\Taskflare\taskflare.ico with any ICO file, then delete the Start Menu shortcut so it is recreated on the next run:
Remove-Item "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Taskflare.lnk" -Force
Requirements #
- Dart SDK
>=3.0.0 <4.0.0 - Windows toast notifications require Windows 10 or later
Architecture #
taskflare follows a clean, layered architecture. Each layer has a single responsibility and depends only on the layers below it.
bin/
└── taskflare.dart Entry point — dispatches menu / help / config / commands
lib/src/
├── cli/ CLI entry points (menu-driven)
│ ├── profile/ CommandProfile base + concrete profiles (TestProfile, …)
│ ├── command_registry.dart Central list of runnable commands (drives menu/help/run)
│ ├── menu_command.dart Main menu shown by bare `taskflare`
│ ├── help_command.dart Interactive help + `help <name>` shortcut
│ ├── run_command.dart "Run command" submenu
│ ├── config_command.dart Interactive configuration menu
│ ├── test_command.dart Wires Taskflare for the `test` command
│ └── terminal.dart TerminalSession — owns the alt screen buffer, injected into all TUI screens
├── config/
│ └── taskflare_config.dart Persisted user preferences (filter + report toggles)
├── utils/ Shared utilities
│ ├── enums.dart TestResultKind and TestOutcome enums
│ └── project_detector.dart Detects Flutter vs. Dart project from pubspec.yaml
├── entities/ Immutable value objects (events, run_summary, …)
├── parser/
│ └── json_event_parser.dart Reads test JSON lines → produces a RunSummary
├── runner/ Abstract CommandRunner + process-based runners (dart / flutter test)
├── reporter/ Markdown run report writer (+ per-test records)
├── notifier/ Console + Windows toast notifiers, progress line, composite
└── taskflare.dart Orchestrator: runner → parser → notifier + reporter
lib/assets/
└── icon.png Bundled app icon (written to LocalAppData on first run)
Layer rules #
utils ← no dependencies
entities ← utils
config ← no dependencies (pure persisted preferences)
parser ← entities, utils
runner ← utils
reporter ← entities, utils
notifier ← entities, utils
taskflare ← runner, parser, notifier, reporter, entities, utils (orchestrator only)
cli ← all layers (entry points that wire everything)
The orchestrator depends only on abstractions (CommandRunner, Notifier, ReportWriter) — never on concrete implementations. Swapping them requires no changes to taskflare.dart.
Extending taskflare #
Add a new command (e.g. taskflare lint):
- Create
lib/src/cli/profile/lint_profile.dartextendingCommandProfile— implementname,description,helpText,commandLabel, andbuildRunner - Create
lib/src/cli/lint_command.dartwiringTaskflarefor the new profile (notifier, reporter, progress options) - Add an entry to
commandRegistryinlib/src/cli/command_registry.dart— menu, help, and run submenu pick it up automatically
Add a new runner (e.g. wrap dart run build_runner build):
- Create
lib/src/runner/build_runner_runner.dartextendingCommandRunner - Override
run()to launch the command and return aCommandResult - Add tests in
test/runner/build_runner_runner_test.dart - Pass it to
Taskflare(runner: BuildRunnerRunner(), ...)from a profile
Add a new notifier (e.g. webhook, Slack):
- Create
lib/src/notifier/slack_notifier.dartimplementingNotifier - Implement
notify(RunSummary summary) - Add tests in
test/notifier/slack_notifier_test.dart - Pass it to
Taskflare(notifier: SlackNotifier(), ...)
Running tests #
dart test
The integration tests in test/runner/ spin up real subprocesses using the fixture projects under test/fixtures/. They take a few seconds — all other tests are pure unit tests and run instantly.
Project conventions #
| Document | Contents |
|---|---|
doc/conventions_testing.md |
Test structure, group/test naming rules, what must be covered |
doc/conventions_architecture.md |
Folder layout, layer dependency rules, naming patterns |
doc/learnings.md |
Problems encountered and what we learned from them |