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 8
// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])

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

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

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

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

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

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

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

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

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

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

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

  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,
169
                          height: 50,
170
                      ),
171
                    ),
172 173 174
                  );
                }),
              ),
175 176 177
            ),
          ),
        ),
178
      ),
179 180 181
    );
    await expectLater(
      find.byType(RepaintBoundary).first,
182
      matchesGoldenFile('opacity_test.offset.png'),
183
    );
184
  });
185 186 187 188 189 190 191 192

  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.
193
    final OffsetLayer offsetLayer = element.renderObject!.debugLayer! as OffsetLayer;
194
    await offsetLayer.toImage(const Rect.fromLTRB(0.0, 0.0, 1.0, 1.0));
195
  }, skip: isBrowser); // https://github.com/flutter/flutter/issues/49857
Dan Field's avatar
Dan Field committed
196 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

  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;
  });
227
}