Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: ui/views/widget/native_widget_mac_accessibility_unittest.mm

Issue 2934993002: MacViews a11y: Allow VoiceOver to read out views::Label word-by-word. (Closed)
Patch Set: Fix TextfieldTest.AccessiblePasswordTest Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/controls/textfield/textfield_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <memory> 5 #include <memory>
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 #include "base/mac/mac_util.h" 9 #include "base/mac/mac_util.h"
10 #import "base/mac/sdk_forward_declarations.h" 10 #import "base/mac/sdk_forward_declarations.h"
11 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
12 #include "base/strings/sys_string_conversions.h" 12 #include "base/strings/sys_string_conversions.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #import "testing/gtest_mac.h" 14 #import "testing/gtest_mac.h"
15 #include "ui/accessibility/ax_enums.h" 15 #include "ui/accessibility/ax_enums.h"
16 #include "ui/accessibility/ax_node_data.h" 16 #include "ui/accessibility/ax_node_data.h"
17 #import "ui/accessibility/platform/ax_platform_node_mac.h" 17 #import "ui/accessibility/platform/ax_platform_node_mac.h"
18 #include "ui/base/ime/text_input_type.h" 18 #include "ui/base/ime/text_input_type.h"
19 #import "ui/gfx/mac/coordinate_conversion.h" 19 #import "ui/gfx/mac/coordinate_conversion.h"
20 #include "ui/views/controls/button/label_button.h" 20 #include "ui/views/controls/button/label_button.h"
21 #include "ui/views/controls/label.h" 21 #include "ui/views/controls/label.h"
22 #include "ui/views/controls/textfield/textfield.h" 22 #include "ui/views/controls/textfield/textfield.h"
23 #include "ui/views/test/widget_test.h" 23 #include "ui/views/test/widget_test.h"
24 #include "ui/views/widget/widget.h" 24 #include "ui/views/widget/widget.h"
25 25
26 // Expose some methods from AXPlatformNodeCocoa for testing purposes only. 26 // Expose some methods from AXPlatformNodeCocoa for testing purposes only.
27 @interface AXPlatformNodeCocoa (Testing) 27 @interface AXPlatformNodeCocoa (Testing)
28 - (NSString*)AXRole; 28 - (NSString*)AXRole;
29 - (id)AXValue;
30
31 // Text attributes.
32 - (NSString*)AXSelectedText;
33 - (NSValue*)AXSelectedTextRange;
34 - (NSNumber*)AXNumberOfCharacters;
35 - (NSValue*)AXVisibleCharacterRange;
36 - (NSNumber*)AXInsertionPointLineNumber;
29 @end 37 @end
30 38
31 namespace views { 39 namespace views {
32 40
33 namespace { 41 namespace {
34 42
35 NSString* const kTestPlaceholderText = @"Test placeholder text"; 43 NSString* const kTestPlaceholderText = @"Test placeholder text";
36 NSString* const kTestStringValue = @"Test string value"; 44 NSString* const kTestStringValue = @"Test string value";
45 constexpr int kTestStringLength = 17;
46 NSString* const kTestRTLStringValue = @"אבגדהוזאבגדהוז";
37 NSString* const kTestTitle = @"Test textfield"; 47 NSString* const kTestTitle = @"Test textfield";
38 48
39 class FlexibleRoleTestView : public View { 49 class FlexibleRoleTestView : public View {
40 public: 50 public:
41 explicit FlexibleRoleTestView(ui::AXRole role) : role_(role) {} 51 explicit FlexibleRoleTestView(ui::AXRole role) : role_(role) {}
42 void set_role(ui::AXRole role) { role_ = role; } 52 void set_role(ui::AXRole role) { role_ = role; }
43 53
44 // Add a child view and resize to fit the child. 54 // Add a child view and resize to fit the child.
45 void FitBoundsToNewChild(View* view) { 55 void FitBoundsToNewChild(View* view) {
46 AddChildView(view); 56 AddChildView(view);
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 356
347 // NSAccessibilitySelectedTextAttribute and 357 // NSAccessibilitySelectedTextAttribute and
348 // NSAccessibilitySelectedTextRangeAttribute. 358 // NSAccessibilitySelectedTextRangeAttribute.
349 EXPECT_NSEQ(@"", 359 EXPECT_NSEQ(@"",
350 AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute)); 360 AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute));
351 // The cursor will be at the end of the textfield, so the selection range will 361 // The cursor will be at the end of the textfield, so the selection range will
352 // span 0 characters and be located at the index after the last character. 362 // span 0 characters and be located at the index after the last character.
353 EXPECT_EQ(gfx::Range(kTestStringValue.length, kTestStringValue.length), 363 EXPECT_EQ(gfx::Range(kTestStringValue.length, kTestStringValue.length),
354 gfx::Range([AttributeValueAtMidpoint( 364 gfx::Range([AttributeValueAtMidpoint(
355 NSAccessibilitySelectedTextRangeAttribute) rangeValue])); 365 NSAccessibilitySelectedTextRangeAttribute) rangeValue]));
366
356 // Select some text in the middle of the textfield. 367 // Select some text in the middle of the textfield.
357 gfx::Range selection_range(2, 6); 368 const gfx::Range forward_range(2, 6);
358 textfield->SelectRange(selection_range); 369 const NSRange ns_range = forward_range.ToNSRange();
359 EXPECT_NSEQ([kTestStringValue substringWithRange:selection_range.ToNSRange()], 370 textfield->SelectRange(forward_range);
371 EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range],
360 AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute)); 372 AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute));
361 EXPECT_EQ(selection_range, 373 EXPECT_EQ(textfield->GetSelectedText(),
374 base::SysNSStringToUTF16(AttributeValueAtMidpoint(
375 NSAccessibilitySelectedTextAttribute)));
376 EXPECT_EQ(forward_range,
362 gfx::Range([AttributeValueAtMidpoint( 377 gfx::Range([AttributeValueAtMidpoint(
363 NSAccessibilitySelectedTextRangeAttribute) rangeValue])); 378 NSAccessibilitySelectedTextRangeAttribute) rangeValue]));
364 379
380 const gfx::Range reversed_range(6, 2);
381 textfield->SelectRange(reversed_range);
382 // NSRange has no direction, so these are unchanged from the forward range.
383 EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range],
384 AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute));
385 EXPECT_EQ(textfield->GetSelectedText(),
386 base::SysNSStringToUTF16(AttributeValueAtMidpoint(
387 NSAccessibilitySelectedTextAttribute)));
388 EXPECT_EQ(forward_range,
389 gfx::Range([AttributeValueAtMidpoint(
390 NSAccessibilitySelectedTextRangeAttribute) rangeValue]));
391
365 // NSAccessibilityVisibleCharacterRangeAttribute. 392 // NSAccessibilityVisibleCharacterRangeAttribute.
366 EXPECT_EQ(gfx::Range(0, kTestStringValue.length), 393 EXPECT_EQ(gfx::Range(0, kTestStringValue.length),
367 gfx::Range([AttributeValueAtMidpoint( 394 gfx::Range([AttributeValueAtMidpoint(
368 NSAccessibilityVisibleCharacterRangeAttribute) rangeValue])); 395 NSAccessibilityVisibleCharacterRangeAttribute) rangeValue]));
396
397 // Test an RTL string.
398 textfield->SetText(base::SysNSStringToUTF16(kTestRTLStringValue));
399 textfield->SelectRange(forward_range);
400 EXPECT_EQ(textfield->GetSelectedText(),
401 base::SysNSStringToUTF16(AttributeValueAtMidpoint(
402 NSAccessibilitySelectedTextAttribute)));
403 textfield->SelectRange(reversed_range);
404 EXPECT_EQ(textfield->GetSelectedText(),
405 base::SysNSStringToUTF16(AttributeValueAtMidpoint(
406 NSAccessibilitySelectedTextAttribute)));
369 } 407 }
370 408
371 // Test writing accessibility attributes via an accessibility client for normal 409 // Test writing accessibility attributes via an accessibility client for normal
372 // Views. 410 // Views.
373 TEST_F(NativeWidgetMacAccessibilityTest, ViewWritableAttributes) { 411 TEST_F(NativeWidgetMacAccessibilityTest, ViewWritableAttributes) {
374 FlexibleRoleTestView* view = new FlexibleRoleTestView(ui::AX_ROLE_GROUP); 412 FlexibleRoleTestView* view = new FlexibleRoleTestView(ui::AX_ROLE_GROUP);
375 view->SetSize(GetWidgetBounds().size()); 413 view->SetSize(GetWidgetBounds().size());
376 widget()->GetContentsView()->AddChildView(view); 414 widget()->GetContentsView()->AddChildView(view);
377 415
378 // Make sure the accessibility object tested is the correct one. 416 // Make sure the accessibility object tested is the correct one.
(...skipping 15 matching lines...) Expand all
394 [AttributeValueAtMidpoint(NSAccessibilityFocusedAttribute) boolValue]); 432 [AttributeValueAtMidpoint(NSAccessibilityFocusedAttribute) boolValue]);
395 EXPECT_TRUE(view->HasFocus()); 433 EXPECT_TRUE(view->HasFocus());
396 } 434 }
397 435
398 // Test writing accessibility attributes via an accessibility client for 436 // Test writing accessibility attributes via an accessibility client for
399 // editable controls (in this case, views::Textfields). 437 // editable controls (in this case, views::Textfields).
400 TEST_F(NativeWidgetMacAccessibilityTest, TextfieldWritableAttributes) { 438 TEST_F(NativeWidgetMacAccessibilityTest, TextfieldWritableAttributes) {
401 Textfield* textfield = AddChildTextfield(GetWidgetBounds().size()); 439 Textfield* textfield = AddChildTextfield(GetWidgetBounds().size());
402 440
403 // Get the Textfield accessibility object. 441 // Get the Textfield accessibility object.
404 NSPoint midpoint = gfx::ScreenPointToNSPoint(GetWidgetBounds().CenterPoint()); 442 id ax_node = A11yElementAtMidpoint();
405 id ax_node = [widget()->GetNativeWindow() accessibilityHitTest:midpoint];
406 EXPECT_TRUE(ax_node); 443 EXPECT_TRUE(ax_node);
407 444
408 // Make sure it's the correct accessibility object. 445 // Make sure it's the correct accessibility object.
409 id value = 446 id value =
410 [ax_node accessibilityAttributeValue:NSAccessibilityValueAttribute]; 447 [ax_node accessibilityAttributeValue:NSAccessibilityValueAttribute];
411 EXPECT_NSEQ(kTestStringValue, value); 448 EXPECT_NSEQ(kTestStringValue, value);
412 449
413 // Write a new NSAccessibilityValueAttribute. 450 // Write a new NSAccessibilityValueAttribute.
414 EXPECT_TRUE( 451 EXPECT_TRUE(
415 [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]); 452 [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 if (base::mac::IsAtLeastOS10_10()) { 590 if (base::mac::IsAtLeastOS10_10()) {
554 // Check Cocoa's attribute values for PlaceHolder and Value here separately 591 // Check Cocoa's attribute values for PlaceHolder and Value here separately
555 // - these are using the new NSAccessibility protocol. 592 // - these are using the new NSAccessibility protocol.
556 EXPECT_TRUE([cocoa_secure_textfield 593 EXPECT_TRUE([cocoa_secure_textfield
557 isAccessibilitySelectorAllowed:@selector( 594 isAccessibilitySelectorAllowed:@selector(
558 accessibilityPlaceholderValue)]); 595 accessibilityPlaceholderValue)]);
559 EXPECT_TRUE([cocoa_secure_textfield 596 EXPECT_TRUE([cocoa_secure_textfield
560 isAccessibilitySelectorAllowed:@selector(accessibilityValue)]); 597 isAccessibilitySelectorAllowed:@selector(accessibilityValue)]);
561 } 598 }
562 599
563 EXPECT_FALSE(
564 [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]);
565
566 for (NSString* attribute_name in expected_unsupported_attributes) { 600 for (NSString* attribute_name in expected_unsupported_attributes) {
567 SCOPED_TRACE(base::SysNSStringToUTF8([NSString 601 SCOPED_TRACE(base::SysNSStringToUTF8([NSString
568 stringWithFormat:@"Missing attribute is: %@", attribute_name])); 602 stringWithFormat:@"Missing attribute is: %@", attribute_name]));
569 EXPECT_FALSE([views_attributes containsObject:attribute_name]); 603 EXPECT_FALSE([views_attributes containsObject:attribute_name]);
570 EXPECT_FALSE([cocoa_attributes containsObject:attribute_name]); 604 EXPECT_FALSE([cocoa_attributes containsObject:attribute_name]);
571 } 605 }
606
607 // Explicit checks done without comparing to NSTextField.
608 EXPECT_TRUE(
609 [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]);
610 EXPECT_NSEQ(NSAccessibilityTextFieldRole, [ax_node AXRole]);
611
612 NSString* kShownValue = @"•"
613 @"••••••••••••••••";
614 // Sanity check.
615 EXPECT_EQ(kTestStringLength, static_cast<int>([kShownValue length]));
616 EXPECT_NSEQ(kShownValue, [ax_node AXValue]);
617
618 // Cursor currently at the end of input.
619 EXPECT_NSEQ(@"", [ax_node AXSelectedText]);
620 EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(kTestStringLength, 0)],
621 [ax_node AXSelectedTextRange]);
622
623 EXPECT_EQ(kTestStringLength, [[ax_node AXNumberOfCharacters] intValue]);
624 EXPECT_NSEQ(([NSValue valueWithRange:{0, kTestStringLength}]),
625 [ax_node AXVisibleCharacterRange]);
626 EXPECT_EQ(0, [[ax_node AXInsertionPointLineNumber] intValue]);
627
628 // Test replacing text.
629 textfield->SetText(base::ASCIIToUTF16("123"));
630 EXPECT_NSEQ(@"•••", [ax_node AXValue]);
631 EXPECT_EQ(3, [[ax_node AXNumberOfCharacters] intValue]);
632
633 textfield->SelectRange(gfx::Range(2, 3)); // Selects "3".
634 [ax_node accessibilitySetValue:@"ab"
635 forAttribute:NSAccessibilitySelectedTextAttribute];
636 EXPECT_EQ(base::ASCIIToUTF16("12ab"), textfield->text());
637 EXPECT_NSEQ(@"••••", [ax_node AXValue]);
638 EXPECT_EQ(4, [[ax_node AXNumberOfCharacters] intValue]);
639 }
640
641 // Test text-specific attributes of Labels.
642 TEST_F(NativeWidgetMacAccessibilityTest, Label) {
643 Label* label = new Label;
644 label->SetText(base::SysNSStringToUTF16(kTestStringValue));
645 label->SetSize(GetWidgetBounds().size());
646 widget()->GetContentsView()->AddChildView(label);
647
648 // Get the Label's accessibility object.
649 id ax_node = A11yElementAtMidpoint();
650 EXPECT_TRUE(ax_node);
651
652 EXPECT_NSEQ(NSAccessibilityStaticTextRole, [ax_node AXRole]);
653 EXPECT_NSEQ(kTestStringValue, [ax_node AXValue]);
654
655 // No selection by default. TODO(tapted): Test selection when views::Label
656 // uses RenderTextHarfBuzz on Mac. See http://crbug.com/454835.
657 // For now, this tests that the codepaths are valid for views::Label.
658 EXPECT_NSEQ(@"", [ax_node AXSelectedText]);
659 EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(0, 0)],
660 [ax_node AXSelectedTextRange]);
661
662 EXPECT_EQ(kTestStringLength, [[ax_node AXNumberOfCharacters] intValue]);
663 EXPECT_NSEQ(([NSValue valueWithRange:{0, kTestStringLength}]),
664 [ax_node AXVisibleCharacterRange]);
665 EXPECT_EQ(0, [[ax_node AXInsertionPointLineNumber] intValue]);
572 } 666 }
573 667
574 } // namespace views 668 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698