opacity_test.dart 6.54 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7
// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
8
library;
9

10
import 'package:flutter/material.dart';
11
import 'package:flutter/rendering.dart';
12
import 'package:flutter_test/flutter_test.dart';
13 14 15 16 17 18

import '../rendering/mock_canvas.dart';
import 'semantics_tester.dart';

void main() {
  testWidgets('Opacity', (WidgetTester tester) async {
19
    final SemanticsTester semantics = SemanticsTester(tester);
20 21 22 23 24

    // Opacity 1.0: Semantics and painting
    await tester.pumpWidget(
      const Opacity(
        opacity: 1.0,
25
        child: Text('a', textDirection: TextDirection.rtl),
26 27 28
      ),
    );
    expect(semantics, hasSemantics(
29
      TestSemantics.root(
30
        children: <TestSemantics>[
31
          TestSemantics.rootChild(
32
            id: 1,
Dan Field's avatar
Dan Field committed
33
            rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
34 35
            label: 'a',
            textDirection: TextDirection.rtl,
36
          ),
37 38 39 40 41 42 43 44 45
        ],
      ),
    ));
    expect(find.byType(Opacity), paints..paragraph());

    // Opacity 0.0: Nothing
    await tester.pumpWidget(
      const Opacity(
        opacity: 0.0,
46
        child: Text('a', textDirection: TextDirection.rtl),
47 48 49
      ),
    );
    expect(semantics, hasSemantics(
50
      TestSemantics.root(),
51 52 53 54 55 56 57 58
    ));
    expect(find.byType(Opacity), paintsNothing);

    // Opacity 0.0 with semantics: Just semantics
    await tester.pumpWidget(
      const Opacity(
        opacity: 0.0,
        alwaysIncludeSemantics: true,
59
        child: Text('a', textDirection: TextDirection.rtl),
60 61 62
      ),
    );
    expect(semantics, hasSemantics(
63
      TestSemantics.root(
64
        children: <TestSemantics>[
65
          TestSemantics.rootChild(
66
            id: 1,
Dan Field's avatar
Dan Field committed
67
            rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
68 69
            label: 'a',
            textDirection: TextDirection.rtl,
70
          ),
71 72 73 74 75 76 77 78 79
        ],
      ),
    ));
    expect(find.byType(Opacity), paintsNothing);

    // Opacity 0.0 without semantics: Nothing
    await tester.pumpWidget(
      const Opacity(
        opacity: 0.0,
80
        child: Text('a', textDirection: TextDirection.rtl),
81 82 83
      ),
    );
    expect(semantics, hasSemantics(
84
      TestSemantics.root(),
85 86 87 88 89 90 91
    ));
    expect(find.byType(Opacity), paintsNothing);

    // Opacity 0.1: Semantics and painting
    await tester.pumpWidget(
      const Opacity(
        opacity: 0.1,
92
        child: Text('a', textDirection: TextDirection.rtl),
93 94 95
      ),
    );
    expect(semantics, hasSemantics(
96
      TestSemantics.root(
97
        children: <TestSemantics>[
98
          TestSemantics.rootChild(
99
            id: 1,
Dan Field's avatar
Dan Field committed
100
            rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
101 102
            label: 'a',
            textDirection: TextDirection.rtl,
103
          ),
104 105 106 107 108 109 110 111 112
        ],
      ),
    ));
    expect(find.byType(Opacity), paints..paragraph());

    // Opacity 0.1 without semantics: Still has semantics and painting
    await tester.pumpWidget(
      const Opacity(
        opacity: 0.1,
113
        child: Text('a', textDirection: TextDirection.rtl),
114 115 116
      ),
    );
    expect(semantics, hasSemantics(
117
      TestSemantics.root(
118
        children: <TestSemantics>[
119
          TestSemantics.rootChild(
120
            id: 1,
Dan Field's avatar
Dan Field committed
121
            rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
122 123
            label: 'a',
            textDirection: TextDirection.rtl,
124
          ),
125 126 127 128 129 130 131 132 133 134
        ],
      ),
    ));
    expect(find.byType(Opacity), paints..paragraph());

    // Opacity 0.1 with semantics: Semantics and painting
    await tester.pumpWidget(
      const Opacity(
        opacity: 0.1,
        alwaysIncludeSemantics: true,
135
        child: Text('a', textDirection: TextDirection.rtl),
136 137 138
      ),
    );
    expect(semantics, hasSemantics(
139
      TestSemantics.root(
140
        children: <TestSemantics>[
141
          TestSemantics.rootChild(
142
            id: 1,
Dan Field's avatar
Dan Field committed
143
            rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
144 145
            label: 'a',
            textDirection: TextDirection.rtl,
146
          ),
147 148 149 150 151 152 153
        ],
      ),
    ));
    expect(find.byType(Opacity), paints..paragraph());

    semantics.dispose();
  });
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

  testWidgets('offset is correctly handled in Opacity', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: SingleChildScrollView(
            child: RepaintBoundary(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: List<Widget>.generate(10, (int index) {
                  return Opacity(
                    opacity: 0.5,
                    child: Padding(
                      padding: const EdgeInsets.all(5.0),
                      child: Container(
                          color: Colors.blue,
170
                          height: 50,
171
                      ),
172
                    ),
173 174 175
                  );
                }),
              ),
176 177 178
            ),
          ),
        ),
179
      ),
180 181 182
    );
    await expectLater(
      find.byType(RepaintBoundary).first,
183
      matchesGoldenFile('opacity_test.offset.png'),
184
    );
185
  });
186 187 188 189 190 191 192 193

  testWidgets('empty opacity does not crash', (WidgetTester tester) async {
    await tester.pumpWidget(
      RepaintBoundary(child: Opacity(opacity: 0.5, child: Container())),
    );
    final Element element = find.byType(RepaintBoundary).first.evaluate().single;
    // The following line will send the layer to engine and cause crash if an
    // empty opacity layer is sent.
194
    final OffsetLayer offsetLayer = element.renderObject!.debugLayer! as OffsetLayer;
195
    await offsetLayer.toImage(const Rect.fromLTRB(0.0, 0.0, 1.0, 1.0));
196
  }, skip: isBrowser); // https://github.com/flutter/flutter/issues/49857
Dan Field's avatar
Dan Field committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

  testWidgets('Child shows up in the right spot when opacity is disabled', (WidgetTester tester) async {
    debugDisableOpacityLayers = true;
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(
      RepaintBoundary(
        key: key,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Stack(
            children: <Widget>[
              Positioned(
                top: 40,
                left: 140,
                child: Opacity(
                  opacity: .5,
                  child: Container(height: 100, width: 100, color: Colors.red),
                ),
              ),
            ],
          ),
        ),
      ),
    );

    await expectLater(
      find.byKey(key),
      matchesGoldenFile('opacity_disabled_with_child.png'),
    );
    debugDisableOpacityLayers = false;
  });
228
}