Skip to content

Commit c3eb5d0

Browse files
author
David Brunow
committed
Fix issue where text fields do not have "text field" or a hint in their description
1 parent c6b18fb commit c3eb5d0

File tree

5 files changed

+102
-0
lines changed

5 files changed

+102
-0
lines changed

Example/AccessibilitySnapshot.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
1104A8CF2B580AC500B6715F /* SwiftUITextEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1104A8CE2B580AC500B6715F /* SwiftUITextEntry.swift */; };
1011
1635CE4E251EAC6700907101 /* SnapshotTestingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1635CE4D251EAC6700907101 /* SnapshotTestingTests.swift */; };
1112
3D04B6D6211558B0006218A4 /* AccessibilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D04B6D5211558B0006218A4 /* AccessibilityViewController.swift */; };
1213
3D04B6D921155942006218A4 /* LabelAccessibilityPropertiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D04B6D821155942006218A4 /* LabelAccessibilityPropertiesViewController.swift */; };
@@ -77,6 +78,7 @@
7778

7879
/* Begin PBXFileReference section */
7980
0BFCB4FD6BC17AB232B26E72 /* Pods_UnitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_UnitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
81+
1104A8CE2B580AC500B6715F /* SwiftUITextEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUITextEntry.swift; sourceTree = "<group>"; };
8082
1635CE4D251EAC6700907101 /* SnapshotTestingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotTestingTests.swift; sourceTree = "<group>"; };
8183
358D84DCD315110A89BD052E /* Pods-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.debug.xcconfig"; sourceTree = "<group>"; };
8284
3A3192D7B9B16BD10FB517A2 /* Pods_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SnapshotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -179,6 +181,7 @@
179181
children = (
180182
83A295832AC22D9D00DFBE4F /* UserInputLabelsViewController.swift */,
181183
3D4674672116A3F100278B57 /* ViewAccessibilityPropertiesViewController.swift */,
184+
1104A8CE2B580AC500B6715F /* SwiftUITextEntry.swift */,
182185
3F8E5DB82535B25000276B32 /* SwiftUIView.swift */,
183186
3FEF854E253846420072611F /* SwiftUIViewWithScrollView.swift */,
184187
3D39BFAB223314C1009C3EF4 /* TabBarViewController.swift */,
@@ -627,6 +630,7 @@
627630
3DBAC28F2242E7C700EF4D0A /* ListContainerViewController.swift in Sources */,
628631
3DBEAA5B2222953E00FAE61D /* SwitchControlViewController.swift in Sources */,
629632
3DBAC2912242F9B200EF4D0A /* LandmarkContainerViewController.swift in Sources */,
633+
1104A8CF2B580AC500B6715F /* SwiftUITextEntry.swift in Sources */,
630634
3D39BFAC223314C1009C3EF4 /* TabBarViewController.swift in Sources */,
631635
3D04B6DB21155D92006218A4 /* ButtonAccessibilityTraitsViewController.swift in Sources */,
632636
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// Copyright 2024 Square Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
#if swift(>=5.1) && canImport(SwiftUI)
18+
19+
import SwiftUI
20+
21+
struct SwiftUITextEntry: View {
22+
var body: some View {
23+
VStack {
24+
TextField("SwiftUI Text Field", text: .constant(""))
25+
TextField("SwiftUI Text Field", text: .constant("Value in Text Field"))
26+
if #available(iOS 14.0, *) {
27+
TextEditor(text: .constant(""))
28+
}
29+
}
30+
}
31+
}
32+
33+
struct SwiftUITextEntry_Previews: PreviewProvider {
34+
static var previews: some View {
35+
SwiftUITextEntry()
36+
.previewLayout(.sizeThatFits)
37+
}
38+
}
39+
40+
#endif

Example/SnapshotTests/SnapshotTestingTests.swift

+11
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,17 @@ final class SnapshotTestingTests: XCTestCase {
138138
assertSnapshot(matching: viewController, as: .imageWithSmartInvert, named: nameForDevice())
139139
}
140140

