Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request: check whether text and icons are consistent in CI tests #31

Open
1 task done
Giuspepe opened this issue Mar 11, 2022 · 1 comment
Open
1 task done

Comments

@Giuspepe
Copy link
Contributor

Is there an existing feature request for this?

  • I have searched the existing issues.

Command

I would love if CI tests would check texts and icons.

Description

It would be great if changing icons or texts would be caught by golden tests. I understand that currently text is not rendered as text to make CI tests stable between platforms, but maybe there is another solution to get the best of both worlds.

Take the following test file as an example. Note that both tests use the same file as golden image reference. The second golden test should fail because it contains a different icon than the first test, but the CI test passes because the icon (which is text as well) is rendered as a black box on both tests.

void main() {
  AlchemistConfig.runWithConfig(
    config: AlchemistConfig.current().merge(
      const AlchemistConfig(
        ciGoldensConfig: CiGoldensConfig(enabled: true),
        platformGoldensConfig: PlatformGoldensConfig(enabled: false),
      ),
    ),
    run: () {
      goldenTest(
        'should pass and passes',
        fileName: 'icon_test',
        builder: () => GoldenTestScenario(
          name: 'icon A',
          child: const Icon(Icons.thumb_up),
        ),
      );

      goldenTest(
        'should fail, but passes too!',
        // use same golden image as the previous test
        fileName: 'icon_test',
        builder: () => GoldenTestScenario(
          name: 'icon B',
          // but use a different icon
          child: const Icon(Icons.bug_report),
        ),
      );
    },
  );
}

Reasoning

This feature would make golden tests even more powerful by preventing more types of regressions.

Additional context and comments

My suggestion is the following:

During the replacement of text blocks with colored rectangles, write all blocked text blocks into a Map<Offset, List<String>> textBlocks. At the end of a test, compare not only the golden image file but also the map containing the text blocks.

Add something like textBlocks.putIfAbsent(offset, () => []).add(child.text.toPlainText()); to the if(child is RenderParagraph) block. Or maybe child.text.toStringDeep() would be better because that also contains information on font family, color, etc.

void paintChild(RenderObject child, Offset offset) {
if (child is RenderParagraph) {
final paint = Paint()
..color = child.text.style?.color ?? const Color(0xFF000000);
canvas.drawRect(offset & child.size, paint);
} else {

If a test is being run with --update-goldens or forceUpdateGoldens: true, save the Map<Offset, List> under goldens/ci/<golden_test_file_name>.texts. Else compare the current textBlocks map with the persisted golden textBlocks map.

The map should be a Map<Offset, List<String>> and not a Map<Offset, String> because multiple texts can be drawn at the same offset. Another advantage of List is that it also keeps track of the correct painting order.

@jolexxa
Copy link
Collaborator

jolexxa commented Mar 14, 2022

Very cool idea! I think we can consider a PR, assuming @Kirpal and @jeroen-meijer don't have any big reasons against.

I'm not sure how this approach will pan out without doing it myself, but I might suggest starting by injecting a new service into BlockedTextPaintingContext during construction here:

class BlockedTextPaintingContext extends PaintingContext {
/// {@macro blocked_text_painting_context}
BlockedTextPaintingContext({
required ContainerLayer containerLayer,
required Rect estimatedBounds,
}) : super(containerLayer, estimatedBounds);

and here:

paintingContextBuilder(
layer,
renderObject.paintBounds,
).paintSingleChild(renderObject);

This service, which would be responsible for the text/icons, can use the goldenTestAdapter to interface directly with flutter_test. It can also interface with the file package for any filesystem operations you might need, since it is friendly to testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants