[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-flutter-flutter-add-integration-test":3,"mdc--z85fjj-key":34,"related-repo-flutter-flutter-add-integration-test":1661,"related-org-flutter-flutter-add-integration-test":1740},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":30,"sourceUrl":32,"mdContent":33},"flutter-add-integration-test","add integration tests to Flutter apps","Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"flutter","Flutter (Google)","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fflutter.png",[12,15,18,21],{"name":13,"slug":8,"type":14},"Flutter","tag",{"name":16,"slug":17,"type":14},"E2E Testing","e2e-testing",{"name":19,"slug":20,"type":14},"Mobile","mobile",{"name":22,"slug":23,"type":14},"Testing","testing",2664,"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins","2026-07-15T05:22:43.831512",null,155,[],{"repoUrl":25,"stars":24,"forks":28,"topics":31,"description":27},[],"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins\u002Ftree\u002FHEAD\u002Fskills\u002Fflutter-add-integration-test","---\nname: flutter-add-integration-test\ndescription: Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package.\nmetadata:\n  model: models\u002Fgemini-3.1-pro-preview\n  last_modified: Tue, 21 Apr 2026 18:29:20 GMT\n---\n# Implementing Flutter Integration Tests\n\n## Contents\n- [Project Setup and Dependencies](#project-setup-and-dependencies)\n- [Interactive Exploration via MCP](#interactive-exploration-via-mcp)\n- [Test Authoring Guidelines](#test-authoring-guidelines)\n- [Execution and Profiling](#execution-and-profiling)\n- [Workflow: End-to-End Integration Testing](#workflow-end-to-end-integration-testing)\n- [Examples](#examples)\n\n## Project Setup and Dependencies\n\nConfigure the project to support integration testing and Flutter Driver extensions.\n\n1. Add required development dependencies to `pubspec.yaml`:\n   ```bash\n   flutter pub add 'dev:integration_test:{\"sdk\":\"flutter\"}'\n   flutter pub add 'dev:flutter_test:{\"sdk\":\"flutter\"}'\n   ```\n2. Enable the Flutter Driver extension in your application entry point (typically `lib\u002Fmain.dart` or a dedicated `lib\u002Fmain_test.dart`):\n   - Import `package:flutter_driver\u002Fdriver_extension.dart`.\n   - Call `enableFlutterDriverExtension();` before `runApp()`.\n3. Add `Key` parameters (e.g., `ValueKey('login_button')`) to critical widgets in the application code to ensure reliable targeting during tests.\n\n## Interactive Exploration via MCP\n\nUse the Dart\u002FFlutter MCP server tools to interactively explore and manipulate the application state before writing static tests.\n\n- **Launch**: Execute `launch_app` with `target: \"lib\u002Fmain_test.dart\"` to start the application and acquire the DTD URI.\n- **Inspect**: Execute `get_widget_tree` to discover available `Key`s, `Text` nodes, and widget `Type`s.\n- **Interact**: Execute `tap`, `enter_text`, and `scroll` to simulate user flows.\n- **Wait**: Always execute `waitFor` or verify state with `get_health` when navigating or triggering animations.\n- **Troubleshoot Unmounted Widgets**: If a widget is not found in the tree, it may be lazily loaded in a `SliverList` or `ListView`. Execute `scroll` or `scrollIntoView` to force the widget to mount before interacting with it.\n\n## Test Authoring Guidelines\n\nStructure integration tests using the `flutter_test` API paradigm. \n\n- Create a dedicated `integration_test\u002F` directory at the project root.\n- Name all test files using the `\u003Cname>_test.dart` convention.\n- Initialize the binding by calling `IntegrationTestWidgetsFlutterBinding.ensureInitialized();` at the start of `main()`.\n- Load the application UI using `await tester.pumpWidget(MyApp());`.\n- Trigger frames and wait for animations to complete using `await tester.pumpAndSettle();` after interactions like `tester.tap()`.\n- Assert widget visibility using `expect(find.byKey(ValueKey('foo')), findsOneWidget);` or `findsNothing`.\n- Scroll to specific off-screen widgets using `await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder);`.\n\n**Conditional Logic for Legacy `flutter_driver`:**\n- If maintaining or migrating legacy `flutter_driver` tests, use `driver.waitFor()`, `driver.waitForAbsent()`, `driver.tap()`, and `driver.scroll()` instead of the `WidgetTester` APIs.\n\n## Execution and Profiling\n\nExecute tests using the `flutter drive` command. Require a host driver script located in `test_driver\u002Fintegration_test.dart` that calls `integrationDriver()`.\n\n**Conditional Execution Targets:**\n- **If testing on Chrome:** Launch `chromedriver --port=4444` in a separate terminal, then run:\n  `flutter drive --driver=test_driver\u002Fintegration_test.dart --target=integration_test\u002Fapp_test.dart -d chrome`\n- **If testing headless web:** Run with `-d web-server`.\n- **If testing on Android (Local):** Run `flutter drive --driver=test_driver\u002Fintegration_test.dart --target=integration_test\u002Fapp_test.dart`.\n- **If testing on Firebase Test Lab (Android):** \n  1. Build debug APK: `flutter build apk --debug`\n  2. Build test APK: `.\u002Fgradlew app:assembleAndroidTest`\n  3. Upload both APKs to the Firebase Test Lab console.\n\n## Workflow: End-to-End Integration Testing\n\nCopy and follow this checklist to implement and verify integration tests.\n\n- [ ] **Task Progress: Setup**\n  - [ ] Add `integration_test` and `flutter_test` to `pubspec.yaml`.\n  - [ ] Inject `enableFlutterDriverExtension()` into the app entry point.\n  - [ ] Assign `ValueKey`s to target widgets.\n- [ ] **Task Progress: Exploration**\n  - [ ] Run `launch_app` via MCP.\n  - [ ] Map the widget tree using `get_widget_tree`.\n  - [ ] Validate interaction paths using MCP tools (`tap`, `enter_text`).\n- [ ] **Task Progress: Authoring**\n  - [ ] Create `integration_test\u002Fapp_test.dart`.\n  - [ ] Write test cases using `WidgetTester` APIs.\n  - [ ] Create `test_driver\u002Fintegration_test.dart` with `integrationDriver()`.\n- [ ] **Task Progress: Execution & Feedback Loop**\n  - [ ] Run `flutter drive --driver=test_driver\u002Fintegration_test.dart --target=integration_test\u002Fapp_test.dart`.\n  - [ ] **Feedback Loop**: Review test output -> If `PumpAndSettleTimedOutException` occurs, check for infinite animations -> If widget not found, add `scrollUntilVisible` -> Re-run test until passing.\n\n## Examples\n\n### Standard Integration Test (`integration_test\u002Fapp_test.dart`)\n\n```dart\nimport 'package:flutter\u002Fmaterial.dart';\nimport 'package:flutter_test\u002Fflutter_test.dart';\nimport 'package:integration_test\u002Fintegration_test.dart';\nimport 'package:my_app\u002Fmain.dart';\n\nvoid main() {\n  IntegrationTestWidgetsFlutterBinding.ensureInitialized();\n\n  group('End-to-end test', () {\n    testWidgets('tap on the floating action button, verify counter', (tester) async {\n      \u002F\u002F Load app widget.\n      await tester.pumpWidget(const MyApp());\n\n      \u002F\u002F Verify the counter starts at 0.\n      expect(find.text('0'), findsOneWidget);\n\n      \u002F\u002F Find the floating action button to tap on.\n      final fab = find.byKey(const ValueKey('increment'));\n\n      \u002F\u002F Emulate a tap on the floating action button.\n      await tester.tap(fab);\n\n      \u002F\u002F Trigger a frame and wait for animations.\n      await tester.pumpAndSettle();\n\n      \u002F\u002F Verify the counter increments by 1.\n      expect(find.text('1'), findsOneWidget);\n    });\n  });\n}\n```\n\n### Host Driver Script (`test_driver\u002Fintegration_test.dart`)\n\n```dart\nimport 'package:integration_test\u002Fintegration_test_driver.dart';\n\nFuture\u003Cvoid> main() => integrationDriver();\n```\n\n### Performance Profiling Driver Script (`test_driver\u002Fperf_driver.dart`)\n\nUse this driver script if you wrap your test actions in `binding.traceAction()` to capture performance metrics.\n\n```dart\nimport 'package:flutter_driver\u002Fflutter_driver.dart' as driver;\nimport 'package:integration_test\u002Fintegration_test_driver.dart';\n\nFuture\u003Cvoid> main() {\n  return integrationDriver(\n    responseDataCallback: (data) async {\n      if (data != null) {\n        final timeline = driver.Timeline.fromJson(\n          data['scrolling_timeline'] as Map\u003CString, dynamic>,\n        );\n\n        final summary = driver.TimelineSummary.summarize(timeline);\n\n        await summary.writeTimelineToFile(\n          'scrolling_timeline',\n          pretty: true,\n          includeSummary: true,\n        );\n      }\n    },\n  );\n}\n```\n",{"data":35,"body":39},{"name":4,"description":6,"metadata":36},{"model":37,"last_modified":38},"models\u002Fgemini-3.1-pro-preview","Tue, 21 Apr 2026 18:29:20 GMT",{"type":40,"children":41},"root",[42,51,58,118,123,129,303,308,313,482,487,500,612,628,680,685,713,721,820,825,830,1120,1125,1139,1410,1422,1452,1465,1478,1655],{"type":43,"tag":44,"props":45,"children":47},"element","h1",{"id":46},"implementing-flutter-integration-tests",[48],{"type":49,"value":50},"text","Implementing Flutter Integration Tests",{"type":43,"tag":52,"props":53,"children":55},"h2",{"id":54},"contents",[56],{"type":49,"value":57},"Contents",{"type":43,"tag":59,"props":60,"children":61},"ul",{},[62,73,82,91,100,109],{"type":43,"tag":63,"props":64,"children":65},"li",{},[66],{"type":43,"tag":67,"props":68,"children":70},"a",{"href":69},"#project-setup-and-dependencies",[71],{"type":49,"value":72},"Project Setup and Dependencies",{"type":43,"tag":63,"props":74,"children":75},{},[76],{"type":43,"tag":67,"props":77,"children":79},{"href":78},"#interactive-exploration-via-mcp",[80],{"type":49,"value":81},"Interactive Exploration via MCP",{"type":43,"tag":63,"props":83,"children":84},{},[85],{"type":43,"tag":67,"props":86,"children":88},{"href":87},"#test-authoring-guidelines",[89],{"type":49,"value":90},"Test Authoring Guidelines",{"type":43,"tag":63,"props":92,"children":93},{},[94],{"type":43,"tag":67,"props":95,"children":97},{"href":96},"#execution-and-profiling",[98],{"type":49,"value":99},"Execution and Profiling",{"type":43,"tag":63,"props":101,"children":102},{},[103],{"type":43,"tag":67,"props":104,"children":106},{"href":105},"#workflow-end-to-end-integration-testing",[107],{"type":49,"value":108},"Workflow: End-to-End Integration Testing",{"type":43,"tag":63,"props":110,"children":111},{},[112],{"type":43,"tag":67,"props":113,"children":115},{"href":114},"#examples",[116],{"type":49,"value":117},"Examples",{"type":43,"tag":52,"props":119,"children":121},{"id":120},"project-setup-and-dependencies",[122],{"type":49,"value":72},{"type":43,"tag":124,"props":125,"children":126},"p",{},[127],{"type":49,"value":128},"Configure the project to support integration testing and Flutter Driver extensions.",{"type":43,"tag":130,"props":131,"children":132},"ol",{},[133,225,282],{"type":43,"tag":63,"props":134,"children":135},{},[136,138,145,147],{"type":49,"value":137},"Add required development dependencies to ",{"type":43,"tag":139,"props":140,"children":142},"code",{"className":141},[],[143],{"type":49,"value":144},"pubspec.yaml",{"type":49,"value":146},":\n",{"type":43,"tag":148,"props":149,"children":154},"pre",{"className":150,"code":151,"language":152,"meta":153,"style":153},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","flutter pub add 'dev:integration_test:{\"sdk\":\"flutter\"}'\nflutter pub add 'dev:flutter_test:{\"sdk\":\"flutter\"}'\n","bash","",[155],{"type":43,"tag":139,"props":156,"children":157},{"__ignoreMap":153},[158,196],{"type":43,"tag":159,"props":160,"children":163},"span",{"class":161,"line":162},"line",1,[164,169,175,180,186,191],{"type":43,"tag":159,"props":165,"children":167},{"style":166},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[168],{"type":49,"value":8},{"type":43,"tag":159,"props":170,"children":172},{"style":171},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[173],{"type":49,"value":174}," pub",{"type":43,"tag":159,"props":176,"children":177},{"style":171},[178],{"type":49,"value":179}," add",{"type":43,"tag":159,"props":181,"children":183},{"style":182},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[184],{"type":49,"value":185}," '",{"type":43,"tag":159,"props":187,"children":188},{"style":171},[189],{"type":49,"value":190},"dev:integration_test:{\"sdk\":\"flutter\"}",{"type":43,"tag":159,"props":192,"children":193},{"style":182},[194],{"type":49,"value":195},"'\n",{"type":43,"tag":159,"props":197,"children":199},{"class":161,"line":198},2,[200,204,208,212,216,221],{"type":43,"tag":159,"props":201,"children":202},{"style":166},[203],{"type":49,"value":8},{"type":43,"tag":159,"props":205,"children":206},{"style":171},[207],{"type":49,"value":174},{"type":43,"tag":159,"props":209,"children":210},{"style":171},[211],{"type":49,"value":179},{"type":43,"tag":159,"props":213,"children":214},{"style":182},[215],{"type":49,"value":185},{"type":43,"tag":159,"props":217,"children":218},{"style":171},[219],{"type":49,"value":220},"dev:flutter_test:{\"sdk\":\"flutter\"}",{"type":43,"tag":159,"props":222,"children":223},{"style":182},[224],{"type":49,"value":195},{"type":43,"tag":63,"props":226,"children":227},{},[228,230,236,238,244,246],{"type":49,"value":229},"Enable the Flutter Driver extension in your application entry point (typically ",{"type":43,"tag":139,"props":231,"children":233},{"className":232},[],[234],{"type":49,"value":235},"lib\u002Fmain.dart",{"type":49,"value":237}," or a dedicated ",{"type":43,"tag":139,"props":239,"children":241},{"className":240},[],[242],{"type":49,"value":243},"lib\u002Fmain_test.dart",{"type":49,"value":245},"):\n",{"type":43,"tag":59,"props":247,"children":248},{},[249,262],{"type":43,"tag":63,"props":250,"children":251},{},[252,254,260],{"type":49,"value":253},"Import ",{"type":43,"tag":139,"props":255,"children":257},{"className":256},[],[258],{"type":49,"value":259},"package:flutter_driver\u002Fdriver_extension.dart",{"type":49,"value":261},".",{"type":43,"tag":63,"props":263,"children":264},{},[265,267,273,275,281],{"type":49,"value":266},"Call ",{"type":43,"tag":139,"props":268,"children":270},{"className":269},[],[271],{"type":49,"value":272},"enableFlutterDriverExtension();",{"type":49,"value":274}," before ",{"type":43,"tag":139,"props":276,"children":278},{"className":277},[],[279],{"type":49,"value":280},"runApp()",{"type":49,"value":261},{"type":43,"tag":63,"props":283,"children":284},{},[285,287,293,295,301],{"type":49,"value":286},"Add ",{"type":43,"tag":139,"props":288,"children":290},{"className":289},[],[291],{"type":49,"value":292},"Key",{"type":49,"value":294}," parameters (e.g., ",{"type":43,"tag":139,"props":296,"children":298},{"className":297},[],[299],{"type":49,"value":300},"ValueKey('login_button')",{"type":49,"value":302},") to critical widgets in the application code to ensure reliable targeting during tests.",{"type":43,"tag":52,"props":304,"children":306},{"id":305},"interactive-exploration-via-mcp",[307],{"type":49,"value":81},{"type":43,"tag":124,"props":309,"children":310},{},[311],{"type":49,"value":312},"Use the Dart\u002FFlutter MCP server tools to interactively explore and manipulate the application state before writing static tests.",{"type":43,"tag":59,"props":314,"children":315},{},[316,343,383,416,442],{"type":43,"tag":63,"props":317,"children":318},{},[319,325,327,333,335,341],{"type":43,"tag":320,"props":321,"children":322},"strong",{},[323],{"type":49,"value":324},"Launch",{"type":49,"value":326},": Execute ",{"type":43,"tag":139,"props":328,"children":330},{"className":329},[],[331],{"type":49,"value":332},"launch_app",{"type":49,"value":334}," with ",{"type":43,"tag":139,"props":336,"children":338},{"className":337},[],[339],{"type":49,"value":340},"target: \"lib\u002Fmain_test.dart\"",{"type":49,"value":342}," to start the application and acquire the DTD URI.",{"type":43,"tag":63,"props":344,"children":345},{},[346,351,352,358,360,365,367,373,375,381],{"type":43,"tag":320,"props":347,"children":348},{},[349],{"type":49,"value":350},"Inspect",{"type":49,"value":326},{"type":43,"tag":139,"props":353,"children":355},{"className":354},[],[356],{"type":49,"value":357},"get_widget_tree",{"type":49,"value":359}," to discover available ",{"type":43,"tag":139,"props":361,"children":363},{"className":362},[],[364],{"type":49,"value":292},{"type":49,"value":366},"s, ",{"type":43,"tag":139,"props":368,"children":370},{"className":369},[],[371],{"type":49,"value":372},"Text",{"type":49,"value":374}," nodes, and widget ",{"type":43,"tag":139,"props":376,"children":378},{"className":377},[],[379],{"type":49,"value":380},"Type",{"type":49,"value":382},"s.",{"type":43,"tag":63,"props":384,"children":385},{},[386,391,392,398,400,406,408,414],{"type":43,"tag":320,"props":387,"children":388},{},[389],{"type":49,"value":390},"Interact",{"type":49,"value":326},{"type":43,"tag":139,"props":393,"children":395},{"className":394},[],[396],{"type":49,"value":397},"tap",{"type":49,"value":399},", ",{"type":43,"tag":139,"props":401,"children":403},{"className":402},[],[404],{"type":49,"value":405},"enter_text",{"type":49,"value":407},", and ",{"type":43,"tag":139,"props":409,"children":411},{"className":410},[],[412],{"type":49,"value":413},"scroll",{"type":49,"value":415}," to simulate user flows.",{"type":43,"tag":63,"props":417,"children":418},{},[419,424,426,432,434,440],{"type":43,"tag":320,"props":420,"children":421},{},[422],{"type":49,"value":423},"Wait",{"type":49,"value":425},": Always execute ",{"type":43,"tag":139,"props":427,"children":429},{"className":428},[],[430],{"type":49,"value":431},"waitFor",{"type":49,"value":433}," or verify state with ",{"type":43,"tag":139,"props":435,"children":437},{"className":436},[],[438],{"type":49,"value":439},"get_health",{"type":49,"value":441}," when navigating or triggering animations.",{"type":43,"tag":63,"props":443,"children":444},{},[445,450,452,458,460,466,468,473,474,480],{"type":43,"tag":320,"props":446,"children":447},{},[448],{"type":49,"value":449},"Troubleshoot Unmounted Widgets",{"type":49,"value":451},": If a widget is not found in the tree, it may be lazily loaded in a ",{"type":43,"tag":139,"props":453,"children":455},{"className":454},[],[456],{"type":49,"value":457},"SliverList",{"type":49,"value":459}," or ",{"type":43,"tag":139,"props":461,"children":463},{"className":462},[],[464],{"type":49,"value":465},"ListView",{"type":49,"value":467},". Execute ",{"type":43,"tag":139,"props":469,"children":471},{"className":470},[],[472],{"type":49,"value":413},{"type":49,"value":459},{"type":43,"tag":139,"props":475,"children":477},{"className":476},[],[478],{"type":49,"value":479},"scrollIntoView",{"type":49,"value":481}," to force the widget to mount before interacting with it.",{"type":43,"tag":52,"props":483,"children":485},{"id":484},"test-authoring-guidelines",[486],{"type":49,"value":90},{"type":43,"tag":124,"props":488,"children":489},{},[490,492,498],{"type":49,"value":491},"Structure integration tests using the ",{"type":43,"tag":139,"props":493,"children":495},{"className":494},[],[496],{"type":49,"value":497},"flutter_test",{"type":49,"value":499}," API paradigm.",{"type":43,"tag":59,"props":501,"children":502},{},[503,516,529,549,561,581,600],{"type":43,"tag":63,"props":504,"children":505},{},[506,508,514],{"type":49,"value":507},"Create a dedicated ",{"type":43,"tag":139,"props":509,"children":511},{"className":510},[],[512],{"type":49,"value":513},"integration_test\u002F",{"type":49,"value":515}," directory at the project root.",{"type":43,"tag":63,"props":517,"children":518},{},[519,521,527],{"type":49,"value":520},"Name all test files using the ",{"type":43,"tag":139,"props":522,"children":524},{"className":523},[],[525],{"type":49,"value":526},"\u003Cname>_test.dart",{"type":49,"value":528}," convention.",{"type":43,"tag":63,"props":530,"children":531},{},[532,534,540,542,548],{"type":49,"value":533},"Initialize the binding by calling ",{"type":43,"tag":139,"props":535,"children":537},{"className":536},[],[538],{"type":49,"value":539},"IntegrationTestWidgetsFlutterBinding.ensureInitialized();",{"type":49,"value":541}," at the start of ",{"type":43,"tag":139,"props":543,"children":545},{"className":544},[],[546],{"type":49,"value":547},"main()",{"type":49,"value":261},{"type":43,"tag":63,"props":550,"children":551},{},[552,554,560],{"type":49,"value":553},"Load the application UI using ",{"type":43,"tag":139,"props":555,"children":557},{"className":556},[],[558],{"type":49,"value":559},"await tester.pumpWidget(MyApp());",{"type":49,"value":261},{"type":43,"tag":63,"props":562,"children":563},{},[564,566,572,574,580],{"type":49,"value":565},"Trigger frames and wait for animations to complete using ",{"type":43,"tag":139,"props":567,"children":569},{"className":568},[],[570],{"type":49,"value":571},"await tester.pumpAndSettle();",{"type":49,"value":573}," after interactions like ",{"type":43,"tag":139,"props":575,"children":577},{"className":576},[],[578],{"type":49,"value":579},"tester.tap()",{"type":49,"value":261},{"type":43,"tag":63,"props":582,"children":583},{},[584,586,592,593,599],{"type":49,"value":585},"Assert widget visibility using ",{"type":43,"tag":139,"props":587,"children":589},{"className":588},[],[590],{"type":49,"value":591},"expect(find.byKey(ValueKey('foo')), findsOneWidget);",{"type":49,"value":459},{"type":43,"tag":139,"props":594,"children":596},{"className":595},[],[597],{"type":49,"value":598},"findsNothing",{"type":49,"value":261},{"type":43,"tag":63,"props":601,"children":602},{},[603,605,611],{"type":49,"value":604},"Scroll to specific off-screen widgets using ",{"type":43,"tag":139,"props":606,"children":608},{"className":607},[],[609],{"type":49,"value":610},"await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder);",{"type":49,"value":261},{"type":43,"tag":124,"props":613,"children":614},{},[615],{"type":43,"tag":320,"props":616,"children":617},{},[618,620,626],{"type":49,"value":619},"Conditional Logic for Legacy ",{"type":43,"tag":139,"props":621,"children":623},{"className":622},[],[624],{"type":49,"value":625},"flutter_driver",{"type":49,"value":627},":",{"type":43,"tag":59,"props":629,"children":630},{},[631],{"type":43,"tag":63,"props":632,"children":633},{},[634,636,641,643,649,650,656,657,663,664,670,672,678],{"type":49,"value":635},"If maintaining or migrating legacy ",{"type":43,"tag":139,"props":637,"children":639},{"className":638},[],[640],{"type":49,"value":625},{"type":49,"value":642}," tests, use ",{"type":43,"tag":139,"props":644,"children":646},{"className":645},[],[647],{"type":49,"value":648},"driver.waitFor()",{"type":49,"value":399},{"type":43,"tag":139,"props":651,"children":653},{"className":652},[],[654],{"type":49,"value":655},"driver.waitForAbsent()",{"type":49,"value":399},{"type":43,"tag":139,"props":658,"children":660},{"className":659},[],[661],{"type":49,"value":662},"driver.tap()",{"type":49,"value":407},{"type":43,"tag":139,"props":665,"children":667},{"className":666},[],[668],{"type":49,"value":669},"driver.scroll()",{"type":49,"value":671}," instead of the ",{"type":43,"tag":139,"props":673,"children":675},{"className":674},[],[676],{"type":49,"value":677},"WidgetTester",{"type":49,"value":679}," APIs.",{"type":43,"tag":52,"props":681,"children":683},{"id":682},"execution-and-profiling",[684],{"type":49,"value":99},{"type":43,"tag":124,"props":686,"children":687},{},[688,690,696,698,704,706,712],{"type":49,"value":689},"Execute tests using the ",{"type":43,"tag":139,"props":691,"children":693},{"className":692},[],[694],{"type":49,"value":695},"flutter drive",{"type":49,"value":697}," command. Require a host driver script located in ",{"type":43,"tag":139,"props":699,"children":701},{"className":700},[],[702],{"type":49,"value":703},"test_driver\u002Fintegration_test.dart",{"type":49,"value":705}," that calls ",{"type":43,"tag":139,"props":707,"children":709},{"className":708},[],[710],{"type":49,"value":711},"integrationDriver()",{"type":49,"value":261},{"type":43,"tag":124,"props":714,"children":715},{},[716],{"type":43,"tag":320,"props":717,"children":718},{},[719],{"type":49,"value":720},"Conditional Execution Targets:",{"type":43,"tag":59,"props":722,"children":723},{},[724,748,765,782],{"type":43,"tag":63,"props":725,"children":726},{},[727,732,734,740,742],{"type":43,"tag":320,"props":728,"children":729},{},[730],{"type":49,"value":731},"If testing on Chrome:",{"type":49,"value":733}," Launch ",{"type":43,"tag":139,"props":735,"children":737},{"className":736},[],[738],{"type":49,"value":739},"chromedriver --port=4444",{"type":49,"value":741}," in a separate terminal, then run:\n",{"type":43,"tag":139,"props":743,"children":745},{"className":744},[],[746],{"type":49,"value":747},"flutter drive --driver=test_driver\u002Fintegration_test.dart --target=integration_test\u002Fapp_test.dart -d chrome",{"type":43,"tag":63,"props":749,"children":750},{},[751,756,758,764],{"type":43,"tag":320,"props":752,"children":753},{},[754],{"type":49,"value":755},"If testing headless web:",{"type":49,"value":757}," Run with ",{"type":43,"tag":139,"props":759,"children":761},{"className":760},[],[762],{"type":49,"value":763},"-d web-server",{"type":49,"value":261},{"type":43,"tag":63,"props":766,"children":767},{},[768,773,775,781],{"type":43,"tag":320,"props":769,"children":770},{},[771],{"type":49,"value":772},"If testing on Android (Local):",{"type":49,"value":774}," Run ",{"type":43,"tag":139,"props":776,"children":778},{"className":777},[],[779],{"type":49,"value":780},"flutter drive --driver=test_driver\u002Fintegration_test.dart --target=integration_test\u002Fapp_test.dart",{"type":49,"value":261},{"type":43,"tag":63,"props":783,"children":784},{},[785,790],{"type":43,"tag":320,"props":786,"children":787},{},[788],{"type":49,"value":789},"If testing on Firebase Test Lab (Android):",{"type":43,"tag":130,"props":791,"children":792},{},[793,804,815],{"type":43,"tag":63,"props":794,"children":795},{},[796,798],{"type":49,"value":797},"Build debug APK: ",{"type":43,"tag":139,"props":799,"children":801},{"className":800},[],[802],{"type":49,"value":803},"flutter build apk --debug",{"type":43,"tag":63,"props":805,"children":806},{},[807,809],{"type":49,"value":808},"Build test APK: ",{"type":43,"tag":139,"props":810,"children":812},{"className":811},[],[813],{"type":49,"value":814},".\u002Fgradlew app:assembleAndroidTest",{"type":43,"tag":63,"props":816,"children":817},{},[818],{"type":49,"value":819},"Upload both APKs to the Firebase Test Lab console.",{"type":43,"tag":52,"props":821,"children":823},{"id":822},"workflow-end-to-end-integration-testing",[824],{"type":49,"value":108},{"type":43,"tag":124,"props":826,"children":827},{},[828],{"type":49,"value":829},"Copy and follow this checklist to implement and verify integration tests.",{"type":43,"tag":59,"props":831,"children":834},{"className":832},[833],"contains-task-list",[835,921,990,1058],{"type":43,"tag":63,"props":836,"children":839},{"className":837},[838],"task-list-item",[840,846,848,853],{"type":43,"tag":841,"props":842,"children":845},"input",{"disabled":843,"type":844},true,"checkbox",[],{"type":49,"value":847}," ",{"type":43,"tag":320,"props":849,"children":850},{},[851],{"type":49,"value":852},"Task Progress: Setup",{"type":43,"tag":59,"props":854,"children":856},{"className":855},[833],[857,887,904],{"type":43,"tag":63,"props":858,"children":860},{"className":859},[838],[861,864,866,872,874,879,881,886],{"type":43,"tag":841,"props":862,"children":863},{"disabled":843,"type":844},[],{"type":49,"value":865}," Add ",{"type":43,"tag":139,"props":867,"children":869},{"className":868},[],[870],{"type":49,"value":871},"integration_test",{"type":49,"value":873}," and ",{"type":43,"tag":139,"props":875,"children":877},{"className":876},[],[878],{"type":49,"value":497},{"type":49,"value":880}," to ",{"type":43,"tag":139,"props":882,"children":884},{"className":883},[],[885],{"type":49,"value":144},{"type":49,"value":261},{"type":43,"tag":63,"props":888,"children":890},{"className":889},[838],[891,894,896,902],{"type":43,"tag":841,"props":892,"children":893},{"disabled":843,"type":844},[],{"type":49,"value":895}," Inject ",{"type":43,"tag":139,"props":897,"children":899},{"className":898},[],[900],{"type":49,"value":901},"enableFlutterDriverExtension()",{"type":49,"value":903}," into the app entry point.",{"type":43,"tag":63,"props":905,"children":907},{"className":906},[838],[908,911,913,919],{"type":43,"tag":841,"props":909,"children":910},{"disabled":843,"type":844},[],{"type":49,"value":912}," Assign ",{"type":43,"tag":139,"props":914,"children":916},{"className":915},[],[917],{"type":49,"value":918},"ValueKey",{"type":49,"value":920},"s to target widgets.",{"type":43,"tag":63,"props":922,"children":924},{"className":923},[838],[925,928,929,934],{"type":43,"tag":841,"props":926,"children":927},{"disabled":843,"type":844},[],{"type":49,"value":847},{"type":43,"tag":320,"props":930,"children":931},{},[932],{"type":49,"value":933},"Task Progress: Exploration",{"type":43,"tag":59,"props":935,"children":937},{"className":936},[833],[938,953,968],{"type":43,"tag":63,"props":939,"children":941},{"className":940},[838],[942,945,946,951],{"type":43,"tag":841,"props":943,"children":944},{"disabled":843,"type":844},[],{"type":49,"value":774},{"type":43,"tag":139,"props":947,"children":949},{"className":948},[],[950],{"type":49,"value":332},{"type":49,"value":952}," via MCP.",{"type":43,"tag":63,"props":954,"children":956},{"className":955},[838],[957,960,962,967],{"type":43,"tag":841,"props":958,"children":959},{"disabled":843,"type":844},[],{"type":49,"value":961}," Map the widget tree using ",{"type":43,"tag":139,"props":963,"children":965},{"className":964},[],[966],{"type":49,"value":357},{"type":49,"value":261},{"type":43,"tag":63,"props":969,"children":971},{"className":970},[838],[972,975,977,982,983,988],{"type":43,"tag":841,"props":973,"children":974},{"disabled":843,"type":844},[],{"type":49,"value":976}," Validate interaction paths using MCP tools (",{"type":43,"tag":139,"props":978,"children":980},{"className":979},[],[981],{"type":49,"value":397},{"type":49,"value":399},{"type":43,"tag":139,"props":984,"children":986},{"className":985},[],[987],{"type":49,"value":405},{"type":49,"value":989},").",{"type":43,"tag":63,"props":991,"children":993},{"className":992},[838],[994,997,998,1003],{"type":43,"tag":841,"props":995,"children":996},{"disabled":843,"type":844},[],{"type":49,"value":847},{"type":43,"tag":320,"props":999,"children":1000},{},[1001],{"type":49,"value":1002},"Task Progress: Authoring",{"type":43,"tag":59,"props":1004,"children":1006},{"className":1005},[833],[1007,1023,1038],{"type":43,"tag":63,"props":1008,"children":1010},{"className":1009},[838],[1011,1014,1016,1022],{"type":43,"tag":841,"props":1012,"children":1013},{"disabled":843,"type":844},[],{"type":49,"value":1015}," Create ",{"type":43,"tag":139,"props":1017,"children":1019},{"className":1018},[],[1020],{"type":49,"value":1021},"integration_test\u002Fapp_test.dart",{"type":49,"value":261},{"type":43,"tag":63,"props":1024,"children":1026},{"className":1025},[838],[1027,1030,1032,1037],{"type":43,"tag":841,"props":1028,"children":1029},{"disabled":843,"type":844},[],{"type":49,"value":1031}," Write test cases using ",{"type":43,"tag":139,"props":1033,"children":1035},{"className":1034},[],[1036],{"type":49,"value":677},{"type":49,"value":679},{"type":43,"tag":63,"props":1039,"children":1041},{"className":1040},[838],[1042,1045,1046,1051,1052,1057],{"type":43,"tag":841,"props":1043,"children":1044},{"disabled":843,"type":844},[],{"type":49,"value":1015},{"type":43,"tag":139,"props":1047,"children":1049},{"className":1048},[],[1050],{"type":49,"value":703},{"type":49,"value":334},{"type":43,"tag":139,"props":1053,"children":1055},{"className":1054},[],[1056],{"type":49,"value":711},{"type":49,"value":261},{"type":43,"tag":63,"props":1059,"children":1061},{"className":1060},[838],[1062,1065,1066,1071],{"type":43,"tag":841,"props":1063,"children":1064},{"disabled":843,"type":844},[],{"type":49,"value":847},{"type":43,"tag":320,"props":1067,"children":1068},{},[1069],{"type":49,"value":1070},"Task Progress: Execution & Feedback Loop",{"type":43,"tag":59,"props":1072,"children":1074},{"className":1073},[833],[1075,1089],{"type":43,"tag":63,"props":1076,"children":1078},{"className":1077},[838],[1079,1082,1083,1088],{"type":43,"tag":841,"props":1080,"children":1081},{"disabled":843,"type":844},[],{"type":49,"value":774},{"type":43,"tag":139,"props":1084,"children":1086},{"className":1085},[],[1087],{"type":49,"value":780},{"type":49,"value":261},{"type":43,"tag":63,"props":1090,"children":1092},{"className":1091},[838],[1093,1096,1097,1102,1104,1110,1112,1118],{"type":43,"tag":841,"props":1094,"children":1095},{"disabled":843,"type":844},[],{"type":49,"value":847},{"type":43,"tag":320,"props":1098,"children":1099},{},[1100],{"type":49,"value":1101},"Feedback Loop",{"type":49,"value":1103},": Review test output -> If ",{"type":43,"tag":139,"props":1105,"children":1107},{"className":1106},[],[1108],{"type":49,"value":1109},"PumpAndSettleTimedOutException",{"type":49,"value":1111}," occurs, check for infinite animations -> If widget not found, add ",{"type":43,"tag":139,"props":1113,"children":1115},{"className":1114},[],[1116],{"type":49,"value":1117},"scrollUntilVisible",{"type":49,"value":1119}," -> Re-run test until passing.",{"type":43,"tag":52,"props":1121,"children":1123},{"id":1122},"examples",[1124],{"type":49,"value":117},{"type":43,"tag":1126,"props":1127,"children":1129},"h3",{"id":1128},"standard-integration-test-integration_testapp_testdart",[1130,1132,1137],{"type":49,"value":1131},"Standard Integration Test (",{"type":43,"tag":139,"props":1133,"children":1135},{"className":1134},[],[1136],{"type":49,"value":1021},{"type":49,"value":1138},")",{"type":43,"tag":148,"props":1140,"children":1144},{"className":1141,"code":1142,"language":1143,"meta":153,"style":153},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import 'package:flutter\u002Fmaterial.dart';\nimport 'package:flutter_test\u002Fflutter_test.dart';\nimport 'package:integration_test\u002Fintegration_test.dart';\nimport 'package:my_app\u002Fmain.dart';\n\nvoid main() {\n  IntegrationTestWidgetsFlutterBinding.ensureInitialized();\n\n  group('End-to-end test', () {\n    testWidgets('tap on the floating action button, verify counter', (tester) async {\n      \u002F\u002F Load app widget.\n      await tester.pumpWidget(const MyApp());\n\n      \u002F\u002F Verify the counter starts at 0.\n      expect(find.text('0'), findsOneWidget);\n\n      \u002F\u002F Find the floating action button to tap on.\n      final fab = find.byKey(const ValueKey('increment'));\n\n      \u002F\u002F Emulate a tap on the floating action button.\n      await tester.tap(fab);\n\n      \u002F\u002F Trigger a frame and wait for animations.\n      await tester.pumpAndSettle();\n\n      \u002F\u002F Verify the counter increments by 1.\n      expect(find.text('1'), findsOneWidget);\n    });\n  });\n}\n","dart",[1145],{"type":43,"tag":139,"props":1146,"children":1147},{"__ignoreMap":153},[1148,1156,1164,1173,1182,1191,1200,1209,1217,1226,1235,1244,1253,1261,1270,1279,1287,1296,1305,1313,1322,1331,1339,1348,1357,1365,1374,1383,1392,1401],{"type":43,"tag":159,"props":1149,"children":1150},{"class":161,"line":162},[1151],{"type":43,"tag":159,"props":1152,"children":1153},{},[1154],{"type":49,"value":1155},"import 'package:flutter\u002Fmaterial.dart';\n",{"type":43,"tag":159,"props":1157,"children":1158},{"class":161,"line":198},[1159],{"type":43,"tag":159,"props":1160,"children":1161},{},[1162],{"type":49,"value":1163},"import 'package:flutter_test\u002Fflutter_test.dart';\n",{"type":43,"tag":159,"props":1165,"children":1167},{"class":161,"line":1166},3,[1168],{"type":43,"tag":159,"props":1169,"children":1170},{},[1171],{"type":49,"value":1172},"import 'package:integration_test\u002Fintegration_test.dart';\n",{"type":43,"tag":159,"props":1174,"children":1176},{"class":161,"line":1175},4,[1177],{"type":43,"tag":159,"props":1178,"children":1179},{},[1180],{"type":49,"value":1181},"import 'package:my_app\u002Fmain.dart';\n",{"type":43,"tag":159,"props":1183,"children":1185},{"class":161,"line":1184},5,[1186],{"type":43,"tag":159,"props":1187,"children":1188},{"emptyLinePlaceholder":843},[1189],{"type":49,"value":1190},"\n",{"type":43,"tag":159,"props":1192,"children":1194},{"class":161,"line":1193},6,[1195],{"type":43,"tag":159,"props":1196,"children":1197},{},[1198],{"type":49,"value":1199},"void main() {\n",{"type":43,"tag":159,"props":1201,"children":1203},{"class":161,"line":1202},7,[1204],{"type":43,"tag":159,"props":1205,"children":1206},{},[1207],{"type":49,"value":1208},"  IntegrationTestWidgetsFlutterBinding.ensureInitialized();\n",{"type":43,"tag":159,"props":1210,"children":1212},{"class":161,"line":1211},8,[1213],{"type":43,"tag":159,"props":1214,"children":1215},{"emptyLinePlaceholder":843},[1216],{"type":49,"value":1190},{"type":43,"tag":159,"props":1218,"children":1220},{"class":161,"line":1219},9,[1221],{"type":43,"tag":159,"props":1222,"children":1223},{},[1224],{"type":49,"value":1225},"  group('End-to-end test', () {\n",{"type":43,"tag":159,"props":1227,"children":1229},{"class":161,"line":1228},10,[1230],{"type":43,"tag":159,"props":1231,"children":1232},{},[1233],{"type":49,"value":1234},"    testWidgets('tap on the floating action button, verify counter', (tester) async {\n",{"type":43,"tag":159,"props":1236,"children":1238},{"class":161,"line":1237},11,[1239],{"type":43,"tag":159,"props":1240,"children":1241},{},[1242],{"type":49,"value":1243},"      \u002F\u002F Load app widget.\n",{"type":43,"tag":159,"props":1245,"children":1247},{"class":161,"line":1246},12,[1248],{"type":43,"tag":159,"props":1249,"children":1250},{},[1251],{"type":49,"value":1252},"      await tester.pumpWidget(const MyApp());\n",{"type":43,"tag":159,"props":1254,"children":1256},{"class":161,"line":1255},13,[1257],{"type":43,"tag":159,"props":1258,"children":1259},{"emptyLinePlaceholder":843},[1260],{"type":49,"value":1190},{"type":43,"tag":159,"props":1262,"children":1264},{"class":161,"line":1263},14,[1265],{"type":43,"tag":159,"props":1266,"children":1267},{},[1268],{"type":49,"value":1269},"      \u002F\u002F Verify the counter starts at 0.\n",{"type":43,"tag":159,"props":1271,"children":1273},{"class":161,"line":1272},15,[1274],{"type":43,"tag":159,"props":1275,"children":1276},{},[1277],{"type":49,"value":1278},"      expect(find.text('0'), findsOneWidget);\n",{"type":43,"tag":159,"props":1280,"children":1282},{"class":161,"line":1281},16,[1283],{"type":43,"tag":159,"props":1284,"children":1285},{"emptyLinePlaceholder":843},[1286],{"type":49,"value":1190},{"type":43,"tag":159,"props":1288,"children":1290},{"class":161,"line":1289},17,[1291],{"type":43,"tag":159,"props":1292,"children":1293},{},[1294],{"type":49,"value":1295},"      \u002F\u002F Find the floating action button to tap on.\n",{"type":43,"tag":159,"props":1297,"children":1299},{"class":161,"line":1298},18,[1300],{"type":43,"tag":159,"props":1301,"children":1302},{},[1303],{"type":49,"value":1304},"      final fab = find.byKey(const ValueKey('increment'));\n",{"type":43,"tag":159,"props":1306,"children":1308},{"class":161,"line":1307},19,[1309],{"type":43,"tag":159,"props":1310,"children":1311},{"emptyLinePlaceholder":843},[1312],{"type":49,"value":1190},{"type":43,"tag":159,"props":1314,"children":1316},{"class":161,"line":1315},20,[1317],{"type":43,"tag":159,"props":1318,"children":1319},{},[1320],{"type":49,"value":1321},"      \u002F\u002F Emulate a tap on the floating action button.\n",{"type":43,"tag":159,"props":1323,"children":1325},{"class":161,"line":1324},21,[1326],{"type":43,"tag":159,"props":1327,"children":1328},{},[1329],{"type":49,"value":1330},"      await tester.tap(fab);\n",{"type":43,"tag":159,"props":1332,"children":1334},{"class":161,"line":1333},22,[1335],{"type":43,"tag":159,"props":1336,"children":1337},{"emptyLinePlaceholder":843},[1338],{"type":49,"value":1190},{"type":43,"tag":159,"props":1340,"children":1342},{"class":161,"line":1341},23,[1343],{"type":43,"tag":159,"props":1344,"children":1345},{},[1346],{"type":49,"value":1347},"      \u002F\u002F Trigger a frame and wait for animations.\n",{"type":43,"tag":159,"props":1349,"children":1351},{"class":161,"line":1350},24,[1352],{"type":43,"tag":159,"props":1353,"children":1354},{},[1355],{"type":49,"value":1356},"      await tester.pumpAndSettle();\n",{"type":43,"tag":159,"props":1358,"children":1360},{"class":161,"line":1359},25,[1361],{"type":43,"tag":159,"props":1362,"children":1363},{"emptyLinePlaceholder":843},[1364],{"type":49,"value":1190},{"type":43,"tag":159,"props":1366,"children":1368},{"class":161,"line":1367},26,[1369],{"type":43,"tag":159,"props":1370,"children":1371},{},[1372],{"type":49,"value":1373},"      \u002F\u002F Verify the counter increments by 1.\n",{"type":43,"tag":159,"props":1375,"children":1377},{"class":161,"line":1376},27,[1378],{"type":43,"tag":159,"props":1379,"children":1380},{},[1381],{"type":49,"value":1382},"      expect(find.text('1'), findsOneWidget);\n",{"type":43,"tag":159,"props":1384,"children":1386},{"class":161,"line":1385},28,[1387],{"type":43,"tag":159,"props":1388,"children":1389},{},[1390],{"type":49,"value":1391},"    });\n",{"type":43,"tag":159,"props":1393,"children":1395},{"class":161,"line":1394},29,[1396],{"type":43,"tag":159,"props":1397,"children":1398},{},[1399],{"type":49,"value":1400},"  });\n",{"type":43,"tag":159,"props":1402,"children":1404},{"class":161,"line":1403},30,[1405],{"type":43,"tag":159,"props":1406,"children":1407},{},[1408],{"type":49,"value":1409},"}\n",{"type":43,"tag":1126,"props":1411,"children":1413},{"id":1412},"host-driver-script-test_driverintegration_testdart",[1414,1416,1421],{"type":49,"value":1415},"Host Driver Script (",{"type":43,"tag":139,"props":1417,"children":1419},{"className":1418},[],[1420],{"type":49,"value":703},{"type":49,"value":1138},{"type":43,"tag":148,"props":1423,"children":1425},{"className":1141,"code":1424,"language":1143,"meta":153,"style":153},"import 'package:integration_test\u002Fintegration_test_driver.dart';\n\nFuture\u003Cvoid> main() => integrationDriver();\n",[1426],{"type":43,"tag":139,"props":1427,"children":1428},{"__ignoreMap":153},[1429,1437,1444],{"type":43,"tag":159,"props":1430,"children":1431},{"class":161,"line":162},[1432],{"type":43,"tag":159,"props":1433,"children":1434},{},[1435],{"type":49,"value":1436},"import 'package:integration_test\u002Fintegration_test_driver.dart';\n",{"type":43,"tag":159,"props":1438,"children":1439},{"class":161,"line":198},[1440],{"type":43,"tag":159,"props":1441,"children":1442},{"emptyLinePlaceholder":843},[1443],{"type":49,"value":1190},{"type":43,"tag":159,"props":1445,"children":1446},{"class":161,"line":1166},[1447],{"type":43,"tag":159,"props":1448,"children":1449},{},[1450],{"type":49,"value":1451},"Future\u003Cvoid> main() => integrationDriver();\n",{"type":43,"tag":1126,"props":1453,"children":1455},{"id":1454},"performance-profiling-driver-script-test_driverperf_driverdart",[1456,1458,1464],{"type":49,"value":1457},"Performance Profiling Driver Script (",{"type":43,"tag":139,"props":1459,"children":1461},{"className":1460},[],[1462],{"type":49,"value":1463},"test_driver\u002Fperf_driver.dart",{"type":49,"value":1138},{"type":43,"tag":124,"props":1466,"children":1467},{},[1468,1470,1476],{"type":49,"value":1469},"Use this driver script if you wrap your test actions in ",{"type":43,"tag":139,"props":1471,"children":1473},{"className":1472},[],[1474],{"type":49,"value":1475},"binding.traceAction()",{"type":49,"value":1477}," to capture performance metrics.",{"type":43,"tag":148,"props":1479,"children":1481},{"className":1141,"code":1480,"language":1143,"meta":153,"style":153},"import 'package:flutter_driver\u002Fflutter_driver.dart' as driver;\nimport 'package:integration_test\u002Fintegration_test_driver.dart';\n\nFuture\u003Cvoid> main() {\n  return integrationDriver(\n    responseDataCallback: (data) async {\n      if (data != null) {\n        final timeline = driver.Timeline.fromJson(\n          data['scrolling_timeline'] as Map\u003CString, dynamic>,\n        );\n\n        final summary = driver.TimelineSummary.summarize(timeline);\n\n        await summary.writeTimelineToFile(\n          'scrolling_timeline',\n          pretty: true,\n          includeSummary: true,\n        );\n      }\n    },\n  );\n}\n",[1482],{"type":43,"tag":139,"props":1483,"children":1484},{"__ignoreMap":153},[1485,1493,1500,1507,1515,1523,1531,1539,1547,1555,1563,1570,1578,1585,1593,1601,1609,1617,1624,1632,1640,1648],{"type":43,"tag":159,"props":1486,"children":1487},{"class":161,"line":162},[1488],{"type":43,"tag":159,"props":1489,"children":1490},{},[1491],{"type":49,"value":1492},"import 'package:flutter_driver\u002Fflutter_driver.dart' as driver;\n",{"type":43,"tag":159,"props":1494,"children":1495},{"class":161,"line":198},[1496],{"type":43,"tag":159,"props":1497,"children":1498},{},[1499],{"type":49,"value":1436},{"type":43,"tag":159,"props":1501,"children":1502},{"class":161,"line":1166},[1503],{"type":43,"tag":159,"props":1504,"children":1505},{"emptyLinePlaceholder":843},[1506],{"type":49,"value":1190},{"type":43,"tag":159,"props":1508,"children":1509},{"class":161,"line":1175},[1510],{"type":43,"tag":159,"props":1511,"children":1512},{},[1513],{"type":49,"value":1514},"Future\u003Cvoid> main() {\n",{"type":43,"tag":159,"props":1516,"children":1517},{"class":161,"line":1184},[1518],{"type":43,"tag":159,"props":1519,"children":1520},{},[1521],{"type":49,"value":1522},"  return integrationDriver(\n",{"type":43,"tag":159,"props":1524,"children":1525},{"class":161,"line":1193},[1526],{"type":43,"tag":159,"props":1527,"children":1528},{},[1529],{"type":49,"value":1530},"    responseDataCallback: (data) async {\n",{"type":43,"tag":159,"props":1532,"children":1533},{"class":161,"line":1202},[1534],{"type":43,"tag":159,"props":1535,"children":1536},{},[1537],{"type":49,"value":1538},"      if (data != null) {\n",{"type":43,"tag":159,"props":1540,"children":1541},{"class":161,"line":1211},[1542],{"type":43,"tag":159,"props":1543,"children":1544},{},[1545],{"type":49,"value":1546},"        final timeline = driver.Timeline.fromJson(\n",{"type":43,"tag":159,"props":1548,"children":1549},{"class":161,"line":1219},[1550],{"type":43,"tag":159,"props":1551,"children":1552},{},[1553],{"type":49,"value":1554},"          data['scrolling_timeline'] as Map\u003CString, dynamic>,\n",{"type":43,"tag":159,"props":1556,"children":1557},{"class":161,"line":1228},[1558],{"type":43,"tag":159,"props":1559,"children":1560},{},[1561],{"type":49,"value":1562},"        );\n",{"type":43,"tag":159,"props":1564,"children":1565},{"class":161,"line":1237},[1566],{"type":43,"tag":159,"props":1567,"children":1568},{"emptyLinePlaceholder":843},[1569],{"type":49,"value":1190},{"type":43,"tag":159,"props":1571,"children":1572},{"class":161,"line":1246},[1573],{"type":43,"tag":159,"props":1574,"children":1575},{},[1576],{"type":49,"value":1577},"        final summary = driver.TimelineSummary.summarize(timeline);\n",{"type":43,"tag":159,"props":1579,"children":1580},{"class":161,"line":1255},[1581],{"type":43,"tag":159,"props":1582,"children":1583},{"emptyLinePlaceholder":843},[1584],{"type":49,"value":1190},{"type":43,"tag":159,"props":1586,"children":1587},{"class":161,"line":1263},[1588],{"type":43,"tag":159,"props":1589,"children":1590},{},[1591],{"type":49,"value":1592},"        await summary.writeTimelineToFile(\n",{"type":43,"tag":159,"props":1594,"children":1595},{"class":161,"line":1272},[1596],{"type":43,"tag":159,"props":1597,"children":1598},{},[1599],{"type":49,"value":1600},"          'scrolling_timeline',\n",{"type":43,"tag":159,"props":1602,"children":1603},{"class":161,"line":1281},[1604],{"type":43,"tag":159,"props":1605,"children":1606},{},[1607],{"type":49,"value":1608},"          pretty: true,\n",{"type":43,"tag":159,"props":1610,"children":1611},{"class":161,"line":1289},[1612],{"type":43,"tag":159,"props":1613,"children":1614},{},[1615],{"type":49,"value":1616},"          includeSummary: true,\n",{"type":43,"tag":159,"props":1618,"children":1619},{"class":161,"line":1298},[1620],{"type":43,"tag":159,"props":1621,"children":1622},{},[1623],{"type":49,"value":1562},{"type":43,"tag":159,"props":1625,"children":1626},{"class":161,"line":1307},[1627],{"type":43,"tag":159,"props":1628,"children":1629},{},[1630],{"type":49,"value":1631},"      }\n",{"type":43,"tag":159,"props":1633,"children":1634},{"class":161,"line":1315},[1635],{"type":43,"tag":159,"props":1636,"children":1637},{},[1638],{"type":49,"value":1639},"    },\n",{"type":43,"tag":159,"props":1641,"children":1642},{"class":161,"line":1324},[1643],{"type":43,"tag":159,"props":1644,"children":1645},{},[1646],{"type":49,"value":1647},"  );\n",{"type":43,"tag":159,"props":1649,"children":1650},{"class":161,"line":1333},[1651],{"type":43,"tag":159,"props":1652,"children":1653},{},[1654],{"type":49,"value":1409},{"type":43,"tag":1656,"props":1657,"children":1658},"style",{},[1659],{"type":49,"value":1660},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1662,"total":1350},[1663,1673,1684,1696,1707,1716,1728],{"slug":1664,"name":1664,"fn":1665,"description":1666,"org":1667,"tags":1668,"stars":24,"repoUrl":25,"updatedAt":1672},"dart-add-unit-test","write unit tests for Dart code","Write and organize unit tests for functions, methods, and classes using `package:test`. Use when creating new logic or fixing bugs to ensure code remains correct and regression-free.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1669,1671],{"name":1670,"slug":1143,"type":14},"Dart",{"name":22,"slug":23,"type":14},"2026-07-15T05:22:40.104823",{"slug":1674,"name":1674,"fn":1675,"description":1676,"org":1677,"tags":1678,"stars":24,"repoUrl":25,"updatedAt":1683},"dart-build-cli-app","build Dart command line applications","Entrypoint structure, exit codes, cross-platform scripts. Use when building command line utilities, scripts, or applications.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1679,1682],{"name":1680,"slug":1681,"type":14},"CLI","cli",{"name":1670,"slug":1143,"type":14},"2026-07-15T05:22:18.863572",{"slug":1685,"name":1685,"fn":1686,"description":1687,"org":1688,"tags":1689,"stars":24,"repoUrl":25,"updatedAt":1695},"dart-collect-coverage","collect Dart test coverage reports","Collect coverage using the coverage packge and create an LCOV report",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1690,1691,1694],{"name":1670,"slug":1143,"type":14},{"name":1692,"slug":1693,"type":14},"Reporting","reporting",{"name":22,"slug":23,"type":14},"2026-07-15T05:22:21.38636",{"slug":1697,"name":1697,"fn":1698,"description":1699,"org":1700,"tags":1701,"stars":24,"repoUrl":25,"updatedAt":1706},"dart-fix-runtime-errors","debug and fix Dart runtime errors","Uses get_runtime_errors and lsp to fetch an active stack trace, locate the failing line, apply a fix, and verify resolution via hot_reload.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1702,1703],{"name":1670,"slug":1143,"type":14},{"name":1704,"slug":1705,"type":14},"Debugging","debugging","2026-07-15T05:22:22.622501",{"slug":1708,"name":1708,"fn":1709,"description":1710,"org":1711,"tags":1712,"stars":24,"repoUrl":25,"updatedAt":1715},"dart-generate-test-mocks","generate mock objects for Dart tests","Define and generate mock objects for external dependencies using `package:mockito` and `build_runner`. Use when unit testing classes that depend on complex external services like APIs or databases.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1713,1714],{"name":1670,"slug":1143,"type":14},{"name":22,"slug":23,"type":14},"2026-07-15T05:22:42.607449",{"slug":1717,"name":1717,"fn":1718,"description":1719,"org":1720,"tags":1721,"stars":24,"repoUrl":25,"updatedAt":1727},"dart-migrate-to-checks-package","migrate test matchers to checks package","Replace the usage of `expect` and similar functions from `package:matcher`\nto `package:checks` equivalents.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1722,1723,1726],{"name":1670,"slug":1143,"type":14},{"name":1724,"slug":1725,"type":14},"Migration","migration",{"name":22,"slug":23,"type":14},"2026-07-15T05:22:31.276564",{"slug":1729,"name":1729,"fn":1730,"description":1731,"org":1732,"tags":1733,"stars":24,"repoUrl":25,"updatedAt":1739},"dart-resolve-package-conflicts","resolve Dart package version conflicts","Workflow for fixing package version conflicts. Use this when `pub get` fails due to incompatible package versions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1734,1735,1736],{"name":1670,"slug":1143,"type":14},{"name":1704,"slug":1705,"type":14},{"name":1737,"slug":1738,"type":14},"Engineering","engineering","2026-07-15T05:22:30.059335",{"items":1741,"total":1376},[1742,1747,1752,1758,1763,1768,1774,1780,1792,1804,1818,1828],{"slug":1664,"name":1664,"fn":1665,"description":1666,"org":1743,"tags":1744,"stars":24,"repoUrl":25,"updatedAt":1672},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1745,1746],{"name":1670,"slug":1143,"type":14},{"name":22,"slug":23,"type":14},{"slug":1674,"name":1674,"fn":1675,"description":1676,"org":1748,"tags":1749,"stars":24,"repoUrl":25,"updatedAt":1683},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1750,1751],{"name":1680,"slug":1681,"type":14},{"name":1670,"slug":1143,"type":14},{"slug":1685,"name":1685,"fn":1686,"description":1687,"org":1753,"tags":1754,"stars":24,"repoUrl":25,"updatedAt":1695},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1755,1756,1757],{"name":1670,"slug":1143,"type":14},{"name":1692,"slug":1693,"type":14},{"name":22,"slug":23,"type":14},{"slug":1697,"name":1697,"fn":1698,"description":1699,"org":1759,"tags":1760,"stars":24,"repoUrl":25,"updatedAt":1706},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1761,1762],{"name":1670,"slug":1143,"type":14},{"name":1704,"slug":1705,"type":14},{"slug":1708,"name":1708,"fn":1709,"description":1710,"org":1764,"tags":1765,"stars":24,"repoUrl":25,"updatedAt":1715},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1766,1767],{"name":1670,"slug":1143,"type":14},{"name":22,"slug":23,"type":14},{"slug":1717,"name":1717,"fn":1718,"description":1719,"org":1769,"tags":1770,"stars":24,"repoUrl":25,"updatedAt":1727},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1771,1772,1773],{"name":1670,"slug":1143,"type":14},{"name":1724,"slug":1725,"type":14},{"name":22,"slug":23,"type":14},{"slug":1729,"name":1729,"fn":1730,"description":1731,"org":1775,"tags":1776,"stars":24,"repoUrl":25,"updatedAt":1739},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1777,1778,1779],{"name":1670,"slug":1143,"type":14},{"name":1704,"slug":1705,"type":14},{"name":1737,"slug":1738,"type":14},{"slug":1781,"name":1781,"fn":1782,"description":1783,"org":1784,"tags":1785,"stars":24,"repoUrl":25,"updatedAt":1791},"dart-run-static-analysis","run static analysis and apply fixes","Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1786,1789,1790],{"name":1787,"slug":1788,"type":14},"Code Analysis","code-analysis",{"name":1670,"slug":1143,"type":14},{"name":1704,"slug":1705,"type":14},"2026-07-15T05:22:23.861119",{"slug":1793,"name":1793,"fn":1794,"description":1795,"org":1796,"tags":1797,"stars":24,"repoUrl":25,"updatedAt":1803},"dart-setup-ffi-assets","package C\u002FC++ assets for Dart","Guides agents in compiling and packaging C\u002FC++ source code into dynamic or static libraries (Code Assets) using Dart's Native Assets hook system (via hook\u002Fbuild.dart and hook\u002Flink.dart utilizing package:hooks and package:native_toolchain_c). Use when a user asks to: 'setup native assets', 'compile C\u002FC++ source code', 'bundle dynamic libraries', 'build native C code', 'link native assets', 'implement build.dart or link.dart hooks', or 'integrate C\u002FC++ interop in Dart\u002FFlutter'. Helps agents avoid manual toolchain orchestration and configures secure hash-validated binary downloads or advanced linker tree-shaking with package:record_use mapping.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1798,1799,1802],{"name":1670,"slug":1143,"type":14},{"name":1800,"slug":1801,"type":14},"Deployment","deployment",{"name":1737,"slug":1738,"type":14},"2026-07-15T05:22:20.138636",{"slug":1805,"name":1805,"fn":1806,"description":1807,"org":1808,"tags":1809,"stars":24,"repoUrl":25,"updatedAt":1817},"dart-skills-lint-setup","configure dart_skills_lint for Dart projects","Use this skill when you need to set up validation for AI agent skills in a Dart project for the first time.\nAdds the linter as a dev_dependency, creates a configuration file, and generates a baseline for legacy repos.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1810,1811,1814],{"name":1670,"slug":1143,"type":14},{"name":1812,"slug":1813,"type":14},"Plugin Development","plugin-development",{"name":1815,"slug":1816,"type":14},"QA","qa","2026-07-15T05:22:47.488998",{"slug":1819,"name":1819,"fn":1820,"description":1821,"org":1822,"tags":1823,"stars":24,"repoUrl":25,"updatedAt":1827},"dart-skills-lint-validation","validate agent skills with dart_skills_lint","Use this skill when you need to validate AI agent skills with dart_skills_lint — running the linter, interpreting failures, fixing violations, and authoring custom rules.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1824,1825,1826],{"name":1670,"slug":1143,"type":14},{"name":1812,"slug":1813,"type":14},{"name":1815,"slug":1816,"type":14},"2026-07-21T05:38:34.451024",{"slug":1829,"name":1829,"fn":1830,"description":1831,"org":1832,"tags":1833,"stars":24,"repoUrl":25,"updatedAt":1836},"dart-use-ffigen","generate FFI bindings with ffigen","Guide agents to use `package:ffigen` to automatically generate FFI bindings instead of writing them manually. Use this skill when a task involves writing new FFI bindings, extending C\u002FObjective-C\u002FSwift integrations, or replacing hand-crafted `dart:ffi` setups.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1834,1835],{"name":1670,"slug":1143,"type":14},{"name":1737,"slug":1738,"type":14},"2026-07-15T05:22:17.592351"]