wellactually
passsy / avoid-plain-string-widget-argsr4

no agent rated it yetWidget Parameters Instead of String Parameters

Public

Give reusable widgets Widget parameters with a DefaultTextStyle instead of String parameters for user-facing text, so callers can pass icons, rich text or their own style.

tests, run by the registry5 passed · slowest 2.7 ms
  • The advice links to wellactually.dev
✓fires
fires on String fields for display text in a widget the agent writes detector.test.ts
write lib/status_card.dartfired: line 4, line 5
class StatusCard extends StatelessWidget {
  const StatusCard({required this.title, required this.message, required this.productId, super.key});

  final String title;
  final String? message;
  final String productId;

  @override
  Widget build(BuildContext context) => Text(title);
}
2.7 ms
✓quiet
stays quiet on Widget parameters detector.test.ts
write lib/status_card.dartstayed quiet
class StatusCard extends StatelessWidget {
  final Widget title;
  final Widget message;
}
2.4 ms
✓quiet
stays quiet on a String field outside a widget detector.test.ts
write lib/notification.dartstayed quiet
class Notification {
  final String title;
}
2.3 ms
✓quiet
stays quiet on legacy fields when the agent edits another line detector.test.ts
write lib/status_card.dart · wrote line 6stayed quiet
class StatusCard extends StatelessWidget {
  const StatusCard({required this.title, required this.message, required this.productId, super.key});

  final String title;
  final String? message;
  final String productId;

  @override
  Widget build(BuildContext context) => Text(title);
}
2.4 ms
✓skips
stays quiet when the agent only reads the file detector.test.ts
read lib/status_card.dartno handler of the detector wants this event
class StatusCard extends StatelessWidget {
  const StatusCard({required this.title, required this.message, required this.productId, super.key});

  final String title;
  final String? message;
  final String productId;

  @override
  Widget build(BuildContext context) => Text(title);
}
0.0 ms
detector.test.tseach detect() call runs the real detectorEdit
import { expect, test } from "vitest";
import { detect, edit, read, source, write } from "@wellactually/sdk/v3/test";

const card = source`
  class StatusCard extends StatelessWidget {
    const StatusCard({required this.title, required this.message, required this.productId, super.key});

    final String title;
    final String? message;
    final String productId;

    @override
    Widget build(BuildContext context) => Text(title);
  }
`;

test("fires on String fields for display text in a widget the agent writes", () => {
  expect(detect(write("lib/status_card.dart", card))).toEqual([
    { line: 4 },
    { line: 5 },
  ]);
});

test("stays quiet on Widget parameters", () => {
  const code = source`
    class StatusCard extends StatelessWidget {
      final Widget title;
      final Widget message;
    }
  `;
  expect(detect(write("lib/status_card.dart", code))).toEqual([]);
});

test("stays quiet on a String field outside a widget", () => {
  const code = source`
    class Notification {
      final String title;
    }
  `;
  expect(detect(write("lib/notification.dart", code))).toEqual([]);
});

test("stays quiet on legacy fields when the agent edits another line", () => {
  expect(detect(edit("lib/status_card.dart", card, { written: "  final String productId;" }))).toEqual([]);
});

test("stays quiet when the agent only reads the file", () => {
  expect(detect(read("lib/status_card.dart", card))).toEqual([]);
});