[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-flutter-flutter-add-widget-test":3,"mdc--3zb50p-key":31,"related-repo-flutter-flutter-add-widget-test":1447,"related-org-flutter-flutter-add-widget-test":1526},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":21,"repoUrl":22,"updatedAt":23,"license":24,"forks":25,"topics":26,"repo":27,"sourceUrl":29,"mdContent":30},"flutter-add-widget-test","implement Flutter widget tests","Implement a component-level test using `WidgetTester` to verify UI rendering and user interactions (tapping, scrolling, entering text). Use when validating that a specific widget displays correct data and responds to events as expected.",{"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],{"name":13,"slug":8,"type":14},"Flutter","tag",{"name":16,"slug":17,"type":14},"UI Components","ui-components",{"name":19,"slug":20,"type":14},"Testing","testing",2664,"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins","2026-07-15T05:22:41.334507",null,155,[],{"repoUrl":22,"stars":21,"forks":25,"topics":28,"description":24},[],"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins\u002Ftree\u002FHEAD\u002Fskills\u002Fflutter-add-widget-test","---\nname: flutter-add-widget-test\ndescription: Implement a component-level test using `WidgetTester` to verify UI rendering and user interactions (tapping, scrolling, entering text). Use when validating that a specific widget displays correct data and responds to events as expected.\nmetadata:\n  model: models\u002Fgemini-3.1-pro-preview\n  last_modified: Tue, 21 Apr 2026 21:15:41 GMT\n---\n# Writing Flutter Widget Tests\n\n## Contents\n- [Setup & Configuration](#setup--configuration)\n- [Core Components](#core-components)\n- [Workflow: Implementing a Widget Test](#workflow-implementing-a-widget-test)\n- [Interaction & State Management](#interaction--state-management)\n- [Examples](#examples)\n\n## Setup & Configuration\n\nEnsure the testing environment is properly configured before authoring widget tests.\n\n1. Add the `flutter_test` dependency to the `dev_dependencies` section of `pubspec.yaml`.\n2. Place all test files in the `test\u002F` directory at the root of the project.\n3. Suffix all test file names with `_test.dart` (e.g., `widget_test.dart`).\n\n## Core Components\n\nUtilize the following `flutter_test` components to interact with and validate the widget tree:\n\n*   **`WidgetTester`**: The primary interface for building and interacting with widgets in the test environment. Provided automatically by the `testWidgets()` function.\n*   **`Finder`**: Locates widgets in the test environment (e.g., `find.text('Submit')`, `find.byType(TextField)`, `find.byKey(Key('submit_btn'))`).\n*   **`Matcher`**: Verifies the presence or state of widgets located by a `Finder` (e.g., `findsOneWidget`, `findsNothing`, `findsNWidgets(2)`, `matchesGoldenFile`).\n\n## Workflow: Implementing a Widget Test\n\nCopy the following checklist to track progress when implementing a new widget test.\n\n### Task Progress\n- [ ] **Step 1: Define the test.** Use `testWidgets('description', (WidgetTester tester) async { ... })`.\n- [ ] **Step 2: Build the widget.** Call `await tester.pumpWidget(MyWidget())` to render the UI. Wrap the widget in a `MaterialApp` or `Directionality` widget if it requires inherited directional or theme data.\n- [ ] **Step 3: Locate elements.** Instantiate `Finder` objects for the target widgets.\n- [ ] **Step 4: Verify initial state.** Use `expect(finder, matcher)` to validate the initial render.\n- [ ] **Step 5: Simulate interactions.** Execute gestures or inputs (e.g., `await tester.tap(buttonFinder)`).\n- [ ] **Step 6: Rebuild the tree.** Call `await tester.pump()` or `await tester.pumpAndSettle()` to process state changes.\n- [ ] **Step 7: Verify updated state.** Use `expect()` to validate the UI after the interaction.\n- [ ] **Step 8: Run and validate.** Execute `flutter test test\u002Fyour_test_file_test.dart`.\n- [ ] **Step 9: Feedback Loop.** Review test output -> identify failing matchers -> adjust widget logic or test assertions -> re-run until passing.\n\n## Interaction & State Management\n\nApply the following conditional logic based on the type of interaction or state change being tested:\n\n*   **If testing static rendering:** Call `await tester.pumpWidget()` once, then immediately run `expect()` assertions.\n*   **If testing standard state changes (e.g., button taps):** \n    1. Call `await tester.tap(finder)`.\n    2. Call `await tester.pump()` to trigger a single frame rebuild.\n*   **If testing animations, transitions, or asynchronous UI updates:** \n    1. Trigger the action (e.g., `await tester.drag(finder, Offset(500, 0))`).\n    2. Call `await tester.pumpAndSettle()` to repeatedly pump frames until no more frames are scheduled (animation completes).\n*   **If testing text input:** Call `await tester.enterText(textFieldFinder, 'Input string')`.\n*   **If testing items in a dynamic or long list:** Call `await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder)` to ensure the target widget is rendered before interacting with it.\n\n## Examples\n\n### High-Fidelity Widget Test Implementation\n\n**Target Widget (`lib\u002Ftodo_list.dart`):**\n```dart\nimport 'package:flutter\u002Fmaterial.dart';\n\nclass TodoList extends StatefulWidget {\n  const TodoList({super.key});\n\n  @override\n  State\u003CTodoList> createState() => _TodoListState();\n}\n\nclass _TodoListState extends State\u003CTodoList> {\n  final todos = \u003CString>[];\n  final controller = TextEditingController();\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      home: Scaffold(\n        body: Column(\n          children: [\n            TextField(controller: controller),\n            Expanded(\n              child: ListView.builder(\n                itemCount: todos.length,\n                itemBuilder: (context, index) {\n                  final todo = todos[index];\n                  return Dismissible(\n                    key: Key('$todo$index'),\n                    onDismissed: (_) => setState(() => todos.removeAt(index)),\n                    child: ListTile(title: Text(todo)),\n                  );\n                },\n              ),\n            ),\n          ],\n        ),\n        floatingActionButton: FloatingActionButton(\n          onPressed: () {\n            setState(() {\n              todos.add(controller.text);\n              controller.clear();\n            });\n          },\n          child: const Icon(Icons.add),\n        ),\n      ),\n    );\n  }\n}\n```\n\n**Test Implementation (`test\u002Ftodo_list_test.dart`):**\n```dart\nimport 'package:flutter\u002Fmaterial.dart';\nimport 'package:flutter_test\u002Fflutter_test.dart';\nimport 'package:my_app\u002Ftodo_list.dart';\n\nvoid main() {\n  testWidgets('Add and remove a todo item', (WidgetTester tester) async {\n    \u002F\u002F 1. Build the widget\n    await tester.pumpWidget(const TodoList());\n\n    \u002F\u002F 2. Verify initial state\n    expect(find.byType(ListTile), findsNothing);\n\n    \u002F\u002F 3. Enter text into the TextField\n    await tester.enterText(find.byType(TextField), 'Buy groceries');\n\n    \u002F\u002F 4. Tap the add button\n    await tester.tap(find.byType(FloatingActionButton));\n\n    \u002F\u002F 5. Rebuild the widget to reflect the new state\n    await tester.pump();\n\n    \u002F\u002F 6. Verify the item was added\n    expect(find.text('Buy groceries'), findsOneWidget);\n\n    \u002F\u002F 7. Swipe the item to dismiss it\n    await tester.drag(find.byType(Dismissible), const Offset(500, 0));\n\n    \u002F\u002F 8. Build the widget until the dismiss animation ends\n    await tester.pumpAndSettle();\n\n    \u002F\u002F 9. Verify the item was removed\n    expect(find.text('Buy groceries'), findsNothing);\n  });\n}\n```\n",{"data":32,"body":36},{"name":4,"description":6,"metadata":33},{"model":34,"last_modified":35},"models\u002Fgemini-3.1-pro-preview","Tue, 21 Apr 2026 21:15:41 GMT",{"type":37,"children":38},"root",[39,48,55,106,111,117,185,190,202,312,317,322,329,554,559,564,692,697,703,719,1158,1173,1441],{"type":40,"tag":41,"props":42,"children":44},"element","h1",{"id":43},"writing-flutter-widget-tests",[45],{"type":46,"value":47},"text","Writing Flutter Widget Tests",{"type":40,"tag":49,"props":50,"children":52},"h2",{"id":51},"contents",[53],{"type":46,"value":54},"Contents",{"type":40,"tag":56,"props":57,"children":58},"ul",{},[59,70,79,88,97],{"type":40,"tag":60,"props":61,"children":62},"li",{},[63],{"type":40,"tag":64,"props":65,"children":67},"a",{"href":66},"#setup--configuration",[68],{"type":46,"value":69},"Setup & Configuration",{"type":40,"tag":60,"props":71,"children":72},{},[73],{"type":40,"tag":64,"props":74,"children":76},{"href":75},"#core-components",[77],{"type":46,"value":78},"Core Components",{"type":40,"tag":60,"props":80,"children":81},{},[82],{"type":40,"tag":64,"props":83,"children":85},{"href":84},"#workflow-implementing-a-widget-test",[86],{"type":46,"value":87},"Workflow: Implementing a Widget Test",{"type":40,"tag":60,"props":89,"children":90},{},[91],{"type":40,"tag":64,"props":92,"children":94},{"href":93},"#interaction--state-management",[95],{"type":46,"value":96},"Interaction & State Management",{"type":40,"tag":60,"props":98,"children":99},{},[100],{"type":40,"tag":64,"props":101,"children":103},{"href":102},"#examples",[104],{"type":46,"value":105},"Examples",{"type":40,"tag":49,"props":107,"children":109},{"id":108},"setup-configuration",[110],{"type":46,"value":69},{"type":40,"tag":112,"props":113,"children":114},"p",{},[115],{"type":46,"value":116},"Ensure the testing environment is properly configured before authoring widget tests.",{"type":40,"tag":118,"props":119,"children":120},"ol",{},[121,151,164],{"type":40,"tag":60,"props":122,"children":123},{},[124,126,133,135,141,143,149],{"type":46,"value":125},"Add the ",{"type":40,"tag":127,"props":128,"children":130},"code",{"className":129},[],[131],{"type":46,"value":132},"flutter_test",{"type":46,"value":134}," dependency to the ",{"type":40,"tag":127,"props":136,"children":138},{"className":137},[],[139],{"type":46,"value":140},"dev_dependencies",{"type":46,"value":142}," section of ",{"type":40,"tag":127,"props":144,"children":146},{"className":145},[],[147],{"type":46,"value":148},"pubspec.yaml",{"type":46,"value":150},".",{"type":40,"tag":60,"props":152,"children":153},{},[154,156,162],{"type":46,"value":155},"Place all test files in the ",{"type":40,"tag":127,"props":157,"children":159},{"className":158},[],[160],{"type":46,"value":161},"test\u002F",{"type":46,"value":163}," directory at the root of the project.",{"type":40,"tag":60,"props":165,"children":166},{},[167,169,175,177,183],{"type":46,"value":168},"Suffix all test file names with ",{"type":40,"tag":127,"props":170,"children":172},{"className":171},[],[173],{"type":46,"value":174},"_test.dart",{"type":46,"value":176}," (e.g., ",{"type":40,"tag":127,"props":178,"children":180},{"className":179},[],[181],{"type":46,"value":182},"widget_test.dart",{"type":46,"value":184},").",{"type":40,"tag":49,"props":186,"children":188},{"id":187},"core-components",[189],{"type":46,"value":78},{"type":40,"tag":112,"props":191,"children":192},{},[193,195,200],{"type":46,"value":194},"Utilize the following ",{"type":40,"tag":127,"props":196,"children":198},{"className":197},[],[199],{"type":46,"value":132},{"type":46,"value":201}," components to interact with and validate the widget tree:",{"type":40,"tag":56,"props":203,"children":204},{},[205,228,264],{"type":40,"tag":60,"props":206,"children":207},{},[208,218,220,226],{"type":40,"tag":209,"props":210,"children":211},"strong",{},[212],{"type":40,"tag":127,"props":213,"children":215},{"className":214},[],[216],{"type":46,"value":217},"WidgetTester",{"type":46,"value":219},": The primary interface for building and interacting with widgets in the test environment. Provided automatically by the ",{"type":40,"tag":127,"props":221,"children":223},{"className":222},[],[224],{"type":46,"value":225},"testWidgets()",{"type":46,"value":227}," function.",{"type":40,"tag":60,"props":229,"children":230},{},[231,240,242,248,250,256,257,263],{"type":40,"tag":209,"props":232,"children":233},{},[234],{"type":40,"tag":127,"props":235,"children":237},{"className":236},[],[238],{"type":46,"value":239},"Finder",{"type":46,"value":241},": Locates widgets in the test environment (e.g., ",{"type":40,"tag":127,"props":243,"children":245},{"className":244},[],[246],{"type":46,"value":247},"find.text('Submit')",{"type":46,"value":249},", ",{"type":40,"tag":127,"props":251,"children":253},{"className":252},[],[254],{"type":46,"value":255},"find.byType(TextField)",{"type":46,"value":249},{"type":40,"tag":127,"props":258,"children":260},{"className":259},[],[261],{"type":46,"value":262},"find.byKey(Key('submit_btn'))",{"type":46,"value":184},{"type":40,"tag":60,"props":265,"children":266},{},[267,276,278,283,284,290,291,297,298,304,305,311],{"type":40,"tag":209,"props":268,"children":269},{},[270],{"type":40,"tag":127,"props":271,"children":273},{"className":272},[],[274],{"type":46,"value":275},"Matcher",{"type":46,"value":277},": Verifies the presence or state of widgets located by a ",{"type":40,"tag":127,"props":279,"children":281},{"className":280},[],[282],{"type":46,"value":239},{"type":46,"value":176},{"type":40,"tag":127,"props":285,"children":287},{"className":286},[],[288],{"type":46,"value":289},"findsOneWidget",{"type":46,"value":249},{"type":40,"tag":127,"props":292,"children":294},{"className":293},[],[295],{"type":46,"value":296},"findsNothing",{"type":46,"value":249},{"type":40,"tag":127,"props":299,"children":301},{"className":300},[],[302],{"type":46,"value":303},"findsNWidgets(2)",{"type":46,"value":249},{"type":40,"tag":127,"props":306,"children":308},{"className":307},[],[309],{"type":46,"value":310},"matchesGoldenFile",{"type":46,"value":184},{"type":40,"tag":49,"props":313,"children":315},{"id":314},"workflow-implementing-a-widget-test",[316],{"type":46,"value":87},{"type":40,"tag":112,"props":318,"children":319},{},[320],{"type":46,"value":321},"Copy the following checklist to track progress when implementing a new widget test.",{"type":40,"tag":323,"props":324,"children":326},"h3",{"id":325},"task-progress",[327],{"type":46,"value":328},"Task Progress",{"type":40,"tag":56,"props":330,"children":333},{"className":331},[332],"contains-task-list",[334,361,400,422,444,466,495,517,539],{"type":40,"tag":60,"props":335,"children":338},{"className":336},[337],"task-list-item",[339,345,347,352,354,360],{"type":40,"tag":340,"props":341,"children":344},"input",{"disabled":342,"type":343},true,"checkbox",[],{"type":46,"value":346}," ",{"type":40,"tag":209,"props":348,"children":349},{},[350],{"type":46,"value":351},"Step 1: Define the test.",{"type":46,"value":353}," Use ",{"type":40,"tag":127,"props":355,"children":357},{"className":356},[],[358],{"type":46,"value":359},"testWidgets('description', (WidgetTester tester) async { ... })",{"type":46,"value":150},{"type":40,"tag":60,"props":362,"children":364},{"className":363},[337],[365,368,369,374,376,382,384,390,392,398],{"type":40,"tag":340,"props":366,"children":367},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":370,"children":371},{},[372],{"type":46,"value":373},"Step 2: Build the widget.",{"type":46,"value":375}," Call ",{"type":40,"tag":127,"props":377,"children":379},{"className":378},[],[380],{"type":46,"value":381},"await tester.pumpWidget(MyWidget())",{"type":46,"value":383}," to render the UI. Wrap the widget in a ",{"type":40,"tag":127,"props":385,"children":387},{"className":386},[],[388],{"type":46,"value":389},"MaterialApp",{"type":46,"value":391}," or ",{"type":40,"tag":127,"props":393,"children":395},{"className":394},[],[396],{"type":46,"value":397},"Directionality",{"type":46,"value":399}," widget if it requires inherited directional or theme data.",{"type":40,"tag":60,"props":401,"children":403},{"className":402},[337],[404,407,408,413,415,420],{"type":40,"tag":340,"props":405,"children":406},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":409,"children":410},{},[411],{"type":46,"value":412},"Step 3: Locate elements.",{"type":46,"value":414}," Instantiate ",{"type":40,"tag":127,"props":416,"children":418},{"className":417},[],[419],{"type":46,"value":239},{"type":46,"value":421}," objects for the target widgets.",{"type":40,"tag":60,"props":423,"children":425},{"className":424},[337],[426,429,430,435,436,442],{"type":40,"tag":340,"props":427,"children":428},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":431,"children":432},{},[433],{"type":46,"value":434},"Step 4: Verify initial state.",{"type":46,"value":353},{"type":40,"tag":127,"props":437,"children":439},{"className":438},[],[440],{"type":46,"value":441},"expect(finder, matcher)",{"type":46,"value":443}," to validate the initial render.",{"type":40,"tag":60,"props":445,"children":447},{"className":446},[337],[448,451,452,457,459,465],{"type":40,"tag":340,"props":449,"children":450},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":453,"children":454},{},[455],{"type":46,"value":456},"Step 5: Simulate interactions.",{"type":46,"value":458}," Execute gestures or inputs (e.g., ",{"type":40,"tag":127,"props":460,"children":462},{"className":461},[],[463],{"type":46,"value":464},"await tester.tap(buttonFinder)",{"type":46,"value":184},{"type":40,"tag":60,"props":467,"children":469},{"className":468},[337],[470,473,474,479,480,486,487,493],{"type":40,"tag":340,"props":471,"children":472},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":475,"children":476},{},[477],{"type":46,"value":478},"Step 6: Rebuild the tree.",{"type":46,"value":375},{"type":40,"tag":127,"props":481,"children":483},{"className":482},[],[484],{"type":46,"value":485},"await tester.pump()",{"type":46,"value":391},{"type":40,"tag":127,"props":488,"children":490},{"className":489},[],[491],{"type":46,"value":492},"await tester.pumpAndSettle()",{"type":46,"value":494}," to process state changes.",{"type":40,"tag":60,"props":496,"children":498},{"className":497},[337],[499,502,503,508,509,515],{"type":40,"tag":340,"props":500,"children":501},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":504,"children":505},{},[506],{"type":46,"value":507},"Step 7: Verify updated state.",{"type":46,"value":353},{"type":40,"tag":127,"props":510,"children":512},{"className":511},[],[513],{"type":46,"value":514},"expect()",{"type":46,"value":516}," to validate the UI after the interaction.",{"type":40,"tag":60,"props":518,"children":520},{"className":519},[337],[521,524,525,530,532,538],{"type":40,"tag":340,"props":522,"children":523},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":526,"children":527},{},[528],{"type":46,"value":529},"Step 8: Run and validate.",{"type":46,"value":531}," Execute ",{"type":40,"tag":127,"props":533,"children":535},{"className":534},[],[536],{"type":46,"value":537},"flutter test test\u002Fyour_test_file_test.dart",{"type":46,"value":150},{"type":40,"tag":60,"props":540,"children":542},{"className":541},[337],[543,546,547,552],{"type":40,"tag":340,"props":544,"children":545},{"disabled":342,"type":343},[],{"type":46,"value":346},{"type":40,"tag":209,"props":548,"children":549},{},[550],{"type":46,"value":551},"Step 9: Feedback Loop.",{"type":46,"value":553}," Review test output -> identify failing matchers -> adjust widget logic or test assertions -> re-run until passing.",{"type":40,"tag":49,"props":555,"children":557},{"id":556},"interaction-state-management",[558],{"type":46,"value":96},{"type":40,"tag":112,"props":560,"children":561},{},[562],{"type":46,"value":563},"Apply the following conditional logic based on the type of interaction or state change being tested:",{"type":40,"tag":56,"props":565,"children":566},{},[567,591,625,659,675],{"type":40,"tag":60,"props":568,"children":569},{},[570,575,576,582,584,589],{"type":40,"tag":209,"props":571,"children":572},{},[573],{"type":46,"value":574},"If testing static rendering:",{"type":46,"value":375},{"type":40,"tag":127,"props":577,"children":579},{"className":578},[],[580],{"type":46,"value":581},"await tester.pumpWidget()",{"type":46,"value":583}," once, then immediately run ",{"type":40,"tag":127,"props":585,"children":587},{"className":586},[],[588],{"type":46,"value":514},{"type":46,"value":590}," assertions.",{"type":40,"tag":60,"props":592,"children":593},{},[594,599],{"type":40,"tag":209,"props":595,"children":596},{},[597],{"type":46,"value":598},"If testing standard state changes (e.g., button taps):",{"type":40,"tag":118,"props":600,"children":601},{},[602,614],{"type":40,"tag":60,"props":603,"children":604},{},[605,607,613],{"type":46,"value":606},"Call ",{"type":40,"tag":127,"props":608,"children":610},{"className":609},[],[611],{"type":46,"value":612},"await tester.tap(finder)",{"type":46,"value":150},{"type":40,"tag":60,"props":615,"children":616},{},[617,618,623],{"type":46,"value":606},{"type":40,"tag":127,"props":619,"children":621},{"className":620},[],[622],{"type":46,"value":485},{"type":46,"value":624}," to trigger a single frame rebuild.",{"type":40,"tag":60,"props":626,"children":627},{},[628,633],{"type":40,"tag":209,"props":629,"children":630},{},[631],{"type":46,"value":632},"If testing animations, transitions, or asynchronous UI updates:",{"type":40,"tag":118,"props":634,"children":635},{},[636,648],{"type":40,"tag":60,"props":637,"children":638},{},[639,641,647],{"type":46,"value":640},"Trigger the action (e.g., ",{"type":40,"tag":127,"props":642,"children":644},{"className":643},[],[645],{"type":46,"value":646},"await tester.drag(finder, Offset(500, 0))",{"type":46,"value":184},{"type":40,"tag":60,"props":649,"children":650},{},[651,652,657],{"type":46,"value":606},{"type":40,"tag":127,"props":653,"children":655},{"className":654},[],[656],{"type":46,"value":492},{"type":46,"value":658}," to repeatedly pump frames until no more frames are scheduled (animation completes).",{"type":40,"tag":60,"props":660,"children":661},{},[662,667,668,674],{"type":40,"tag":209,"props":663,"children":664},{},[665],{"type":46,"value":666},"If testing text input:",{"type":46,"value":375},{"type":40,"tag":127,"props":669,"children":671},{"className":670},[],[672],{"type":46,"value":673},"await tester.enterText(textFieldFinder, 'Input string')",{"type":46,"value":150},{"type":40,"tag":60,"props":676,"children":677},{},[678,683,684,690],{"type":40,"tag":209,"props":679,"children":680},{},[681],{"type":46,"value":682},"If testing items in a dynamic or long list:",{"type":46,"value":375},{"type":40,"tag":127,"props":685,"children":687},{"className":686},[],[688],{"type":46,"value":689},"await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder)",{"type":46,"value":691}," to ensure the target widget is rendered before interacting with it.",{"type":40,"tag":49,"props":693,"children":695},{"id":694},"examples",[696],{"type":46,"value":105},{"type":40,"tag":323,"props":698,"children":700},{"id":699},"high-fidelity-widget-test-implementation",[701],{"type":46,"value":702},"High-Fidelity Widget Test Implementation",{"type":40,"tag":112,"props":704,"children":705},{},[706],{"type":40,"tag":209,"props":707,"children":708},{},[709,711,717],{"type":46,"value":710},"Target Widget (",{"type":40,"tag":127,"props":712,"children":714},{"className":713},[],[715],{"type":46,"value":716},"lib\u002Ftodo_list.dart",{"type":46,"value":718},"):",{"type":40,"tag":720,"props":721,"children":726},"pre",{"className":722,"code":723,"language":724,"meta":725,"style":725},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import 'package:flutter\u002Fmaterial.dart';\n\nclass TodoList extends StatefulWidget {\n  const TodoList({super.key});\n\n  @override\n  State\u003CTodoList> createState() => _TodoListState();\n}\n\nclass _TodoListState extends State\u003CTodoList> {\n  final todos = \u003CString>[];\n  final controller = TextEditingController();\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      home: Scaffold(\n        body: Column(\n          children: [\n            TextField(controller: controller),\n            Expanded(\n              child: ListView.builder(\n                itemCount: todos.length,\n                itemBuilder: (context, index) {\n                  final todo = todos[index];\n                  return Dismissible(\n                    key: Key('$todo$index'),\n                    onDismissed: (_) => setState(() => todos.removeAt(index)),\n                    child: ListTile(title: Text(todo)),\n                  );\n                },\n              ),\n            ),\n          ],\n        ),\n        floatingActionButton: FloatingActionButton(\n          onPressed: () {\n            setState(() {\n              todos.add(controller.text);\n              controller.clear();\n            });\n          },\n          child: const Icon(Icons.add),\n        ),\n      ),\n    );\n  }\n}\n","dart","",[727],{"type":40,"tag":127,"props":728,"children":729},{"__ignoreMap":725},[730,741,750,759,768,776,785,794,803,811,820,829,838,846,854,863,872,881,890,899,908,917,926,935,944,953,962,971,980,989,998,1007,1016,1025,1034,1043,1052,1061,1070,1079,1088,1097,1106,1115,1123,1132,1141,1150],{"type":40,"tag":731,"props":732,"children":735},"span",{"class":733,"line":734},"line",1,[736],{"type":40,"tag":731,"props":737,"children":738},{},[739],{"type":46,"value":740},"import 'package:flutter\u002Fmaterial.dart';\n",{"type":40,"tag":731,"props":742,"children":744},{"class":733,"line":743},2,[745],{"type":40,"tag":731,"props":746,"children":747},{"emptyLinePlaceholder":342},[748],{"type":46,"value":749},"\n",{"type":40,"tag":731,"props":751,"children":753},{"class":733,"line":752},3,[754],{"type":40,"tag":731,"props":755,"children":756},{},[757],{"type":46,"value":758},"class TodoList extends StatefulWidget {\n",{"type":40,"tag":731,"props":760,"children":762},{"class":733,"line":761},4,[763],{"type":40,"tag":731,"props":764,"children":765},{},[766],{"type":46,"value":767},"  const TodoList({super.key});\n",{"type":40,"tag":731,"props":769,"children":771},{"class":733,"line":770},5,[772],{"type":40,"tag":731,"props":773,"children":774},{"emptyLinePlaceholder":342},[775],{"type":46,"value":749},{"type":40,"tag":731,"props":777,"children":779},{"class":733,"line":778},6,[780],{"type":40,"tag":731,"props":781,"children":782},{},[783],{"type":46,"value":784},"  @override\n",{"type":40,"tag":731,"props":786,"children":788},{"class":733,"line":787},7,[789],{"type":40,"tag":731,"props":790,"children":791},{},[792],{"type":46,"value":793},"  State\u003CTodoList> createState() => _TodoListState();\n",{"type":40,"tag":731,"props":795,"children":797},{"class":733,"line":796},8,[798],{"type":40,"tag":731,"props":799,"children":800},{},[801],{"type":46,"value":802},"}\n",{"type":40,"tag":731,"props":804,"children":806},{"class":733,"line":805},9,[807],{"type":40,"tag":731,"props":808,"children":809},{"emptyLinePlaceholder":342},[810],{"type":46,"value":749},{"type":40,"tag":731,"props":812,"children":814},{"class":733,"line":813},10,[815],{"type":40,"tag":731,"props":816,"children":817},{},[818],{"type":46,"value":819},"class _TodoListState extends State\u003CTodoList> {\n",{"type":40,"tag":731,"props":821,"children":823},{"class":733,"line":822},11,[824],{"type":40,"tag":731,"props":825,"children":826},{},[827],{"type":46,"value":828},"  final todos = \u003CString>[];\n",{"type":40,"tag":731,"props":830,"children":832},{"class":733,"line":831},12,[833],{"type":40,"tag":731,"props":834,"children":835},{},[836],{"type":46,"value":837},"  final controller = TextEditingController();\n",{"type":40,"tag":731,"props":839,"children":841},{"class":733,"line":840},13,[842],{"type":40,"tag":731,"props":843,"children":844},{"emptyLinePlaceholder":342},[845],{"type":46,"value":749},{"type":40,"tag":731,"props":847,"children":849},{"class":733,"line":848},14,[850],{"type":40,"tag":731,"props":851,"children":852},{},[853],{"type":46,"value":784},{"type":40,"tag":731,"props":855,"children":857},{"class":733,"line":856},15,[858],{"type":40,"tag":731,"props":859,"children":860},{},[861],{"type":46,"value":862},"  Widget build(BuildContext context) {\n",{"type":40,"tag":731,"props":864,"children":866},{"class":733,"line":865},16,[867],{"type":40,"tag":731,"props":868,"children":869},{},[870],{"type":46,"value":871},"    return MaterialApp(\n",{"type":40,"tag":731,"props":873,"children":875},{"class":733,"line":874},17,[876],{"type":40,"tag":731,"props":877,"children":878},{},[879],{"type":46,"value":880},"      home: Scaffold(\n",{"type":40,"tag":731,"props":882,"children":884},{"class":733,"line":883},18,[885],{"type":40,"tag":731,"props":886,"children":887},{},[888],{"type":46,"value":889},"        body: Column(\n",{"type":40,"tag":731,"props":891,"children":893},{"class":733,"line":892},19,[894],{"type":40,"tag":731,"props":895,"children":896},{},[897],{"type":46,"value":898},"          children: [\n",{"type":40,"tag":731,"props":900,"children":902},{"class":733,"line":901},20,[903],{"type":40,"tag":731,"props":904,"children":905},{},[906],{"type":46,"value":907},"            TextField(controller: controller),\n",{"type":40,"tag":731,"props":909,"children":911},{"class":733,"line":910},21,[912],{"type":40,"tag":731,"props":913,"children":914},{},[915],{"type":46,"value":916},"            Expanded(\n",{"type":40,"tag":731,"props":918,"children":920},{"class":733,"line":919},22,[921],{"type":40,"tag":731,"props":922,"children":923},{},[924],{"type":46,"value":925},"              child: ListView.builder(\n",{"type":40,"tag":731,"props":927,"children":929},{"class":733,"line":928},23,[930],{"type":40,"tag":731,"props":931,"children":932},{},[933],{"type":46,"value":934},"                itemCount: todos.length,\n",{"type":40,"tag":731,"props":936,"children":938},{"class":733,"line":937},24,[939],{"type":40,"tag":731,"props":940,"children":941},{},[942],{"type":46,"value":943},"                itemBuilder: (context, index) {\n",{"type":40,"tag":731,"props":945,"children":947},{"class":733,"line":946},25,[948],{"type":40,"tag":731,"props":949,"children":950},{},[951],{"type":46,"value":952},"                  final todo = todos[index];\n",{"type":40,"tag":731,"props":954,"children":956},{"class":733,"line":955},26,[957],{"type":40,"tag":731,"props":958,"children":959},{},[960],{"type":46,"value":961},"                  return Dismissible(\n",{"type":40,"tag":731,"props":963,"children":965},{"class":733,"line":964},27,[966],{"type":40,"tag":731,"props":967,"children":968},{},[969],{"type":46,"value":970},"                    key: Key('$todo$index'),\n",{"type":40,"tag":731,"props":972,"children":974},{"class":733,"line":973},28,[975],{"type":40,"tag":731,"props":976,"children":977},{},[978],{"type":46,"value":979},"                    onDismissed: (_) => setState(() => todos.removeAt(index)),\n",{"type":40,"tag":731,"props":981,"children":983},{"class":733,"line":982},29,[984],{"type":40,"tag":731,"props":985,"children":986},{},[987],{"type":46,"value":988},"                    child: ListTile(title: Text(todo)),\n",{"type":40,"tag":731,"props":990,"children":992},{"class":733,"line":991},30,[993],{"type":40,"tag":731,"props":994,"children":995},{},[996],{"type":46,"value":997},"                  );\n",{"type":40,"tag":731,"props":999,"children":1001},{"class":733,"line":1000},31,[1002],{"type":40,"tag":731,"props":1003,"children":1004},{},[1005],{"type":46,"value":1006},"                },\n",{"type":40,"tag":731,"props":1008,"children":1010},{"class":733,"line":1009},32,[1011],{"type":40,"tag":731,"props":1012,"children":1013},{},[1014],{"type":46,"value":1015},"              ),\n",{"type":40,"tag":731,"props":1017,"children":1019},{"class":733,"line":1018},33,[1020],{"type":40,"tag":731,"props":1021,"children":1022},{},[1023],{"type":46,"value":1024},"            ),\n",{"type":40,"tag":731,"props":1026,"children":1028},{"class":733,"line":1027},34,[1029],{"type":40,"tag":731,"props":1030,"children":1031},{},[1032],{"type":46,"value":1033},"          ],\n",{"type":40,"tag":731,"props":1035,"children":1037},{"class":733,"line":1036},35,[1038],{"type":40,"tag":731,"props":1039,"children":1040},{},[1041],{"type":46,"value":1042},"        ),\n",{"type":40,"tag":731,"props":1044,"children":1046},{"class":733,"line":1045},36,[1047],{"type":40,"tag":731,"props":1048,"children":1049},{},[1050],{"type":46,"value":1051},"        floatingActionButton: FloatingActionButton(\n",{"type":40,"tag":731,"props":1053,"children":1055},{"class":733,"line":1054},37,[1056],{"type":40,"tag":731,"props":1057,"children":1058},{},[1059],{"type":46,"value":1060},"          onPressed: () {\n",{"type":40,"tag":731,"props":1062,"children":1064},{"class":733,"line":1063},38,[1065],{"type":40,"tag":731,"props":1066,"children":1067},{},[1068],{"type":46,"value":1069},"            setState(() {\n",{"type":40,"tag":731,"props":1071,"children":1073},{"class":733,"line":1072},39,[1074],{"type":40,"tag":731,"props":1075,"children":1076},{},[1077],{"type":46,"value":1078},"              todos.add(controller.text);\n",{"type":40,"tag":731,"props":1080,"children":1082},{"class":733,"line":1081},40,[1083],{"type":40,"tag":731,"props":1084,"children":1085},{},[1086],{"type":46,"value":1087},"              controller.clear();\n",{"type":40,"tag":731,"props":1089,"children":1091},{"class":733,"line":1090},41,[1092],{"type":40,"tag":731,"props":1093,"children":1094},{},[1095],{"type":46,"value":1096},"            });\n",{"type":40,"tag":731,"props":1098,"children":1100},{"class":733,"line":1099},42,[1101],{"type":40,"tag":731,"props":1102,"children":1103},{},[1104],{"type":46,"value":1105},"          },\n",{"type":40,"tag":731,"props":1107,"children":1109},{"class":733,"line":1108},43,[1110],{"type":40,"tag":731,"props":1111,"children":1112},{},[1113],{"type":46,"value":1114},"          child: const Icon(Icons.add),\n",{"type":40,"tag":731,"props":1116,"children":1118},{"class":733,"line":1117},44,[1119],{"type":40,"tag":731,"props":1120,"children":1121},{},[1122],{"type":46,"value":1042},{"type":40,"tag":731,"props":1124,"children":1126},{"class":733,"line":1125},45,[1127],{"type":40,"tag":731,"props":1128,"children":1129},{},[1130],{"type":46,"value":1131},"      ),\n",{"type":40,"tag":731,"props":1133,"children":1135},{"class":733,"line":1134},46,[1136],{"type":40,"tag":731,"props":1137,"children":1138},{},[1139],{"type":46,"value":1140},"    );\n",{"type":40,"tag":731,"props":1142,"children":1144},{"class":733,"line":1143},47,[1145],{"type":40,"tag":731,"props":1146,"children":1147},{},[1148],{"type":46,"value":1149},"  }\n",{"type":40,"tag":731,"props":1151,"children":1153},{"class":733,"line":1152},48,[1154],{"type":40,"tag":731,"props":1155,"children":1156},{},[1157],{"type":46,"value":802},{"type":40,"tag":112,"props":1159,"children":1160},{},[1161],{"type":40,"tag":209,"props":1162,"children":1163},{},[1164,1166,1172],{"type":46,"value":1165},"Test Implementation (",{"type":40,"tag":127,"props":1167,"children":1169},{"className":1168},[],[1170],{"type":46,"value":1171},"test\u002Ftodo_list_test.dart",{"type":46,"value":718},{"type":40,"tag":720,"props":1174,"children":1176},{"className":722,"code":1175,"language":724,"meta":725,"style":725},"import 'package:flutter\u002Fmaterial.dart';\nimport 'package:flutter_test\u002Fflutter_test.dart';\nimport 'package:my_app\u002Ftodo_list.dart';\n\nvoid main() {\n  testWidgets('Add and remove a todo item', (WidgetTester tester) async {\n    \u002F\u002F 1. Build the widget\n    await tester.pumpWidget(const TodoList());\n\n    \u002F\u002F 2. Verify initial state\n    expect(find.byType(ListTile), findsNothing);\n\n    \u002F\u002F 3. Enter text into the TextField\n    await tester.enterText(find.byType(TextField), 'Buy groceries');\n\n    \u002F\u002F 4. Tap the add button\n    await tester.tap(find.byType(FloatingActionButton));\n\n    \u002F\u002F 5. Rebuild the widget to reflect the new state\n    await tester.pump();\n\n    \u002F\u002F 6. Verify the item was added\n    expect(find.text('Buy groceries'), findsOneWidget);\n\n    \u002F\u002F 7. Swipe the item to dismiss it\n    await tester.drag(find.byType(Dismissible), const Offset(500, 0));\n\n    \u002F\u002F 8. Build the widget until the dismiss animation ends\n    await tester.pumpAndSettle();\n\n    \u002F\u002F 9. Verify the item was removed\n    expect(find.text('Buy groceries'), findsNothing);\n  });\n}\n",[1177],{"type":40,"tag":127,"props":1178,"children":1179},{"__ignoreMap":725},[1180,1187,1195,1203,1210,1218,1226,1234,1242,1249,1257,1265,1272,1280,1288,1295,1303,1311,1318,1326,1334,1341,1349,1357,1364,1372,1380,1387,1395,1403,1410,1418,1426,1434],{"type":40,"tag":731,"props":1181,"children":1182},{"class":733,"line":734},[1183],{"type":40,"tag":731,"props":1184,"children":1185},{},[1186],{"type":46,"value":740},{"type":40,"tag":731,"props":1188,"children":1189},{"class":733,"line":743},[1190],{"type":40,"tag":731,"props":1191,"children":1192},{},[1193],{"type":46,"value":1194},"import 'package:flutter_test\u002Fflutter_test.dart';\n",{"type":40,"tag":731,"props":1196,"children":1197},{"class":733,"line":752},[1198],{"type":40,"tag":731,"props":1199,"children":1200},{},[1201],{"type":46,"value":1202},"import 'package:my_app\u002Ftodo_list.dart';\n",{"type":40,"tag":731,"props":1204,"children":1205},{"class":733,"line":761},[1206],{"type":40,"tag":731,"props":1207,"children":1208},{"emptyLinePlaceholder":342},[1209],{"type":46,"value":749},{"type":40,"tag":731,"props":1211,"children":1212},{"class":733,"line":770},[1213],{"type":40,"tag":731,"props":1214,"children":1215},{},[1216],{"type":46,"value":1217},"void main() {\n",{"type":40,"tag":731,"props":1219,"children":1220},{"class":733,"line":778},[1221],{"type":40,"tag":731,"props":1222,"children":1223},{},[1224],{"type":46,"value":1225},"  testWidgets('Add and remove a todo item', (WidgetTester tester) async {\n",{"type":40,"tag":731,"props":1227,"children":1228},{"class":733,"line":787},[1229],{"type":40,"tag":731,"props":1230,"children":1231},{},[1232],{"type":46,"value":1233},"    \u002F\u002F 1. Build the widget\n",{"type":40,"tag":731,"props":1235,"children":1236},{"class":733,"line":796},[1237],{"type":40,"tag":731,"props":1238,"children":1239},{},[1240],{"type":46,"value":1241},"    await tester.pumpWidget(const TodoList());\n",{"type":40,"tag":731,"props":1243,"children":1244},{"class":733,"line":805},[1245],{"type":40,"tag":731,"props":1246,"children":1247},{"emptyLinePlaceholder":342},[1248],{"type":46,"value":749},{"type":40,"tag":731,"props":1250,"children":1251},{"class":733,"line":813},[1252],{"type":40,"tag":731,"props":1253,"children":1254},{},[1255],{"type":46,"value":1256},"    \u002F\u002F 2. Verify initial state\n",{"type":40,"tag":731,"props":1258,"children":1259},{"class":733,"line":822},[1260],{"type":40,"tag":731,"props":1261,"children":1262},{},[1263],{"type":46,"value":1264},"    expect(find.byType(ListTile), findsNothing);\n",{"type":40,"tag":731,"props":1266,"children":1267},{"class":733,"line":831},[1268],{"type":40,"tag":731,"props":1269,"children":1270},{"emptyLinePlaceholder":342},[1271],{"type":46,"value":749},{"type":40,"tag":731,"props":1273,"children":1274},{"class":733,"line":840},[1275],{"type":40,"tag":731,"props":1276,"children":1277},{},[1278],{"type":46,"value":1279},"    \u002F\u002F 3. Enter text into the TextField\n",{"type":40,"tag":731,"props":1281,"children":1282},{"class":733,"line":848},[1283],{"type":40,"tag":731,"props":1284,"children":1285},{},[1286],{"type":46,"value":1287},"    await tester.enterText(find.byType(TextField), 'Buy groceries');\n",{"type":40,"tag":731,"props":1289,"children":1290},{"class":733,"line":856},[1291],{"type":40,"tag":731,"props":1292,"children":1293},{"emptyLinePlaceholder":342},[1294],{"type":46,"value":749},{"type":40,"tag":731,"props":1296,"children":1297},{"class":733,"line":865},[1298],{"type":40,"tag":731,"props":1299,"children":1300},{},[1301],{"type":46,"value":1302},"    \u002F\u002F 4. Tap the add button\n",{"type":40,"tag":731,"props":1304,"children":1305},{"class":733,"line":874},[1306],{"type":40,"tag":731,"props":1307,"children":1308},{},[1309],{"type":46,"value":1310},"    await tester.tap(find.byType(FloatingActionButton));\n",{"type":40,"tag":731,"props":1312,"children":1313},{"class":733,"line":883},[1314],{"type":40,"tag":731,"props":1315,"children":1316},{"emptyLinePlaceholder":342},[1317],{"type":46,"value":749},{"type":40,"tag":731,"props":1319,"children":1320},{"class":733,"line":892},[1321],{"type":40,"tag":731,"props":1322,"children":1323},{},[1324],{"type":46,"value":1325},"    \u002F\u002F 5. Rebuild the widget to reflect the new state\n",{"type":40,"tag":731,"props":1327,"children":1328},{"class":733,"line":901},[1329],{"type":40,"tag":731,"props":1330,"children":1331},{},[1332],{"type":46,"value":1333},"    await tester.pump();\n",{"type":40,"tag":731,"props":1335,"children":1336},{"class":733,"line":910},[1337],{"type":40,"tag":731,"props":1338,"children":1339},{"emptyLinePlaceholder":342},[1340],{"type":46,"value":749},{"type":40,"tag":731,"props":1342,"children":1343},{"class":733,"line":919},[1344],{"type":40,"tag":731,"props":1345,"children":1346},{},[1347],{"type":46,"value":1348},"    \u002F\u002F 6. Verify the item was added\n",{"type":40,"tag":731,"props":1350,"children":1351},{"class":733,"line":928},[1352],{"type":40,"tag":731,"props":1353,"children":1354},{},[1355],{"type":46,"value":1356},"    expect(find.text('Buy groceries'), findsOneWidget);\n",{"type":40,"tag":731,"props":1358,"children":1359},{"class":733,"line":937},[1360],{"type":40,"tag":731,"props":1361,"children":1362},{"emptyLinePlaceholder":342},[1363],{"type":46,"value":749},{"type":40,"tag":731,"props":1365,"children":1366},{"class":733,"line":946},[1367],{"type":40,"tag":731,"props":1368,"children":1369},{},[1370],{"type":46,"value":1371},"    \u002F\u002F 7. Swipe the item to dismiss it\n",{"type":40,"tag":731,"props":1373,"children":1374},{"class":733,"line":955},[1375],{"type":40,"tag":731,"props":1376,"children":1377},{},[1378],{"type":46,"value":1379},"    await tester.drag(find.byType(Dismissible), const Offset(500, 0));\n",{"type":40,"tag":731,"props":1381,"children":1382},{"class":733,"line":964},[1383],{"type":40,"tag":731,"props":1384,"children":1385},{"emptyLinePlaceholder":342},[1386],{"type":46,"value":749},{"type":40,"tag":731,"props":1388,"children":1389},{"class":733,"line":973},[1390],{"type":40,"tag":731,"props":1391,"children":1392},{},[1393],{"type":46,"value":1394},"    \u002F\u002F 8. Build the widget until the dismiss animation ends\n",{"type":40,"tag":731,"props":1396,"children":1397},{"class":733,"line":982},[1398],{"type":40,"tag":731,"props":1399,"children":1400},{},[1401],{"type":46,"value":1402},"    await tester.pumpAndSettle();\n",{"type":40,"tag":731,"props":1404,"children":1405},{"class":733,"line":991},[1406],{"type":40,"tag":731,"props":1407,"children":1408},{"emptyLinePlaceholder":342},[1409],{"type":46,"value":749},{"type":40,"tag":731,"props":1411,"children":1412},{"class":733,"line":1000},[1413],{"type":40,"tag":731,"props":1414,"children":1415},{},[1416],{"type":46,"value":1417},"    \u002F\u002F 9. Verify the item was removed\n",{"type":40,"tag":731,"props":1419,"children":1420},{"class":733,"line":1009},[1421],{"type":40,"tag":731,"props":1422,"children":1423},{},[1424],{"type":46,"value":1425},"    expect(find.text('Buy groceries'), findsNothing);\n",{"type":40,"tag":731,"props":1427,"children":1428},{"class":733,"line":1018},[1429],{"type":40,"tag":731,"props":1430,"children":1431},{},[1432],{"type":46,"value":1433},"  });\n",{"type":40,"tag":731,"props":1435,"children":1436},{"class":733,"line":1027},[1437],{"type":40,"tag":731,"props":1438,"children":1439},{},[1440],{"type":46,"value":802},{"type":40,"tag":1442,"props":1443,"children":1444},"style",{},[1445],{"type":46,"value":1446},"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":1448,"total":937},[1449,1459,1470,1482,1493,1502,1514],{"slug":1450,"name":1450,"fn":1451,"description":1452,"org":1453,"tags":1454,"stars":21,"repoUrl":22,"updatedAt":1458},"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},[1455,1457],{"name":1456,"slug":724,"type":14},"Dart",{"name":19,"slug":20,"type":14},"2026-07-15T05:22:40.104823",{"slug":1460,"name":1460,"fn":1461,"description":1462,"org":1463,"tags":1464,"stars":21,"repoUrl":22,"updatedAt":1469},"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},[1465,1468],{"name":1466,"slug":1467,"type":14},"CLI","cli",{"name":1456,"slug":724,"type":14},"2026-07-15T05:22:18.863572",{"slug":1471,"name":1471,"fn":1472,"description":1473,"org":1474,"tags":1475,"stars":21,"repoUrl":22,"updatedAt":1481},"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},[1476,1477,1480],{"name":1456,"slug":724,"type":14},{"name":1478,"slug":1479,"type":14},"Reporting","reporting",{"name":19,"slug":20,"type":14},"2026-07-15T05:22:21.38636",{"slug":1483,"name":1483,"fn":1484,"description":1485,"org":1486,"tags":1487,"stars":21,"repoUrl":22,"updatedAt":1492},"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},[1488,1489],{"name":1456,"slug":724,"type":14},{"name":1490,"slug":1491,"type":14},"Debugging","debugging","2026-07-15T05:22:22.622501",{"slug":1494,"name":1494,"fn":1495,"description":1496,"org":1497,"tags":1498,"stars":21,"repoUrl":22,"updatedAt":1501},"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},[1499,1500],{"name":1456,"slug":724,"type":14},{"name":19,"slug":20,"type":14},"2026-07-15T05:22:42.607449",{"slug":1503,"name":1503,"fn":1504,"description":1505,"org":1506,"tags":1507,"stars":21,"repoUrl":22,"updatedAt":1513},"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},[1508,1509,1512],{"name":1456,"slug":724,"type":14},{"name":1510,"slug":1511,"type":14},"Migration","migration",{"name":19,"slug":20,"type":14},"2026-07-15T05:22:31.276564",{"slug":1515,"name":1515,"fn":1516,"description":1517,"org":1518,"tags":1519,"stars":21,"repoUrl":22,"updatedAt":1525},"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},[1520,1521,1522],{"name":1456,"slug":724,"type":14},{"name":1490,"slug":1491,"type":14},{"name":1523,"slug":1524,"type":14},"Engineering","engineering","2026-07-15T05:22:30.059335",{"items":1527,"total":964},[1528,1533,1538,1544,1549,1554,1560,1566,1578,1590,1604,1614],{"slug":1450,"name":1450,"fn":1451,"description":1452,"org":1529,"tags":1530,"stars":21,"repoUrl":22,"updatedAt":1458},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1531,1532],{"name":1456,"slug":724,"type":14},{"name":19,"slug":20,"type":14},{"slug":1460,"name":1460,"fn":1461,"description":1462,"org":1534,"tags":1535,"stars":21,"repoUrl":22,"updatedAt":1469},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1536,1537],{"name":1466,"slug":1467,"type":14},{"name":1456,"slug":724,"type":14},{"slug":1471,"name":1471,"fn":1472,"description":1473,"org":1539,"tags":1540,"stars":21,"repoUrl":22,"updatedAt":1481},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1541,1542,1543],{"name":1456,"slug":724,"type":14},{"name":1478,"slug":1479,"type":14},{"name":19,"slug":20,"type":14},{"slug":1483,"name":1483,"fn":1484,"description":1485,"org":1545,"tags":1546,"stars":21,"repoUrl":22,"updatedAt":1492},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1547,1548],{"name":1456,"slug":724,"type":14},{"name":1490,"slug":1491,"type":14},{"slug":1494,"name":1494,"fn":1495,"description":1496,"org":1550,"tags":1551,"stars":21,"repoUrl":22,"updatedAt":1501},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1552,1553],{"name":1456,"slug":724,"type":14},{"name":19,"slug":20,"type":14},{"slug":1503,"name":1503,"fn":1504,"description":1505,"org":1555,"tags":1556,"stars":21,"repoUrl":22,"updatedAt":1513},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1557,1558,1559],{"name":1456,"slug":724,"type":14},{"name":1510,"slug":1511,"type":14},{"name":19,"slug":20,"type":14},{"slug":1515,"name":1515,"fn":1516,"description":1517,"org":1561,"tags":1562,"stars":21,"repoUrl":22,"updatedAt":1525},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1563,1564,1565],{"name":1456,"slug":724,"type":14},{"name":1490,"slug":1491,"type":14},{"name":1523,"slug":1524,"type":14},{"slug":1567,"name":1567,"fn":1568,"description":1569,"org":1570,"tags":1571,"stars":21,"repoUrl":22,"updatedAt":1577},"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},[1572,1575,1576],{"name":1573,"slug":1574,"type":14},"Code Analysis","code-analysis",{"name":1456,"slug":724,"type":14},{"name":1490,"slug":1491,"type":14},"2026-07-15T05:22:23.861119",{"slug":1579,"name":1579,"fn":1580,"description":1581,"org":1582,"tags":1583,"stars":21,"repoUrl":22,"updatedAt":1589},"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},[1584,1585,1588],{"name":1456,"slug":724,"type":14},{"name":1586,"slug":1587,"type":14},"Deployment","deployment",{"name":1523,"slug":1524,"type":14},"2026-07-15T05:22:20.138636",{"slug":1591,"name":1591,"fn":1592,"description":1593,"org":1594,"tags":1595,"stars":21,"repoUrl":22,"updatedAt":1603},"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},[1596,1597,1600],{"name":1456,"slug":724,"type":14},{"name":1598,"slug":1599,"type":14},"Plugin Development","plugin-development",{"name":1601,"slug":1602,"type":14},"QA","qa","2026-07-15T05:22:47.488998",{"slug":1605,"name":1605,"fn":1606,"description":1607,"org":1608,"tags":1609,"stars":21,"repoUrl":22,"updatedAt":1613},"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},[1610,1611,1612],{"name":1456,"slug":724,"type":14},{"name":1598,"slug":1599,"type":14},{"name":1601,"slug":1602,"type":14},"2026-07-21T05:38:34.451024",{"slug":1615,"name":1615,"fn":1616,"description":1617,"org":1618,"tags":1619,"stars":21,"repoUrl":22,"updatedAt":1622},"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},[1620,1621],{"name":1456,"slug":724,"type":14},{"name":1523,"slug":1524,"type":14},"2026-07-15T05:22:17.592351"]