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

When Testing Accessibility, Text Contrast Tests Do Not Always Give Right Results #50376

Open
pennzht opened this issue Feb 7, 2020 · 3 comments
Labels
a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests framework flutter/packages/flutter repository. See also f: labels. P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team

Comments

@pennzht
Copy link
Member

pennzht commented Feb 7, 2020

Steps to Reproduce

  1. Checkout the file packages/flutter_test/test/accessibility_test.dart from the following branch.
    • https://github.com/pennzht/flutter/tree/contrast-test-issue
    • This file contains some additional tests for color contrast.
    • Alternatively, you can add the tests (see the Additional Tests section below) to packages/flutter_test/test/accessibility_test.dart.
    • You can use tests in this file to test your own implementations for packages/flutter_test/lib/src/accessibility.dart.
  2. Go to the path packages/flutter_test and run flutter test test/accessibility_test.dart

Expected results:

  • All tests should pass.
    • During a color contrast test, all text widgets which contribute to semantics should be tested for their color contrast ratio, including children of MergeSemantics widgets. Text widgets that do not contribute to semantics should be skipped.

Actual results:

  • The following tests fail:
    • text contrast guideline white text on white background with merge semantics
    • white and black text on white
    • black and white text on white
    • irrelevant text
    • irrelevant button

Related Solutions

May be fixed by #48868

Logs
  • Some personal information has been << REMOVED >>.
  • The following log is for flutter test --verbose test/accessibility_test.dart.
<< REMOVED >>-macbookpro:flutter_test << REMOVED >>$ flutter test --verbose test/accessibility_test.dart 
[  +22 ms] executing: [/Users/<< REMOVED >>/Documents/f/flutter/] git -c log.showSignature=false log -n 1 --pretty=format:%H
[  +28 ms] Exit code 0 from: git -c log.showSignature=false log -n 1 --pretty=format:%H
[        ] << REMOVED >>
[        ] executing: [/Users/<< REMOVED >>/Documents/f/flutter/] git describe --match v*.*.* --first-parent --long --tags
[  +20 ms] Exit code 0 from: git describe --match v*.*.* --first-parent --long --tags
[        ] v1.15.2-31-<< REMOVED >>
[   +7 ms] executing: [/Users/<< REMOVED >>/Documents/f/flutter/] git rev-parse --abbrev-ref --symbolic @{u}
[   +5 ms] Exit code 128 from: git rev-parse --abbrev-ref --symbolic @{u}
[        ] fatal: no upstream configured for branch 'contrast-test-issue'
[  +18 ms] Artifact Instance of 'MaterialFonts' is not required, skipping update.
[        ] Artifact Instance of 'GradleWrapper' is not required, skipping update.
[        ] Artifact Instance of 'AndroidMavenArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[        ] Artifact Instance of 'FlutterSdk' is not required, skipping update.
[        ] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FontSubsetArtifacts' is not required, skipping update.
[  +64 ms] running test package with arguments: [-r, compact, --concurrency=10, --test-randomize-ordering-seed=0, --,
/Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart]
00:00 +0: loading /Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart                           [ +167 ms] test 0: starting test /Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart
[  +17 ms] test 0: starting shell process
[   +4 ms] Stopping scan for flutter_test_config.dart; found project root at
/Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test
[   +7 ms] Compiler will use the following file as its incremental dill file:
/var/folders/3l/<< REMOVED >>/T/flutter_test_compiler.2XrLZx/output.dill
[        ] Listening to compiler controller...
[   +2 ms] Compiling /var/folders/3l/<< REMOVED >>/T/flutter_test_listener.D4nwqe/listener.dart
[  +13 ms] /Users/<< REMOVED >>/Documents/f/flutter/bin/cache/dart-sdk/bin/dart
/Users/<< REMOVED >>/Documents/f/flutter/bin/cache/artifacts/engine/darwin-x64/frontend_server.dart.snapshot --sdk-root
/Users/<< REMOVED >>/Documents/f/flutter/bin/cache/artifacts/engine/common/flutter_patched_sdk/ --incremental --target=flutter
-Ddart.developer.causal_async_stacks=true --output-dill
/var/folders/3l/<< REMOVED >>/T/flutter_test_compiler.2XrLZx/output.dill --packages
/Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/.packages -Ddart.vm.profile=false -Ddart.vm.product=false
--bytecode-options=source-positions,local-var-info,debugger-stops,instance-field-initializers,keep-unreachable-code,avoid-closure-cal
l-instructions --enable-asserts --track-widget-creation --initialize-from-dill
/Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/build/testfile.dill.track.dill
[  +18 ms] <- compile /var/folders/3l/<< REMOVED >>/T/flutter_test_listener.D4nwqe/listener.dart
00:06 +0: loading /Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart                           [+6105 ms] <- accept
[        ] <- reset
[        ] Compiling /var/folders/3l/<< REMOVED >>/T/flutter_test_listener.D4nwqe/listener.dart took 6138ms
[   +1 ms] /Users/<< REMOVED >>/Documents/f/flutter/bin/cache/artifacts/engine/darwin-x64/flutter_tester --disable-observatory
--enable-checked-mode --verify-entry-points --enable-software-rendering --skia-deterministic-rendering --enable-dart-profiling
--non-interactive --use-test-fonts --packages=/Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/.packages
/var/folders/3l/<< REMOVED >>/T/flutter_test_listener.D4nwqe/listener.dart.dill
[   +1 ms] Using this directory for fonts configuration: /var/folders/3l/<< REMOVED >>/T/flutter_test_fonts.bkjW2N
[   +7 ms] test 0: awaiting initial result for pid 18541
[ +351 ms] test 0: process with pid 18541 connected to test harness
[        ] test 0: awaiting test result for pid 18541
00:07 +0: text contrast guideline white text on white background with merge semantics                                               
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: Does not Text contrast should follow WCAG guidelines
  Actual: <Instance of 'WidgetTester'>
   Which: Failed

When the exception was thrown, this was the stack:
#0      fail (package:test_api/src/frontend/expect.dart:153:30)
#1      _expect.<anonymous closure> (package:test_api/src/frontend/expect.dart:127:9)
#13     _DoesNotMatchAccessibilityGuideline.matchAsync (package:flutter_test/src/matchers.dart)
<asynchronous suspension>
#14     _expect (package:test_api/src/frontend/expect.dart:116:26)
#15     expectLater (package:test_api/src/frontend/expect.dart:75:5)
#16     expectLater (package:flutter_test/src/widget_tester.dart:385:10)
#17     main.<anonymous closure>.<anonymous closure> (file:///Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart:35:13)
<asynchronous suspension>
#18     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#19     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:706:19)
<asynchronous suspension>
#22     TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:686:14)
#23     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1086:24)
#29     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1083:15)
#30     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#31     Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#32     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#37     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#38     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#43     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#44     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
(elided 42 frames from class _FakeAsync, class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)

The test description was:
  white text on white background with merge semantics
════════════════════════════════════════════════════════════════════════════════════════════════════
00:07 +0 -1: text contrast guideline white text on white background with merge semantics [E]                                        
  Test failed. See exception logs above.
  The test description was: white text on white background with merge semantics
  
00:08 +36 -1: white and black text on white                                                                                         
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: Does not Text contrast should follow WCAG guidelines
  Actual: <Instance of 'WidgetTester'>
   Which: Failed

