hasProp<T> method

WidgetMatcher<W> hasProp<T>({
  1. Subject<T> elementSelector(
    1. Subject<Element>
    )?,
  2. Subject<T> widgetSelector(
    1. Subject<W>
    )?,
  3. required MatchProp<T> match,
})

Allows checking for properties of Element that are stored in child Widgets or in the state. Use selector to extract the actual value and validate it with match.

Example usage:

hasProp(
  selector: (subject) => subject.context.nest<int?>(
    () => ['has "maxLines"'],
    (Element element) => Extracted.value(_extractMaxLines(element)),
  ),
  match: (maxLines) => maxLines.equals(1),
);

int? _extractMaxLines(Element element) {
  element.requireWidgetType<Text>();
  // every Text widget has a RichText child where the effective maxLines are set
  final richTextElement =
      element.children.firstWhere((e) => e.widget is RichText);
  final richText = richTextElement.widget as RichText;
  return richText.maxLines;
}

Implementation

WidgetMatcher<W> hasProp<T>({
  Subject<T> Function(Subject<Element>)? elementSelector,
  Subject<T> Function(Subject<W>)? widgetSelector,
  required MatchProp<T> match,
}) {
  if (elementSelector == null && widgetSelector == null) {
    throw ArgumentError(
      'Either elementSelector (former selector) or widgetSelector must be set',
    );
  }
  void widgetSelectorCondition(Subject<Element> subject) {
    final Subject<W> widgetSubject = subject.context.nest<W>(
      () => ['widget $W'],
      (element) {
        final widget = selector.mapElementToWidget(element);
        return Extracted.value(widget);
      },
    );
    final value = widgetSelector!(widgetSubject);
    match(value);
  }

  void elementSelectorCondition(Subject<Element> subject) {
    final value = elementSelector!(subject);
    match(value);
  }

  final void Function(Subject<Element>) condition = elementSelector != null
      ? elementSelectorCondition
      : widgetSelectorCondition;

  final failure = softCheckHideNull(element, condition);
  failure.throwPropertyCheckFailure(condition, element);
  return this;
}