141+
func testTextEntry() {
142+
let view = SwiftUITextEntry()
143+
.frame(width: 400, height: 400)
144+
145+
assertSnapshot(
146+
matching: view,
147+
as: .accessibilityImage,
148+
named: nameForDevice()
149+
)
150+
}
151+
141152
// MARK: - Private Methods
142153

143154
private func nameForDevice(baseName: String? = nil) -> String {
Loading

Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+SnapshotAdditions.swift

+47
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@ extension NSObject {
132132
traitSpecifiers.append(strings.tabTraitName)
133133
}
134134

135+
if accessibilityTraits.contains(.textEntry) {
136+
if accessibilityTraits.contains(.scrollable) {
137+
// This is being a UITextView/TextEditor
138+
if let accessibilityValue = accessibilityValue, !accessibilityValue.isEmpty {
139+
// No-op. iOS does not read the trait name when there's text.
140+
} else {
141+
traitSpecifiers.append(strings.textEntryTraitName)
142+
}
143+
} else {
144+
// This is a UITextField/TextField
145+
traitSpecifiers.append(strings.textEntryTraitName)
146+
}
147+
}
148+
135149
if accessibilityTraits.contains(.header) {
136150
traitSpecifiers.append(strings.headerTraitName)
137151
}
@@ -229,6 +243,20 @@ extension NSObject {
229243
}
230244
}
231245

246+
if accessibilityTraits.contains(.textEntry) && !accessibilityTraits.contains(.notEnabled) {
247+
if accessibilityTraits.contains(.scrollable) {
248+
// This is a UITextView/TextEditor
249+
if let accessibilityValue = accessibilityValue, !accessibilityValue.isEmpty {
250+
// No-op. iOS does not read the hint when there's text.
251+
} else {
252+
hintDescription = strings.textEntryTraitHint
253+
}
254+
} else {
255+
// This is a UITextField/TextField
256+
hintDescription = strings.textEntryTraitHint
257+
}
258+
}
259+
232260
let hasHintOnly = (accessibilityHint?.nonEmpty() != nil) && (accessibilityLabel?.nonEmpty() == nil) && (accessibilityValue?.nonEmpty() == nil)
233261
let hidesAdjustableHint = accessibilityTraits.contains(.notEnabled) || accessibilityTraits.contains(.switchButton) || hasHintOnly
234262
if accessibilityTraits.contains(.adjustable) && !hidesAdjustableHint {
@@ -338,6 +366,10 @@ extension NSObject {
338366

339367
let landmarkEndContext: String
340368

369+
let textEntryTraitName: String
370+
371+
let textEntryTraitHint: String
372+
341373
// MARK: - Life Cycle
342374

343375
init(locale: String?) {
@@ -479,6 +511,16 @@ extension NSObject {
479511
comment: "Description of the last element in a landmark container",
480512
locale: locale
481513
)
514+
self.textEntryTraitName = "Text Field.".localized(
515+
key: "trait.text_field.description",
516+
comment: "Description for the 'text entry' accessibility trait",
517+
locale: locale
518+
)
519+
self.textEntryTraitHint = "Double tap to edit.".localized(
520+
key: "trait.text_field.hint",
521+
comment: "Hint describing how to use elements with the 'text entry' accessibility trait",
522+
locale: locale
523+
)
482524
}
483525

484526
}
@@ -512,6 +554,11 @@ extension UIAccessibilityTraits {
512554

513555
static let switchButton = UIAccessibilityTraits(rawValue: 0x0020000000000000)
514556

557+
static let isEditing = UIAccessibilityTraits(rawValue: 0x0000000000200000)
558+
559+
static let textEntry = UIAccessibilityTraits(rawValue: 0x0000000000040000)
560+
561+
static let scrollable = UIAccessibilityTraits(rawValue: 0x0000800000000000)
515562
}
516563

517564
// MARK: -

0 commit comments

Comments
 (0)