When the exception was thrown, this was the stack:
#0      fail (package:test_api/src/frontend/expect.dart:153:30)
#1      _expect.<anonymous closure> (package:test_api/src/frontend/expect.dart:127:9)
#13     _DoesNotMatchAccessibilityGuideline.matchAsync (package:flutter_test/src/matchers.dart)
<asynchronous suspension>
#14     _expect (package:test_api/src/frontend/expect.dart:116:26)
#15     expectLater (package:test_api/src/frontend/expect.dart:75:5)
#16     expectLater (package:flutter_test/src/widget_tester.dart:385:10)
#17     main.<anonymous closure> (file:///Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart:698:11)
<asynchronous suspension>
#18     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#19     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:706:19)
<asynchronous suspension>
#22     TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:686:14)
#23     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1086:24)
#29     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1083:15)
#30     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#31     Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#32     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#37     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#38     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#43     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#44     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
(elided 42 frames from class _FakeAsync, class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)

The test description was:
  white and black text on white
════════════════════════════════════════════════════════════════════════════════════════════════════
00:08 +36 -2: white and black text on white [E]                                                                                     
  Test failed. See exception logs above.
  The test description was: white and black text on white
  
00:08 +36 -2: black and white text on white                                                                                         
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: Does not Text contrast should follow WCAG guidelines
  Actual: <Instance of 'WidgetTester'>
   Which: Failed

When the exception was thrown, this was the stack:
#0      fail (package:test_api/src/frontend/expect.dart:153:30)
#1      _expect.<anonymous closure> (package:test_api/src/frontend/expect.dart:127:9)
#13     _DoesNotMatchAccessibilityGuideline.matchAsync (package:flutter_test/src/matchers.dart)
<asynchronous suspension>
#14     _expect (package:test_api/src/frontend/expect.dart:116:26)
#15     expectLater (package:test_api/src/frontend/expect.dart:75:5)
#16     expectLater (package:flutter_test/src/widget_tester.dart:385:10)
#17     main.<anonymous closure> (file:///Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart:722:11)
<asynchronous suspension>
#18     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#19     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:706:19)
<asynchronous suspension>
#22     TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:686:14)
#23     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1086:24)
#29     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1083:15)
#30     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#31     Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#32     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#37     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#38     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#43     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#44     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
(elided 42 frames from class _FakeAsync, class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)

The test description was:
  black and white text on white
════════════════════════════════════════════════════════════════════════════════════════════════════
00:08 +36 -3: black and white text on white [E]                                                                                     
  Test failed. See exception logs above.
  The test description was: black and white text on white
  
00:08 +36 -3: irrelevant text                                                                                                       
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: Text contrast should follow WCAG guidelines
  Actual: <Instance of 'WidgetTester'>
   Which: Multiple nodes with the same label: One

When the exception was thrown, this was the stack:
#0      fail (package:test_api/src/frontend/expect.dart:153:30)
#1      _expect.<anonymous closure> (package:test_api/src/frontend/expect.dart:127:9)
#13     _MatchesAccessibilityGuideline.matchAsync (package:flutter_test/src/matchers.dart)
<asynchronous suspension>
#14     _expect (package:test_api/src/frontend/expect.dart:116:26)
#15     expectLater (package:test_api/src/frontend/expect.dart:75:5)
#16     expectLater (package:flutter_test/src/widget_tester.dart:385:10)
#17     main.<anonymous closure> (file:///Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart:748:11)
<asynchronous suspension>
#18     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#19     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:706:19)
<asynchronous suspension>
#22     TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:686:14)
#23     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1086:24)
#29     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1083:15)
#30     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#31     Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#32     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#37     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#38     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#43     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#44     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
(elided 42 frames from class _FakeAsync, class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)

The test description was:
  irrelevant text
════════════════════════════════════════════════════════════════════════════════════════════════════
00:08 +36 -4: irrelevant text [E]                                                                                                   
  Test failed. See exception logs above.
  The test description was: irrelevant text
  
00:08 +37 -4: irrelevant button                                                                                                     
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: Text contrast should follow WCAG guidelines
  Actual: <Instance of 'WidgetTester'>
   Which: Multiple nodes with the same label: One

When the exception was thrown, this was the stack:
#0      fail (package:test_api/src/frontend/expect.dart:153:30)
#1      _expect.<anonymous closure> (package:test_api/src/frontend/expect.dart:127:9)
#13     _MatchesAccessibilityGuideline.matchAsync (package:flutter_test/src/matchers.dart)
<asynchronous suspension>
#14     _expect (package:test_api/src/frontend/expect.dart:116:26)
#15     expectLater (package:test_api/src/frontend/expect.dart:75:5)
#16     expectLater (package:flutter_test/src/widget_tester.dart:385:10)
#17     main.<anonymous closure> (file:///Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_test/test/accessibility_test.dart:800:11)
<asynchronous suspension>
#18     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#19     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:706:19)
<asynchronous suspension>
#22     TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:686:14)
#23     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1086:24)
#29     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1083:15)
#30     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#31     Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#32     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#37     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#38     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#43     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#44     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
(elided 42 frames from class _FakeAsync, class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)

The test description was:
  irrelevant button
════════════════════════════════════════════════════════════════════════════════════════════════════
00:08 +37 -5: irrelevant button [E]                                                                                                 
  Test failed. See exception logs above.
  The test description was: irrelevant button
  
00:08 +39 -5: black and white text, without MergeSemantics                                                                          [+2229 ms] test 0: process with pid 18541 no longer needed by test harness
[        ] test 0: cleaning up...
[        ] test 0: ensuring end-of-process for shell
[  +20 ms] test 0: deleting temporary directory
[   +2 ms] test 0: shutting down test harness socket server
[   +2 ms] test 0: finished
00:08 +39 -5: Some tests failed.                                                                                                    
[  +15 ms] Deleting /var/folders/3l/<< REMOVED >>/T/flutter_test_compiler.2XrLZx...
[   +4 ms] killing pid 18527
[  +50 ms] Deleting /var/folders/3l/<< REMOVED >>/T/flutter_test_fonts.bkjW2N...
[   +5 ms] test package returned with exit code 1

#0      throwToolExit (package:flutter_tools/src/base/common.dart:14:3)
#1      TestCommand.runCommand (package:flutter_tools/src/commands/test.dart:271:7)
<asynchronous suspension>
#2      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:29)
#3      _rootRun (dart:async/zone.dart:1126:13)
#4      _CustomZone.run (dart:async/zone.dart:1023:19)
#5      _runZoned (dart:async/zone.dart:1518:10)
#6      runZoned (dart:async/zone.dart:1465:12)
#7      AppContext.run (package:flutter_tools/src/base/context.dart:149:18)
#8      FastFlutterCommand.run (package:flutter_tools/src/runner/flutter_command.dart:877:20)
#9      CommandRunner.runCommand (package:args/command_runner.dart:197:27)
#10     FlutterCommandRunner.runCommand.<anonymous closure> (package:flutter_tools/src/runner/flutter_command_runner.dart:338:21)
<asynchronous suspension>
#11     AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:29)
#12     _rootRun (dart:async/zone.dart:1126:13)
#13     _CustomZone.run (dart:async/zone.dart:1023:19)
#14     _runZoned (dart:async/zone.dart:1518:10)
#15     runZoned (dart:async/zone.dart:1465:12)
#16     AppContext.run (package:flutter_tools/src/base/context.dart:149:18)
#17     FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:288:19)
#18     CommandRunner.run.<anonymous closure> (package:args/command_runner.dart:112:25)
#19     new Future.sync (dart:async/future.dart:224:31)
#20     CommandRunner.run (package:args/command_runner.dart:112:14)
#21     FlutterCommandRunner.run (package:flutter_tools/src/runner/flutter_command_runner.dart:231:18)
#22     run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:64:22)
#23     _rootRun (dart:async/zone.dart:1126:13)
#24     _CustomZone.run (dart:async/zone.dart:1023:19)
#25     _runZoned (dart:async/zone.dart:1518:10)
#26     runZoned (dart:async/zone.dart:1502:12)
#27     run.<anonymous closure> (package:flutter_tools/runner.dart:62:18)
<asynchronous suspension>
#28     AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:29)
#29     _rootRun (dart:async/zone.dart:1126:13)
#30     _CustomZone.run (dart:async/zone.dart:1023:19)
#31     _runZoned (dart:async/zone.dart:1518:10)
#32     runZoned (dart:async/zone.dart:1465:12)
#33     AppContext.run (package:flutter_tools/src/base/context.dart:149:18)
#34     runInContext (package:flutter_tools/src/context_runner.dart:64:24)
#35     run (package:flutter_tools/runner.dart:51:10)
#36     main (package:flutter_tools/executable.dart:65:9)
#37     main (file:///Users/<< REMOVED >>/Documents/f/flutter/packages/flutter_tools/bin/flutter_tools.dart:8:3)
#38     _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:299:32)
#39     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)



[  +12 ms] executing: [/Users/<< REMOVED >>/Documents/f/flutter/] git rev-parse --abbrev-ref HEAD
[   +7 ms] Exit code 0 from: git rev-parse --abbrev-ref HEAD
[        ] contrast-test-issue
<< REMOVED >>-macbookpro:flutter_test << REMOVED >>$ 
<< REMOVED >>-macbookpro:flutter_test << REMOVED >>$ flutter analyze
Analyzing flutter_test...                                               
No issues found! (ran in 1.7s)
<< REMOVED >>-macbookpro:flutter_test << REMOVED >>$ 
<< REMOVED >>-macbookpro:flutter_test << REMOVED >>$ flutter doctor -v
Downloading android-arm-profile/darwin-x64 tools...                 1.0s
Downloading android-arm-release/darwin-x64 tools...                 1.0s
Downloading android-arm64-profile/darwin-x64 tools...               0.8s
Downloading android-arm64-release/darwin-x64 tools...               0.8s
Downloading android-x64-profile/darwin-x64 tools...                 0.8s
Downloading android-x64-release/darwin-x64 tools...                 0.7s
[✓] Flutter (Channel unknown, v1.15.3-pre.30, on Mac OS X 10.14.6 18G2022, locale en-DE)
    • Flutter version 1.15.3-pre.30 at /Users/<< REMOVED >>/Documents/f/flutter
    • Framework revision << REMOVED >> (10 minutes ago), 2020-02-07 23:50:53 +0100
    • Engine revision << REMOVED >>
    • Dart version 2.8.0 (build 2.8.0-dev.7.0 << REMOVED >>)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at /Users/<< REMOVED >>/Library/Android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.2.1)
    • Xcode at /Applications/Xcode 11.2.1.app/Contents/Developer
    • Xcode 11.2.1, Build version 11B500
    • CocoaPods version 1.7.5

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 3.5)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 39.0.3
    • Dart plugin version 191.8423
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] Connected device (3 available)
    • macOS      • macOS      • darwin-x64     • Mac OS X 10.14.6 18G2022
    • Chrome     • chrome     • web-javascript • Google Chrome 80.0.3987.87
    • Web Server • web-server • web-javascript • Flutter Tools

• No issues found!
<< REMOVED >>-macbookpro:flutter_test << REMOVED >>$ 

Additional Tests

Additional tests
    testWidgets('white text on white background with merge semantics', (WidgetTester tester) async {
      final SemanticsHandle handle = tester.ensureSemantics();
      await tester.pumpWidget(MaterialApp(
        home: Scaffold(
          backgroundColor: Colors.white,
          body: Center(
            child: MergeSemantics(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const <Widget>[
                  Text(
                    'I am text one',
                    style: TextStyle(color: Colors.white),
                  ),
                  Text(
                    'And I am text two',
                    style: TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
          ),
        ),
      ));

      await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
      handle.dispose();
    });

    testWidgets('black text on white background with merge semantics', (WidgetTester tester) async {
      final SemanticsHandle handle = tester.ensureSemantics();
      await tester.pumpWidget(MaterialApp(
        home: Scaffold(
          backgroundColor: Colors.white,
          body: Center(
            child: MergeSemantics(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const <Widget>[
                  Text(
                    'I am text one',
                    style: TextStyle(color: Colors.black),
                  ),
                  Text(
                    'And I am text two',
                    style: TextStyle(color: Colors.black),
                  ),
                ],
              ),
            ),
          ),
        ),
      ));

      await expectLater(tester, meetsGuideline(textContrastGuideline));
      handle.dispose();
    });

  testWidgets('white text on white', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: MergeSemantics(
                child: Column(
                  children: const <Widget>[
                    Text('White', style: TextStyle(color: Colors.white)),
                  ]
                ),
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('white and black text on white', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: MergeSemantics(
                child: Column(
                  children: const <Widget>[
                    Text('White', style: TextStyle(color: Colors.white)),
                    SizedBox(height: 30),
                    Text('Black', style: TextStyle(color: Colors.black)),
                  ]
                ),
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('black and white text on white', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: MergeSemantics(
                child: Column(
                  children: const <Widget>[
                    Text('Black', style: TextStyle(color: Colors.black)),
                    SizedBox(height: 30),
                    Text('White', style: TextStyle(color: Colors.white)),
                  ]
                ),
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant text', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.white)),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant text - passing', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: Text('Two', style: TextStyle(color: Colors.white)),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant button', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: FlatButton(child: Text('One'), onPressed: null),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant button - passing', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: FlatButton(child: Text('Two'), onPressed: null),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('black and white text, without MergeSemantics', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  ),
                  SizedBox(height: 30),
                  Text('One', style: TextStyle(color: Colors.white)),
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });
@pennzht pennzht self-assigned this Feb 7, 2020
@VladyslavBondarenko VladyslavBondarenko added a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests framework flutter/packages/flutter repository. See also f: labels. labels Feb 10, 2020
@pennzht pennzht added this to In progress in Material Flutter - Sprint 36 Feb 11, 2020
@clocksmith clocksmith moved this from In progress to Sprint + 1 in Material Flutter - Sprint 36 Aug 18, 2020
@TahaTesser
Copy link
Member

Hi @pennzht
Not sure if this is still valid but cloning repo and flutter test test/accessibility_test.dart , did pass all the test on the latest master

tahatesser@Tahas-MacBook-Pro flutter_test % flutterm test test/accessibility_test.dart
Running "flutter pub get" in flutter_test...                        1.5s
00:11 +34: All tests passed!                
flutter doctor -v
[✓] Flutter (Channel master, 1.22.0-10.0.pre.251, on Mac OS X 10.15.6 19G2021
    x86_64, locale en-GB)
    • Flutter version 1.22.0-10.0.pre.251 at
      /Users/tahatesser/Code/flutter_master
    • Framework revision d26268bb9e (13 hours ago), 2020-09-18 09:06:26 +0900
    • Engine revision 2abe69c608
    • Dart version 2.10.0 (build 2.10.0-136.0.dev)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/tahatesser/Code/sdk
    • Platform android-30, build-tools 30.0.2
    • ANDROID_HOME = /Users/tahatesser/Code/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.0)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.0, Build version 12A7209
    • CocoaPods version 1.9.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 49.0.2
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.49.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.14.1

[✓] Connected device (3 available)
    • macOS (desktop)  • macos      • darwin-x64     • Mac OS X 10.15.6 19G2021
      x86_64
    • Web Server (web) • web-server • web-javascript • Flutter Tools
    • Chrome (web)     • chrome     • web-javascript • Google Chrome
      85.0.4183.102

• No issues found!

@TahaTesser TahaTesser added passed first triage waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds labels Sep 18, 2020
@pennzht
Copy link
Member Author

pennzht commented Sep 18, 2020

@TahaTesser Thank you for your message!

You need to checkout the file packages/flutter_test/test/accessibility_test.dart from the branch pennzht:contrast-test-issue. This branch adds a few tests which should pass, but fail.

Alternatively, you can add the following tests to packages/flutter_test/test/accessibility_test.dart and test it again. The tests are still failing on the latest master.

Additional tests
    testWidgets('white text on white background with merge semantics', (WidgetTester tester) async {
      final SemanticsHandle handle = tester.ensureSemantics();
      await tester.pumpWidget(MaterialApp(
        home: Scaffold(
          backgroundColor: Colors.white,
          body: Center(
            child: MergeSemantics(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const <Widget>[
                  Text(
                    'I am text one',
                    style: TextStyle(color: Colors.white),
                  ),
                  Text(
                    'And I am text two',
                    style: TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
          ),
        ),
      ));

      await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
      handle.dispose();
    });

    testWidgets('black text on white background with merge semantics', (WidgetTester tester) async {
      final SemanticsHandle handle = tester.ensureSemantics();
      await tester.pumpWidget(MaterialApp(
        home: Scaffold(
          backgroundColor: Colors.white,
          body: Center(
            child: MergeSemantics(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const <Widget>[
                  Text(
                    'I am text one',
                    style: TextStyle(color: Colors.black),
                  ),
                  Text(
                    'And I am text two',
                    style: TextStyle(color: Colors.black),
                  ),
                ],
              ),
            ),
          ),
        ),
      ));

      await expectLater(tester, meetsGuideline(textContrastGuideline));
      handle.dispose();
    });

  testWidgets('white text on white', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: MergeSemantics(
                child: Column(
                  children: const <Widget>[
                    Text('White', style: TextStyle(color: Colors.white)),
                  ]
                ),
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('white and black text on white', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: MergeSemantics(
                child: Column(
                  children: const <Widget>[
                    Text('White', style: TextStyle(color: Colors.white)),
                    SizedBox(height: 30),
                    Text('Black', style: TextStyle(color: Colors.black)),
                  ]
                ),
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('black and white text on white', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: MergeSemantics(
                child: Column(
                  children: const <Widget>[
                    Text('Black', style: TextStyle(color: Colors.black)),
                    SizedBox(height: 30),
                    Text('White', style: TextStyle(color: Colors.white)),
                  ]
                ),
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant text', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.white)),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant text - passing', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: Text('Two', style: TextStyle(color: Colors.white)),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant button', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: FlatButton(child: Text('One'), onPressed: null),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('irrelevant button - passing', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: FlatButton(child: Text('Two'), onPressed: null),
                  ),
                  SizedBox(height: 30),
                  MergeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  )
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, meetsGuideline(textContrastGuideline));
    handle.dispose();
  });

  testWidgets('black and white text, without MergeSemantics', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData.light(),
          home: Scaffold(
            backgroundColor: Colors.white,
            body: Center(
              child: Column(
                children: const <Widget>[
                  ExcludeSemantics(
                    child: Text('One', style: TextStyle(color: Colors.black)),
                  ),
                  SizedBox(height: 30),
                  Text('One', style: TextStyle(color: Colors.white)),
                ],
              ),
            ),
          ),
        ));
    await expectLater(tester, doesNotMeetGuideline(textContrastGuideline));
    handle.dispose();
  });

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Sep 18, 2020
@pennzht
Copy link
Member Author

pennzht commented Sep 18, 2020

@TahaTesser I updated the description.

@guidezpl guidezpl moved this from Sprint + 1 to Backlog in Material Flutter - Sprint 36 Feb 2, 2022
@goderbauer goderbauer added the P2 Important issues not at the top of the work list label Oct 4, 2022
@flutter-triage-bot flutter-triage-bot bot added team-framework Owned by Framework team triaged-framework Triaged by Framework team labels Jul 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests framework flutter/packages/flutter repository. See also f: labels. P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team
Projects
No open projects
Development

No branches or pull requests

5 participants