diff --git a/AccessibilityTests/Sources/Application.swift b/AccessibilityTests/Sources/Application.swift
new file mode 100644
index 000000000..d78470936
--- /dev/null
+++ b/AccessibilityTests/Sources/Application.swift
@@ -0,0 +1,41 @@
+//
+// Copyright 2022-2024 New Vector Ltd.
+//
+// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
+// Please see LICENSE files in the repository root for full details.
+//
+
+import XCTest
+
+enum Application {
+ static func launch(viewID: String) -> XCUIApplication {
+ checkEnvironments()
+
+ let app = XCUIApplication()
+
+ let launchEnvironment = [
+ "ACCESSIBILITY_VIEW": viewID
+ ]
+
+ app.launchEnvironment = launchEnvironment
+ app.launch()
+ return app
+ }
+
+ private static func checkEnvironments() {
+ let requirediPhoneSimulator = "iPhone17,3" // iPhone 16
+ let requiredOSVersion = 18
+
+ let osVersion = ProcessInfo().operatingSystemVersion
+ guard osVersion.majorVersion == requiredOSVersion else {
+ fatalError("Switch to iOS \(requiredOSVersion) for these tests.")
+ }
+
+ guard let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] else {
+ fatalError("Unknown simulator.")
+ }
+ guard deviceModel == requirediPhoneSimulator else {
+ fatalError("Running on \(deviceModel) but we only support \(requirediPhoneSimulator)")
+ }
+ }
+}
diff --git a/AccessibilityTests/Sources/Test.swift b/AccessibilityTests/Sources/Test.swift
new file mode 100644
index 000000000..8c5e3ae70
--- /dev/null
+++ b/AccessibilityTests/Sources/Test.swift
@@ -0,0 +1,43 @@
+//
+// Copyright 2025 New Vector Ltd.
+//
+// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
+// Please see LICENSE files in the repository root for full details.
+//
+
+import XCTest
+
+@MainActor
+class Test: XCTestCase {
+ var app: XCUIApplication!
+
+ func test() async throws {
+ let client = try UITestsSignalling.Client(mode: .tests)
+ app = Application.launch(viewID: "SecureBackupLogoutConfirmationScreen_Previews")
+ await client.waitForApp()
+ defer { try? client.stop() }
+
+ try client.send(.accessibilityAudit(.nextPreview))
+ forLoop: for await signal in client.signals.values {
+ switch signal {
+ case .accessibilityAudit(let auditSignal):
+ switch auditSignal {
+ case .nextPreviewReady(let name):
+ try? app.performAccessibilityAudit { issue in
+ XCTFail("\(name): \(issue)")
+ return true
+ }
+ try? client.send(.accessibilityAudit(.nextPreview))
+ case .noMorePreviews:
+ break forLoop
+ default:
+ fatalError("Unhandled signal")
+ }
+ default:
+ fatalError("Unhandled signal")
+ }
+ }
+
+ app.terminate()
+ }
+}
diff --git a/AccessibilityTests/SupportingFiles/AccessibilityTests.xctestplan b/AccessibilityTests/SupportingFiles/AccessibilityTests.xctestplan
new file mode 100644
index 000000000..a2a909774
--- /dev/null
+++ b/AccessibilityTests/SupportingFiles/AccessibilityTests.xctestplan
@@ -0,0 +1,52 @@
+{
+ "configurations" : [
+ {
+ "id" : "EFC6A442-D3B7-4273-B349-7A923C06AF5E",
+ "name" : "Default",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "addressSanitizer" : {
+ "enabled" : true
+ },
+ "codeCoverage" : {
+ "targets" : [
+ {
+ "containerPath" : "container:ElementX.xcodeproj",
+ "identifier" : "C0FAEB81CFD9776CD78CE489",
+ "name" : "ElementX"
+ }
+ ]
+ },
+ "defaultTestExecutionTimeAllowance" : 120,
+ "environmentVariableEntries" : [
+
+ ],
+ "language" : "en-US",
+ "locationScenario" : {
+ "identifier" : "San Francisco, CA, USA",
+ "referenceType" : "built-in"
+ },
+ "region" : "US",
+ "targetForVariableExpansion" : {
+ "containerPath" : "container:ElementX.xcodeproj",
+ "identifier" : "C0C687DE1D270F9895FEE186",
+ "name" : "AccessibilityTests"
+ },
+ "testTimeoutsEnabled" : true,
+ "undefinedBehaviorSanitizerEnabled" : true
+ },
+ "testTargets" : [
+ {
+ "target" : {
+ "containerPath" : "container:ElementX.xcodeproj",
+ "identifier" : "C0C687DE1D270F9895FEE186",
+ "name" : "AccessibilityTests"
+ }
+ }
+ ],
+ "version" : 1
+}
diff --git a/AccessibilityTests/SupportingFiles/Info.plist b/AccessibilityTests/SupportingFiles/Info.plist
new file mode 100644
index 000000000..6c40a6cd0
--- /dev/null
+++ b/AccessibilityTests/SupportingFiles/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/AccessibilityTests/SupportingFiles/target.yml b/AccessibilityTests/SupportingFiles/target.yml
new file mode 100644
index 000000000..b80f00867
--- /dev/null
+++ b/AccessibilityTests/SupportingFiles/target.yml
@@ -0,0 +1,51 @@
+name: AccessibilityTests
+
+schemes:
+ AccessibilityTests:
+ analyze:
+ config: Debug
+ archive:
+ config: Release
+ build:
+ targets:
+ AccessibilityTests: all
+ profile:
+ config: Release
+ run:
+ config: Debug
+ disableMainThreadChecker: false
+ test:
+ config: Debug
+ testPlans:
+ - path: AccessibilityTests.xctestplan
+ defaultPlan: true
+
+targets:
+ AccessibilityTests:
+ type: bundle.ui-testing
+ platform: iOS
+
+ dependencies:
+ - target: ElementX
+ - package: KZFileWatchers
+
+ info:
+ path: ../SupportingFiles/Info.plist
+
+ settings:
+ base:
+ PRODUCT_NAME: AccessibilityTests
+ PRODUCT_BUNDLE_IDENTIFIER: ${BASE_BUNDLE_IDENTIFIER}.accessibility.tests
+ configs:
+ # This is required to remove the $(inherited) flags
+ # which would prevent SnapshotTesting to be imported in UI Tests
+ debug:
+ OTHER_SWIFT_FLAGS: ["-DDEBUG"]
+ release:
+ OTHER_SWIFT_FLAGS: ["-DRELEASE"]
+
+ sources:
+ - path: ../Sources
+ - path: ../SupportingFiles
+ - path: ../../ElementX/Sources/UITests/UITestsSignalling.swift
+
diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj
index a09ce1bfc..a656c8d60 100644
--- a/ElementX.xcodeproj/project.pbxproj
+++ b/ElementX.xcodeproj/project.pbxproj
@@ -178,6 +178,7 @@
1D623953F970D11F6F38499C /* AppLockService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B95BB98649B8E773D6790 /* AppLockService.swift */; };
1D69E31913DF66426985909B /* EmojiPickerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */; };
1DC227816777A2F3A19657E5 /* RoomDirectorySearchScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */; };
+ 1ECE584D2CFA0FEF0ADE458C /* TestablePreviewsDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA723686F23EF45E2B398FBC /* TestablePreviewsDictionary.swift */; };
1F3232BD368DF430AB433907 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 07FEEEDB11543A7DED420F04 /* Compound */; };
1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */; };
@@ -198,6 +199,7 @@
237FC70AA257B935F53316BA /* SessionVerificationControllerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */; };
238D561CA231339C6D4D06F3 /* ClientBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1C33355FFB0F0953C35036 /* ClientBuilder.swift */; };
241CDEFE23819867D9B39066 /* RoomChangePermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */; };
+ 2435DCCBD4513B9FD053CAC9 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = DD3C65634A34467CB407A061 /* target.yml */; };
244407B18B2F2D6466BA5961 /* RoomChangeRolesScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DFA1B7B088D033E0794B82 /* RoomChangeRolesScreenCoordinator.swift */; };
2447FADEF13225BB6227B977 /* VerificationBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D97BAF04AA150C0EF03021 /* VerificationBadge.swift */; };
24A1BBADAC43DC3F3A7347DA /* AnalyticsPromptScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */; };
@@ -223,6 +225,7 @@
2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7310D8DFE01AF45F0689C3AA /* Publisher.swift */; };
288408E6151D7BD3EBAA073A /* RoomScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = B343C5255FB408DDE853CFDF /* RoomScreenHook.swift */; };
28AB1614E749D1147A2AC6C2 /* CreateRoomScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2214C32EA81FA9168D923D4C /* CreateRoomScreenTests.swift */; };
+ 28E8C44DD6E39BEB2A1599C8 /* AccessibilityTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CABD320DE5566D133890B24 /* AccessibilityTestsAppCoordinator.swift */; };
292827744227DF61C930BDDB /* CreateRoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */; };
29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */; };
2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; };
@@ -516,7 +519,6 @@
63DCEBC1DD555E0D645B9E98 /* MapTilerURLBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1033290D99D5BBA1AF3560A /* MapTilerURLBuilderProtocol.swift */; };
63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; };
63FD7DBE7BBA149B4B8B99D7 /* TimelineControllerFactoryMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F5CC38803B8382D2C63222 /* TimelineControllerFactoryMock.swift */; };
- 642DF13C49ED4121C148230E /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; };
6448F8D1D3CA4CD27BB4CADD /* RoomMemberProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */; };
64AB99285DC4437C0DDE9585 /* MenuSheetLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49ABAB186CF00B15C5521D04 /* MenuSheetLabelStyle.swift */; };
64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 981663D961C94270FA035FD0 /* Alert.swift */; };
@@ -559,6 +561,7 @@
6AD722DD92E465E56D2885AB /* BugReportScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA919F521E9F0EE3638AFC85 /* BugReportScreen.swift */; };
6AEB650311F694A5702255C9 /* UserProfileScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B4932E4EFBC8FAC10972CD /* UserProfileScreenCoordinator.swift */; };
6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */; };
+ 6B3AB95A6993646A5081BFF9 /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43F773904F87FF5ADFE4DD1 /* TestablePreview.swift */; };
6B61F5B27412ED4BC2F9769C /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */; };
6B80C24A52411EAF10E06E96 /* SecurityAndPrivacyScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBADF8010C813D905C172CE /* SecurityAndPrivacyScreenModels.swift */; };
6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; };
@@ -847,6 +850,7 @@
A1672EF491FE6F3BBF7878BE /* test_apple_image.heic in Resources */ = {isa = PBXBuildFile; fileRef = BB576F4118C35E6B5124FA22 /* test_apple_image.heic */; };
A17FAD2EBC53E17B5FD384DB /* InviteUsersScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */; };
A1BA8D6BABAFA9BAAEAA3FFD /* NotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDD775CFD72DD2D3C8A8390 /* NotificationSettingsProxyProtocol.swift */; };
+ A1C8951A632AC5F350FE0A6C /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 932E4E8BB476283CBF219427 /* Test.swift */; };
A1DF0E1E526A981ED6D5DF44 /* UserIndicatorControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */; };
A216C83ADCF32BA5EF8A6FBC /* InviteUsersViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */; };
A2172B5A26976F9174228B8A /* AppHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */; };
@@ -888,6 +892,7 @@
A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */; };
A87DC550659C5176AC1829DE /* ElementTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7673F2B0B038FAB2A8D16AD /* ElementTextFieldStyle.swift */; };
A8FA7671948E3DF27F320026 /* BugReportFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */; };
+ A91D125414C3D9ABBABCF2F1 /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = 6690850AA47ECED7E1CAB345 /* KZFileWatchers */; };
A93661C962B12942C08864B6 /* WysiwygComposer in Frameworks */ = {isa = PBXBuildFile; productRef = CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */; };
A950C95855C474F75B30CA7B /* PollFormScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCDAB580109C09A6AA97AF7E /* PollFormScreenTests.swift */; };
A969147E0EEE0E27EE226570 /* MediaUploadPreviewScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */; };
@@ -1065,6 +1070,7 @@
CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; };
CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; };
CE3B7FC34FB2C279AAA5EA01 /* AVMetadataMachineReadableCodeObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */; };
+ CE4B342F9DD747CF4BEDB5AB /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43F773904F87FF5ADFE4DD1 /* TestablePreview.swift */; };
CE6F237360875D3D573FD0B2 /* RoomNotificationSettingsProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6B522BD637845AB9570B10 /* RoomNotificationSettingsProxy.swift */; };
CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */; };
CEAEA57B7665C8E790599A78 /* BlockedUsersScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 240610DF32F3213BEC5611D7 /* BlockedUsersScreenViewModelTests.swift */; };
@@ -1139,7 +1145,6 @@
DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = F012CB5EE3F2B67359F6CC52 /* target.yml */; };
E0B6A569AC3E81D233B43D60 /* SettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E625B0EB2F86B37C14EF7E6 /* SettingsScreenViewModel.swift */; };
E0C167D41A48EDB30B447DE3 /* VoiceMessageRecordingComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */; };
- E0FB26262689F04D66A949D7 /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; };
E14E469CD97550D0FC58F3CA /* CancellableTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */; };
E184FFAD32342D3D6E2F89AA /* PinnedEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */; };
E1A0752244567A25E376A2F4 /* AdvancedSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A1B80FE6E3BA72F9C748AD /* AdvancedSettingsScreenViewModel.swift */; };
@@ -1153,6 +1158,7 @@
E2DB696117BAEABAD5718023 /* MediaSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */; };
E2DDA49BD62F03F180A42E30 /* MapLibreStaticMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */; };
E313BDD2B8813144139B2E00 /* UserDiscoveryServiceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0287793F11C480E242B03DF5 /* UserDiscoveryServiceTest.swift */; };
+ E323A54F317604BDD6968D79 /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; };
E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */; };
E32A18802EB37EEE3EF7B965 /* GlobalSearchScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */; };
E362924A42934C9F0F97A956 /* OIDCConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69869844D2B6F5BD9AABF85 /* OIDCConfigurationProxy.swift */; };
@@ -1275,6 +1281,7 @@
F8F47CE757EE656905F01F2C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90DFF217B3D9D0941283278C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift */; };
F9788AE0B9EA19F1190ED14F /* StartChatScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B927A399A5418DA40A5CA15 /* StartChatScreenTests.swift */; };
F9842667B68DC6FA1F9ECCBB /* NSItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EFC8C634469F9262659C7 /* NSItemProvider.swift */; };
+ F996259EAE68664BC345C197 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D9DBE1C69F3A60D93B2203F /* Application.swift */; };
F99FB21EFC6D99D247FE7CBE /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DE8DC9B3FBA402117DC4C49F /* Kingfisher */; };
F9EA79092C18A8CFE4922DD2 /* PollFormScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */; };
FA2BBAE9FC5E2E9F960C0980 /* NavigationCoordinators.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */; };
@@ -1311,6 +1318,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ 1CE0B5D9ECEB44A4A32285B4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = AC22997D58D612146053154D /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = C0FAEB81CFD9776CD78CE489;
+ remoteInfo = ElementX;
+ };
4448BD77D7203616C4FAD26A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = AC22997D58D612146053154D /* Project object */;
@@ -1567,6 +1581,7 @@
227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = ""; };
22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenCell.swift; sourceTree = ""; };
2355398E4A55DA5A89128AD1 /* EncryptionKeyProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProvider.swift; sourceTree = ""; };
+ 2363DB6162BBCC511B67B527 /* AccessibilityTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = AccessibilityTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
23674BF78CE814366EBD8762 /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/InfoPlist.strings; sourceTree = ""; };
2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenCoordinator.swift; sourceTree = ""; };
23E6EB7960BC9D0F7396B3BD /* RoomChangeRolesScreenRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenRow.swift; sourceTree = ""; };
@@ -1628,6 +1643,7 @@
2D0946F77B696176E062D037 /* RoomMembersListScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenModels.swift; sourceTree = ""; };
2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemProxy.swift; sourceTree = ""; };
2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderTests.swift; sourceTree = ""; };
+ 2D9DBE1C69F3A60D93B2203F /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; };
2DA3DBE1A42EAFF93889FA04 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/SAS.strings; sourceTree = ""; };
2DA4F09CB613C54FDC73AE6A /* ThreadDecorator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadDecorator.swift; sourceTree = ""; };
2DB0E533508094156D8024C3 /* TimelineStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyler.swift; sourceTree = ""; };
@@ -1662,6 +1678,7 @@
34E0FA38BD473FFA6F1AB7A5 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = be; path = be.lproj/Localizable.stringsdict; sourceTree = ""; };
34ED3AB7E0287552A5648AB3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/InfoPlist.strings; sourceTree = ""; };
3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; };
+ 35A057BA9BE0F079784CD061 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; };
35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; };
35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; };
36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; };
@@ -1849,6 +1866,7 @@
5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenCoordinator.swift; sourceTree = ""; };
5C1F000589F2CEE6B03ECFAB /* TimelineMediaPreviewViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewViewModelTests.swift; sourceTree = ""; };
5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenCoordinator.swift; sourceTree = ""; };
+ 5CABD320DE5566D133890B24 /* AccessibilityTestsAppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityTestsAppCoordinator.swift; sourceTree = ""; };
5CDE60FEE95039CCCEEEE3B0 /* TimelineMediaPreviewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewController.swift; sourceTree = ""; };
5CEEAE1BFAACD6C96B6DB731 /* PHGPostHogProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogProtocol.swift; sourceTree = ""; };
5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = ""; };
@@ -2106,6 +2124,7 @@
922E498EB74CF6F5CC236F81 /* AdvancedSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenModels.swift; sourceTree = ""; };
92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCAuthenticationPresenter.swift; sourceTree = ""; };
92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScannerView.swift; sourceTree = ""; };
+ 932E4E8BB476283CBF219427 /* Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Test.swift; sourceTree = ""; };
9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = ""; };
933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaFrame.swift; sourceTree = ""; };
9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenModels.swift; sourceTree = ""; };
@@ -2222,6 +2241,7 @@
AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationAnnotation.swift; sourceTree = ""; };
AB07F03461023BC39C730922 /* PhishingDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhishingDetector.swift; sourceTree = ""; };
AB26D5444A4A7E095222DE8B /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.stringsdict"; sourceTree = ""; };
+ AB389C38BD41EB3E47092CFB /* AccessibilityTests.xctestplan */ = {isa = PBXFileReference; path = AccessibilityTests.xctestplan; sourceTree = ""; };
ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelProtocol.swift; sourceTree = ""; };
AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelTests.swift; sourceTree = ""; };
AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageCache.swift; sourceTree = ""; };
@@ -2266,7 +2286,6 @@
B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineItem.swift; sourceTree = ""; };
B172057567E049007A5C4D92 /* Strings+SAS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+SAS.swift"; sourceTree = ""; };
B18A454132A5A5247802821E /* TimelineMediaPreviewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewDataSource.swift; sourceTree = ""; };
- B1E227F34BE43B08E098796E /* TestablePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestablePreview.swift; sourceTree = ""; };
B1FDB0B87D925AE830E32621 /* ReportRoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportRoomScreenViewModel.swift; sourceTree = ""; };
B251F5B4511D1CA0BA8361FE /* CoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoordinatorProtocol.swift; sourceTree = ""; };
B2AD8A56CD37E23071A2F4BF /* PHGPostHogMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogMock.swift; sourceTree = ""; };
@@ -2482,6 +2501,7 @@
DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionModels.swift; sourceTree = ""; };
DCDAB580109C09A6AA97AF7E /* PollFormScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenTests.swift; sourceTree = ""; };
DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenModels.swift; sourceTree = ""; };
+ DD3C65634A34467CB407A061 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; };
DD955A0380C287C418F1A74D /* PhotoLibraryManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryManagerMock.swift; sourceTree = ""; };
DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceTests.swift; sourceTree = ""; };
DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenViewModelTests.swift; sourceTree = ""; };
@@ -2514,6 +2534,7 @@
E4103AB4340F2974D690A12A /* CallScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreen.swift; sourceTree = ""; };
E413F4CBD7BF0588F394A9DD /* RoomDetailsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModel.swift; sourceTree = ""; };
E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorModalView.swift; sourceTree = ""; };
+ E43F773904F87FF5ADFE4DD1 /* TestablePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestablePreview.swift; sourceTree = ""; };
E44E35AA87F49503E7B3BF6E /* AudioConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioConverter.swift; sourceTree = ""; };
E45EBAFF1A83538D54ABDF92 /* ServerSelectionScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModelTests.swift; sourceTree = ""; };
E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteURLParserTests.swift; sourceTree = ""; };
@@ -2617,6 +2638,7 @@
F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreen.swift; sourceTree = ""; };
F9E543072DE58E751F028998 /* TimelineProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxy.swift; sourceTree = ""; };
FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkTests.swift; sourceTree = ""; };
+ FA723686F23EF45E2B398FBC /* TestablePreviewsDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestablePreviewsDictionary.swift; sourceTree = ""; };
FA7BB497B2F539C17E88F6B7 /* NotificationSettingsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModelProtocol.swift; sourceTree = ""; };
FABAC5C4373B0EC24D399663 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/SAS.strings"; sourceTree = ""; };
FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreen.swift; sourceTree = ""; };
@@ -2721,6 +2743,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ EE2DAC14F8157479693D2705 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A91D125414C3D9ABBABCF2F1 /* KZFileWatchers in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
EE878EAA342710DB973E0A87 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -3445,6 +3475,15 @@
path = View;
sourceTree = "";
};
+ 35784B4A763838C0324B324A /* TestablePreview */ = {
+ isa = PBXGroup;
+ children = (
+ E43F773904F87FF5ADFE4DD1 /* TestablePreview.swift */,
+ FA723686F23EF45E2B398FBC /* TestablePreviewsDictionary.swift */,
+ );
+ path = TestablePreview;
+ sourceTree = "";
+ };
358B1920EA0C8129198FBA4F /* View */ = {
isa = PBXGroup;
children = (
@@ -3621,6 +3660,7 @@
A4852B57D55D71EEBFCD931D /* UnitTests */,
1803CD2B96BF06009334BB61 /* PreviewTests */,
C0FAC17D4DD7D3A502822550 /* UITests */,
+ D7117C32909844BCF5AF30BA /* AccessibilityTests */,
8A9C09B6A392465E03B8D1B1 /* IntegrationTests */,
A8002CB4F20B6282850A614C /* DevelopmentAssets */,
2197234282B4BC0CE79AAC74 /* Secrets */,
@@ -4141,6 +4181,16 @@
path = SecureBackupLogoutConfirmationScreen;
sourceTree = "";
};
+ 63FCFB02914E796299B25213 /* SupportingFiles */ = {
+ isa = PBXGroup;
+ children = (
+ AB389C38BD41EB3E47092CFB /* AccessibilityTests.xctestplan */,
+ 35A057BA9BE0F079784CD061 /* Info.plist */,
+ DD3C65634A34467CB407A061 /* target.yml */,
+ );
+ path = SupportingFiles;
+ sourceTree = "";
+ };
6709362D60732DED2069AE0F /* MediaPlayer */ = {
isa = PBXGroup;
children = (
@@ -4184,6 +4234,7 @@
681566846AF307E9BA4C72C6 /* Products */ = {
isa = PBXGroup;
children = (
+ 2363DB6162BBCC511B67B527 /* AccessibilityTests.xctest */,
4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */,
9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */,
0D8F620C8B314840D8602E3F /* NSE.appex */,
@@ -4540,6 +4591,14 @@
path = View;
sourceTree = "";
};
+ 79654D131C1B234A7D034532 /* AccessibilityTests */ = {
+ isa = PBXGroup;
+ children = (
+ 5CABD320DE5566D133890B24 /* AccessibilityTestsAppCoordinator.swift */,
+ );
+ path = AccessibilityTests;
+ sourceTree = "";
+ };
79E560F5113ED25D172E550C /* Media */ = {
isa = PBXGroup;
children = (
@@ -5442,7 +5501,6 @@
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */,
FE5CD2993048222B64C45006 /* SDKListener.swift */,
4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */,
- B1E227F34BE43B08E098796E /* TestablePreview.swift */,
1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */,
35FA991289149D31F4286747 /* UserPreference.swift */,
7431C962E314ADAE38B6D708 /* Analytics */,
@@ -5456,6 +5514,7 @@
9C4193C4524B35FD6B94B5A9 /* Pills */,
25852CD5316875417111E5CA /* Progress */,
052CC920F473C10B509F9FC1 /* SwiftUI */,
+ 35784B4A763838C0324B324A /* TestablePreview */,
B687E3E8C23415A06A3D5C65 /* UserIndicator */,
A33CE1B72A29E3931CBEC2A5 /* VoiceMessage */,
);
@@ -5701,6 +5760,15 @@
path = RoomPollsHistoryScreen;
sourceTree = "";
};
+ D7117C32909844BCF5AF30BA /* AccessibilityTests */ = {
+ isa = PBXGroup;
+ children = (
+ EB9C851423AA9BC8CEC381DC /* Sources */,
+ 63FCFB02914E796299B25213 /* SupportingFiles */,
+ );
+ path = AccessibilityTests;
+ sourceTree = "";
+ };
D8388454B5909D862CAC78F7 /* RoomChangeRolesScreen */ = {
isa = PBXGroup;
children = (
@@ -5908,6 +5976,7 @@
E59565F441830B19DBAE567C /* Screens */,
C0937E3B06A8F0E2DB7C8241 /* Other */,
2ECFF6B05DAA37EB10DBF7E8 /* UITests */,
+ 79654D131C1B234A7D034532 /* AccessibilityTests */,
22F9F1514B91803BB4B88894 /* AppHooks */,
337015ADFBA3AB96660DB3A6 /* Generated */,
31CE4DA53232AA534057F912 /* Mocks */,
@@ -5980,6 +6049,15 @@
path = AccountSettings;
sourceTree = "";
};
+ EB9C851423AA9BC8CEC381DC /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 2D9DBE1C69F3A60D93B2203F /* Application.swift */,
+ 932E4E8BB476283CBF219427 /* Test.swift */,
+ );
+ path = Sources;
+ sourceTree = "";
+ };
EC4545C7E37E8294D3FE6800 /* StartChatScreen */ = {
isa = PBXGroup;
children = (
@@ -6291,6 +6369,27 @@
productReference = D95E8C0EFEC0C6F96EDAA71A /* PreviewTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
+ C0C687DE1D270F9895FEE186 /* AccessibilityTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8FFA8C81E8F740B7AC0183EC /* Build configuration list for PBXNativeTarget "AccessibilityTests" */;
+ buildPhases = (
+ 94540A814D43C5F35B910D5E /* Sources */,
+ E8235B7CF8A765A03DC263A1 /* Resources */,
+ EE2DAC14F8157479693D2705 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 856923B8570E40A97E26EEDE /* PBXTargetDependency */,
+ );
+ name = AccessibilityTests;
+ packageProductDependencies = (
+ 6690850AA47ECED7E1CAB345 /* KZFileWatchers */,
+ );
+ productName = AccessibilityTests;
+ productReference = 2363DB6162BBCC511B67B527 /* AccessibilityTests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
C0FAEB81CFD9776CD78CE489 /* ElementX */ = {
isa = PBXNativeTarget;
buildConfigurationList = B15427F8699AD5A5FC75C17E /* Build configuration list for PBXNativeTarget "ElementX" */;
@@ -6298,6 +6397,7 @@
A7130911BCB2DF3D249A1836 /* 🛠 SwiftGen */,
7F26850DA7BC749F6FC41586 /* 🧙 Sourcery - Generate mocks */,
024F73AD10ACB163505ABE1E /* 🧙 Sourcery - Generate preview tests */,
+ B48A38232A774CE14E6CAFC9 /* 🧙 Sourcery - Generate Accessibility Tests */,
9797D588420FCBBC228A63C9 /* Sources */,
215E1D91B98672C856F559D0 /* Resources */,
EE878EAA342710DB973E0A87 /* Frameworks */,
@@ -6423,6 +6523,10 @@
7A17BE29BAC81ADBAC6349D9 = {
DevelopmentTeam = 7J4U792NQT;
};
+ C0C687DE1D270F9895FEE186 = {
+ DevelopmentTeam = 7J4U792NQT;
+ TestTargetID = C0FAEB81CFD9776CD78CE489;
+ };
C0FAEB81CFD9776CD78CE489 = {
DevelopmentTeam = "$(DEVELOPMENT_TEAM)";
};
@@ -6513,6 +6617,7 @@
projectDirPath = "";
projectRoot = "";
targets = (
+ C0C687DE1D270F9895FEE186 /* AccessibilityTests */,
C0FAEB81CFD9776CD78CE489 /* ElementX */,
D3DB351B7FBE0F49649171FC /* IntegrationTests */,
FEB53A5BC378C913769656D8 /* NSE */,
@@ -6624,6 +6729,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ E8235B7CF8A765A03DC263A1 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2435DCCBD4513B9FD053CAC9 /* target.yml in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -6741,6 +6854,25 @@
shellPath = /bin/sh;
shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftformat >/dev/null; then\n swiftformat --lint --lenient \"$PROJECT_DIR\"\nelse\n echo \"warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat\"\nfi\n";
};
+ B48A38232A774CE14E6CAFC9 /* 🧙 Sourcery - Generate Accessibility Tests */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "🧙 Sourcery - Generate Accessibility Tests";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which sourcery >/dev/null; then\n sourcery --config Tools/Sourcery/TestablePreviewsDictionary.yml\nelse\n echo \"warning: Sourcery not installed, run swift run tools setup-project\"\nfi\n";
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -6805,7 +6937,7 @@
6EC7A40A537CFB3D526A111C /* Strings.swift in Sources */,
88A3FBBC3D67996863DB9CAF /* TargetConfiguration.swift in Sources */,
719E7AAD1F8E68F68F30FECD /* Task.swift in Sources */,
- E0FB26262689F04D66A949D7 /* TestablePreview.swift in Sources */,
+ CE4B342F9DD747CF4BEDB5AB /* TestablePreview.swift in Sources */,
AC3C3D6D4AD31F13EE987390 /* TraceLogPack.swift in Sources */,
B81840E45D8746A4692DA774 /* Tracing.swift in Sources */,
DDB47D29C6865669288BF87C /* UIFont+AttributedStringBuilder.m in Sources */,
@@ -6990,6 +7122,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 94540A814D43C5F35B910D5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F996259EAE68664BC345C197 /* Application.swift in Sources */,
+ A1C8951A632AC5F350FE0A6C /* Test.swift in Sources */,
+ E323A54F317604BDD6968D79 /* UITestsSignalling.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
9797D588420FCBBC228A63C9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -6997,6 +7139,7 @@
41F553349AF44567184822D8 /* APNSPayload.swift in Sources */,
CE3B7FC34FB2C279AAA5EA01 /* AVMetadataMachineReadableCodeObject.swift in Sources */,
70394ECD2DCC70741538620D /* AccessibilityIdentifiers.swift in Sources */,
+ 28E8C44DD6E39BEB2A1599C8 /* AccessibilityTestsAppCoordinator.swift in Sources */,
09E1A358EA4205480AEF4698 /* AdvancedSettingsScreen.swift in Sources */,
34ADC506C929D10B138EBA51 /* AdvancedSettingsScreenCoordinator.swift in Sources */,
2BEDEA4851E1DF901779362C /* AdvancedSettingsScreenModels.swift in Sources */,
@@ -7766,7 +7909,8 @@
CCBEC2100CAF2EEBE9DB4156 /* TemplateScreenModels.swift in Sources */,
275EDE8849A2AC1D9309ED7C /* TemplateScreenViewModel.swift in Sources */,
2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */,
- 642DF13C49ED4121C148230E /* TestablePreview.swift in Sources */,
+ 6B3AB95A6993646A5081BFF9 /* TestablePreview.swift in Sources */,
+ 1ECE584D2CFA0FEF0ADE458C /* TestablePreviewsDictionary.swift in Sources */,
887AC93C523AEFB640EA5EC8 /* TextBasedRoomTimelineItem.swift in Sources */,
4FE688FE9375B2FBF424146A /* TextBasedRoomTimelineViewProtocol.swift in Sources */,
BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */,
@@ -7991,6 +8135,11 @@
target = 19F0C845D67E9BEA4BE7133E /* ShareExtension */;
targetProxy = 52A426E590105174D83B9532 /* PBXContainerItemProxy */;
};
+ 856923B8570E40A97E26EEDE /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = C0FAEB81CFD9776CD78CE489 /* ElementX */;
+ targetProxy = 1CE0B5D9ECEB44A4A32285B4 /* PBXContainerItemProxy */;
+ };
8E24DC048A099AAFEE13B4F5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C0FAEB81CFD9776CD78CE489 /* ElementX */;
@@ -8166,6 +8315,48 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
+ 2F9917BC52CB6F9FFACE9D64 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ INFOPLIST_FILE = AccessibilityTests/SupportingFiles/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ OTHER_SWIFT_FLAGS = (
+ "-DRELEASE",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.accessibility.tests";
+ PRODUCT_NAME = AccessibilityTests;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = ElementX;
+ };
+ name = Release;
+ };
+ 33096BC465A038B6B6D76B7A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ INFOPLIST_FILE = AccessibilityTests/SupportingFiles/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ OTHER_SWIFT_FLAGS = (
+ "-DDEBUG",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.accessibility.tests";
+ PRODUCT_NAME = AccessibilityTests;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = ElementX;
+ };
+ name = Debug;
+ };
4CB921EC997F763064B8E436 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -8644,6 +8835,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
+ 8FFA8C81E8F740B7AC0183EC /* Build configuration list for PBXNativeTarget "AccessibilityTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33096BC465A038B6B6D76B7A /* Debug */,
+ 2F9917BC52CB6F9FFACE9D64 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
A60414DDC2A95B206C91D4A4 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -9058,6 +9258,11 @@
package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */;
productName = MatrixRustSDK;
};
+ 6690850AA47ECED7E1CAB345 /* KZFileWatchers */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 395DE6AE429B7ACC7C7FE31D /* XCRemoteSwiftPackageReference "KZFileWatchers" */;
+ productName = KZFileWatchers;
+ };
67E7A6F388D3BF85767609D9 /* Sentry */ = {
isa = XCSwiftPackageProductDependency;
package = A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */;
diff --git a/ElementX.xcodeproj/xcshareddata/xcschemes/AccessibilityTests.xcscheme b/ElementX.xcodeproj/xcshareddata/xcschemes/AccessibilityTests.xcscheme
new file mode 100644
index 000000000..3f2e7e6f2
--- /dev/null
+++ b/ElementX.xcodeproj/xcshareddata/xcschemes/AccessibilityTests.xcscheme
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ElementX/Sources/AccessibilityTests/AccessibilityTestsAppCoordinator.swift b/ElementX/Sources/AccessibilityTests/AccessibilityTestsAppCoordinator.swift
new file mode 100644
index 000000000..3f0dd0c4e
--- /dev/null
+++ b/ElementX/Sources/AccessibilityTests/AccessibilityTestsAppCoordinator.swift
@@ -0,0 +1,155 @@
+//
+// Copyright 2025 New Vector Ltd.
+//
+// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
+// Please see LICENSE files in the repository root for full details.
+//
+
+import Combine
+import SwiftUI
+
+class AccessibilityTestsAppCoordinator: AppCoordinatorProtocol {
+ var windowManager: any SecureWindowManagerProtocol
+
+ func handleDeepLink(_ url: URL, isExternalURL: Bool) -> Bool {
+ fatalError("Not implemented")
+ }
+
+ func handlePotentialPhishingAttempt(url: URL, openURLAction: @escaping (URL) -> Void) -> Bool {
+ fatalError("Not implemented")
+ }
+
+ func handleUserActivity(_ userActivity: NSUserActivity) {
+ fatalError("Not implemented")
+ }
+
+ private let previewsWrapper: PreviewsWrapper
+
+ private var cancellables = Set()
+
+ init(appDelegate: AppDelegate) {
+ windowManager = WindowManager(appDelegate: appDelegate)
+ // disabling View animations
+ UIView.setAnimationsEnabled(false)
+
+ MXLog.configure(currentTarget: "accessibility-tests")
+
+ ServiceLocator.shared.register(userIndicatorController: UserIndicatorController())
+
+ AppSettings.configureWithSuiteName("io.element.elementx.accessibilitytests")
+ AppSettings.resetAllSettings()
+ ServiceLocator.shared.register(appSettings: AppSettings())
+ ServiceLocator.shared.register(bugReportService: BugReportServiceMock(.init()))
+
+ let analyticsClient = AnalyticsClientMock()
+ analyticsClient.isRunning = false
+ ServiceLocator.shared.register(analytics: AnalyticsService(client: analyticsClient,
+ appSettings: ServiceLocator.shared.settings))
+
+ guard let name = ProcessInfo.accessibilityViewID,
+ let previewType = TestablePreviewsDictionary.dictionary[name] else {
+ fatalError("Unable to launch with unknown screen.")
+ }
+ previewsWrapper = .init(name: name, previews: previewType._allPreviews)
+
+ setupSignalling()
+ }
+
+ func toPresentable() -> AnyView {
+ AnyView(PreviewsWrapperView(wrapper: previewsWrapper))
+ }
+
+ private func setupSignalling() {
+ do {
+ let client = try UITestsSignalling.Client(mode: .app)
+ client.signals.sink { [weak self] signal in
+ guard let self else { return }
+ switch signal {
+ case .accessibilityAudit(let auditSignal):
+ switch auditSignal {
+ case .nextPreview:
+ Task { [weak self] in
+ guard let self else { return }
+ await previewsWrapper.updateCurrentIndex()
+ do {
+ guard !previewsWrapper.isDone else {
+ try client.send(.accessibilityAudit(.noMorePreviews))
+ return
+ }
+
+ try client.send(.accessibilityAudit(.nextPreviewReady(name: previewsWrapper.previewName)))
+ } catch {
+ fatalError("Failed sending signal: \(signal)")
+ }
+ }
+ default:
+ break
+ }
+ default:
+ break
+ }
+ }
+ .store(in: &cancellables)
+ } catch {
+ fatalError("Unable to start client signalling")
+ }
+ }
+}
+
+struct PreviewsWrapperView: View {
+ let wrapper: PreviewsWrapper
+
+ var body: some View {
+ if wrapper.currentIndex < 0 || wrapper.isDone {
+ EmptyView()
+ } else {
+ wrapper.currentPreview.content
+ .id(wrapper.previewName)
+ }
+ }
+}
+
+@Observable final class PreviewsWrapper {
+ private let name: String
+ private let previews: [_Preview]
+ private(set) var currentIndex = -1
+ var currentPreview: _Preview { previews[currentIndex] }
+
+ private(set) var isDone = false
+
+ var previewName: String {
+ "\(name)-\(currentPreview.displayName ?? String(currentIndex))"
+ }
+
+ init(name: String, previews: [_Preview]) {
+ self.name = name
+ self.previews = previews
+ }
+
+ @MainActor
+ func updateCurrentIndex() async {
+ let newIndex = currentIndex + 1
+ guard newIndex < previews.count else {
+ isDone = true
+ return
+ }
+ let newPreview = previews[newIndex]
+ var fulfillmentSource: SnapshotFulfillmentPreferenceKey.Source?
+ let preferenceReadingView = newPreview.content.onPreferenceChange(SnapshotFulfillmentPreferenceKey.self) { fulfillmentSource = $0?.source }
+
+ // Render an image of the view in order to trigger the preference updates to occur.
+ let imageRenderer = ImageRenderer(content: preferenceReadingView)
+ _ = imageRenderer.uiImage
+
+ switch fulfillmentSource {
+ case .publisher(let publisher):
+ _ = await publisher.values.first { $0 == true }
+ case .stream(let stream):
+ _ = await stream.first { $0 == true }
+ case .none:
+ break
+ }
+
+ currentIndex = newIndex
+ }
+}
diff --git a/ElementX/Sources/Application/Application.swift b/ElementX/Sources/Application/Application.swift
index 4ebf94f36..48fba3d74 100644
--- a/ElementX/Sources/Application/Application.swift
+++ b/ElementX/Sources/Application/Application.swift
@@ -19,6 +19,8 @@ struct Application: App {
appCoordinator = UITestsAppCoordinator(appDelegate: appDelegate)
} else if ProcessInfo.isRunningUnitTests {
appCoordinator = UnitTestsAppCoordinator(appDelegate: appDelegate)
+ } else if ProcessInfo.isRunningAccessibilityTests {
+ appCoordinator = AccessibilityTestsAppCoordinator(appDelegate: appDelegate)
} else {
appCoordinator = AppCoordinator(appDelegate: appDelegate)
}
diff --git a/ElementX/Sources/Other/Extensions/ProcessInfo.swift b/ElementX/Sources/Other/Extensions/ProcessInfo.swift
index 6990c3548..c90164df9 100644
--- a/ElementX/Sources/Other/Extensions/ProcessInfo.swift
+++ b/ElementX/Sources/Other/Extensions/ProcessInfo.swift
@@ -33,10 +33,18 @@ extension ProcessInfo {
false
#endif
}
+
+ static var isRunningAccessibilityTests: Bool {
+ #if DEBUG
+ processInfo.environment["ACCESSIBILITY_VIEW"] != nil
+ #else
+ false
+ #endif
+ }
/// Flag indicating whether the app is running the UI tests or unit tests.
static var isRunningTests: Bool {
- isRunningUITests || isRunningUnitTests || isRunningIntegrationTests
+ isRunningUITests || isRunningUnitTests || isRunningIntegrationTests || isRunningAccessibilityTests
}
/// The identifier of the screen to be loaded when running UI tests.
@@ -48,6 +56,15 @@ extension ProcessInfo {
#endif
}
+ /// The identifier of the preview that will be accessibility tested
+ static var accessibilityViewID: String? {
+ #if DEBUG
+ processInfo.environment["ACCESSIBILITY_VIEW"]
+ #else
+ nil
+ #endif
+ }
+
static var shouldDisableTimelineAccessibility: Bool {
guard isRunningUITests else {
return false
diff --git a/ElementX/Sources/Other/TestablePreview.swift b/ElementX/Sources/Other/TestablePreview/TestablePreview.swift
similarity index 100%
rename from ElementX/Sources/Other/TestablePreview.swift
rename to ElementX/Sources/Other/TestablePreview/TestablePreview.swift
diff --git a/ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift b/ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift
new file mode 100644
index 000000000..4e58b869e
--- /dev/null
+++ b/ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift
@@ -0,0 +1,205 @@
+// Generated using Sourcery 2.2.7 — https://github.com/krzysztofzablocki/Sourcery
+// DO NOT EDIT
+
+// swiftlint:disable all
+// swiftformat:disable all
+
+import SwiftUI
+
+
+enum TestablePreviewsDictionary {
+ static let dictionary: [String: any PreviewProvider.Type] = [
+ "AdvancedSettingsScreen_Previews" : AdvancedSettingsScreen_Previews.self,
+ "AnalyticsPromptScreen_Previews" : AnalyticsPromptScreen_Previews.self,
+ "AnalyticsSettingsScreen_Previews" : AnalyticsSettingsScreen_Previews.self,
+ "AppLockScreen_Previews" : AppLockScreen_Previews.self,
+ "AppLockSetupBiometricsScreen_Previews" : AppLockSetupBiometricsScreen_Previews.self,
+ "AppLockSetupPINScreen_Previews" : AppLockSetupPINScreen_Previews.self,
+ "AppLockSetupSettingsScreen_Previews" : AppLockSetupSettingsScreen_Previews.self,
+ "AudioMediaEventsTimelineView_Previews" : AudioMediaEventsTimelineView_Previews.self,
+ "AudioRoomTimelineView_Previews" : AudioRoomTimelineView_Previews.self,
+ "AuthenticationStartScreen_Previews" : AuthenticationStartScreen_Previews.self,
+ "AvatarHeaderView_Previews" : AvatarHeaderView_Previews.self,
+ "BadgeLabel_Previews" : BadgeLabel_Previews.self,
+ "BigIcon_Previews" : BigIcon_Previews.self,
+ "BlockedUsersScreen_Previews" : BlockedUsersScreen_Previews.self,
+ "BugReportScreen_Previews" : BugReportScreen_Previews.self,
+ "CallInviteRoomTimelineView_Previews" : CallInviteRoomTimelineView_Previews.self,
+ "CallNotificationRoomTimelineView_Previews" : CallNotificationRoomTimelineView_Previews.self,
+ "CollapsibleRoomTimelineView_Previews" : CollapsibleRoomTimelineView_Previews.self,
+ "CompletionSuggestion_Previews" : CompletionSuggestion_Previews.self,
+ "ComposerToolbar_Previews" : ComposerToolbar_Previews.self,
+ "CreateRoom_Previews" : CreateRoom_Previews.self,
+ "DeactivateAccountScreen_Previews" : DeactivateAccountScreen_Previews.self,
+ "DeclineAndBlockScreen_Previews" : DeclineAndBlockScreen_Previews.self,
+ "EditRoomAddressScreen_Previews" : EditRoomAddressScreen_Previews.self,
+ "ElementTextFieldStyle_Previews" : ElementTextFieldStyle_Previews.self,
+ "EmojiPickerScreenHeaderView_Previews" : EmojiPickerScreenHeaderView_Previews.self,
+ "EmojiPickerScreen_Previews" : EmojiPickerScreen_Previews.self,
+ "EmoteRoomTimelineView_Previews" : EmoteRoomTimelineView_Previews.self,
+ "EncryptedRoomTimelineView_Previews" : EncryptedRoomTimelineView_Previews.self,
+ "EncryptionResetPasswordScreen_Previews" : EncryptionResetPasswordScreen_Previews.self,
+ "EncryptionResetScreen_Previews" : EncryptionResetScreen_Previews.self,
+ "EstimatedWaveformView_Previews" : EstimatedWaveformView_Previews.self,
+ "FileMediaEventsTimelineView_Previews" : FileMediaEventsTimelineView_Previews.self,
+ "FileRoomTimelineView_Previews" : FileRoomTimelineView_Previews.self,
+ "FormButtonStyles_Previews" : FormButtonStyles_Previews.self,
+ "FormattedBodyText_Previews" : FormattedBodyText_Previews.self,
+ "FormattingToolbar_Previews" : FormattingToolbar_Previews.self,
+ "FullscreenDialog_Previews" : FullscreenDialog_Previews.self,
+ "GlobalSearchScreenListRow_Previews" : GlobalSearchScreenListRow_Previews.self,
+ "GlobalSearchScreen_Previews" : GlobalSearchScreen_Previews.self,
+ "HighlightedTimelineItemModifier_Previews" : HighlightedTimelineItemModifier_Previews.self,
+ "HomeScreenEmptyStateView_Previews" : HomeScreenEmptyStateView_Previews.self,
+ "HomeScreenInviteCell_Previews" : HomeScreenInviteCell_Previews.self,
+ "HomeScreenKnockedCell_Previews" : HomeScreenKnockedCell_Previews.self,
+ "HomeScreenRecoveryKeyConfirmationBanner_Previews" : HomeScreenRecoveryKeyConfirmationBanner_Previews.self,
+ "HomeScreenRoomCell_Previews" : HomeScreenRoomCell_Previews.self,
+ "HomeScreen_Previews" : HomeScreen_Previews.self,
+ "IdentityConfirmationScreen_Previews" : IdentityConfirmationScreen_Previews.self,
+ "IdentityConfirmedScreen_Previews" : IdentityConfirmedScreen_Previews.self,
+ "ImageMediaEventsTimelineView_Previews" : ImageMediaEventsTimelineView_Previews.self,
+ "ImageRoomTimelineView_Previews" : ImageRoomTimelineView_Previews.self,
+ "InviteUsersScreenSelectedItem_Previews" : InviteUsersScreenSelectedItem_Previews.self,
+ "InviteUsersScreen_Previews" : InviteUsersScreen_Previews.self,
+ "JoinRoomByAddressView_Previews" : JoinRoomByAddressView_Previews.self,
+ "JoinRoomScreen_Previews" : JoinRoomScreen_Previews.self,
+ "KnockRequestCell_Previews" : KnockRequestCell_Previews.self,
+ "KnockRequestsBannerView_Previews" : KnockRequestsBannerView_Previews.self,
+ "KnockRequestsListEmptyStateView_Previews" : KnockRequestsListEmptyStateView_Previews.self,
+ "KnockRequestsListScreen_Previews" : KnockRequestsListScreen_Previews.self,
+ "LegalInformationScreen_Previews" : LegalInformationScreen_Previews.self,
+ "LoadableImage_Previews" : LoadableImage_Previews.self,
+ "LocationMarkerView_Previews" : LocationMarkerView_Previews.self,
+ "LocationRoomTimelineView_Previews" : LocationRoomTimelineView_Previews.self,
+ "LoginScreen_Previews" : LoginScreen_Previews.self,
+ "LongPressWithFeedback_Previews" : LongPressWithFeedback_Previews.self,
+ "ManageRoomMemberSheetView_Previews" : ManageRoomMemberSheetView_Previews.self,
+ "MapLibreStaticMapView_Previews" : MapLibreStaticMapView_Previews.self,
+ "MatrixUserPermalink_Previews" : MatrixUserPermalink_Previews.self,
+ "MediaEventsTimelineScreen_Previews" : MediaEventsTimelineScreen_Previews.self,
+ "MediaUploadPreviewScreen_Previews" : MediaUploadPreviewScreen_Previews.self,
+ "MentionSuggestionItemView_Previews" : MentionSuggestionItemView_Previews.self,
+ "MessageComposerTextField_Previews" : MessageComposerTextField_Previews.self,
+ "MessageComposer_Previews" : MessageComposer_Previews.self,
+ "MessageForwardingScreen_Previews" : MessageForwardingScreen_Previews.self,
+ "MessageText_Previews" : MessageText_Previews.self,
+ "NoticeRoomTimelineView_Previews" : NoticeRoomTimelineView_Previews.self,
+ "NotificationPermissionsScreen_Previews" : NotificationPermissionsScreen_Previews.self,
+ "NotificationSettingsEditScreenRoomCell_Previews" : NotificationSettingsEditScreenRoomCell_Previews.self,
+ "NotificationSettingsEditScreen_Previews" : NotificationSettingsEditScreen_Previews.self,
+ "NotificationSettingsScreen_Previews" : NotificationSettingsScreen_Previews.self,
+ "PINTextField_Previews" : PINTextField_Previews.self,
+ "PaginationIndicatorRoomTimelineView_Previews" : PaginationIndicatorRoomTimelineView_Previews.self,
+ "PillViewOnBubble_Previews" : PillViewOnBubble_Previews.self,
+ "PillView_Previews" : PillView_Previews.self,
+ "PinnedEventsTimelineScreen_Previews" : PinnedEventsTimelineScreen_Previews.self,
+ "PinnedItemsBannerView_Previews" : PinnedItemsBannerView_Previews.self,
+ "PinnedItemsIndicatorView_Previews" : PinnedItemsIndicatorView_Previews.self,
+ "PlaceholderAvatarImage_Previews" : PlaceholderAvatarImage_Previews.self,
+ "PlaceholderScreen_Previews" : PlaceholderScreen_Previews.self,
+ "PollFormScreen_Previews" : PollFormScreen_Previews.self,
+ "PollOptionView_Previews" : PollOptionView_Previews.self,
+ "PollRoomTimelineView_Previews" : PollRoomTimelineView_Previews.self,
+ "PollView_Previews" : PollView_Previews.self,
+ "QRCodeLoginScreen_Previews" : QRCodeLoginScreen_Previews.self,
+ "ReactionsSummaryView_Previews" : ReactionsSummaryView_Previews.self,
+ "ReadMarkerRoomTimelineView_Previews" : ReadMarkerRoomTimelineView_Previews.self,
+ "ReadReceiptCell_Previews" : ReadReceiptCell_Previews.self,
+ "ReadReceiptsSummaryView_Previews" : ReadReceiptsSummaryView_Previews.self,
+ "RedactedRoomTimelineView_Previews" : RedactedRoomTimelineView_Previews.self,
+ "ReportContentScreen_Previews" : ReportContentScreen_Previews.self,
+ "ReportRoomScreen_Previews" : ReportRoomScreen_Previews.self,
+ "ResolveVerifiedUserSendFailureScreen_Previews" : ResolveVerifiedUserSendFailureScreen_Previews.self,
+ "RoomAttachmentPicker_Previews" : RoomAttachmentPicker_Previews.self,
+ "RoomAvatarImage_Previews" : RoomAvatarImage_Previews.self,
+ "RoomChangePermissionsScreen_Previews" : RoomChangePermissionsScreen_Previews.self,
+ "RoomChangeRolesScreenRow_Previews" : RoomChangeRolesScreenRow_Previews.self,
+ "RoomChangeRolesScreenSelectedItem_Previews" : RoomChangeRolesScreenSelectedItem_Previews.self,
+ "RoomChangeRolesScreen_Previews" : RoomChangeRolesScreen_Previews.self,
+ "RoomDetailsEditScreen_Previews" : RoomDetailsEditScreen_Previews.self,
+ "RoomDetailsScreen_Previews" : RoomDetailsScreen_Previews.self,
+ "RoomDirectorySearchCell_Previews" : RoomDirectorySearchCell_Previews.self,
+ "RoomDirectorySearchScreen_Previews" : RoomDirectorySearchScreen_Previews.self,
+ "RoomHeaderView_Previews" : RoomHeaderView_Previews.self,
+ "RoomInviterLabel_Previews" : RoomInviterLabel_Previews.self,
+ "RoomListFilterView_Previews" : RoomListFilterView_Previews.self,
+ "RoomListFiltersEmptyStateView_Previews" : RoomListFiltersEmptyStateView_Previews.self,
+ "RoomListFiltersView_Previews" : RoomListFiltersView_Previews.self,
+ "RoomMemberDetailsScreen_Previews" : RoomMemberDetailsScreen_Previews.self,
+ "RoomMembersListMemberCell_Previews" : RoomMembersListMemberCell_Previews.self,
+ "RoomMembersListScreen_Previews" : RoomMembersListScreen_Previews.self,
+ "RoomNotificationSettingsCustomSectionView_Previews" : RoomNotificationSettingsCustomSectionView_Previews.self,
+ "RoomNotificationSettingsScreen_Previews" : RoomNotificationSettingsScreen_Previews.self,
+ "RoomNotificationSettingsUserDefinedScreen_Previews" : RoomNotificationSettingsUserDefinedScreen_Previews.self,
+ "RoomPollsHistoryScreen_Previews" : RoomPollsHistoryScreen_Previews.self,
+ "RoomRolesAndPermissionsScreen_Previews" : RoomRolesAndPermissionsScreen_Previews.self,
+ "RoomScreenFooterView_Previews" : RoomScreenFooterView_Previews.self,
+ "RoomScreen_Previews" : RoomScreen_Previews.self,
+ "RoomSelectionScreen_Previews" : RoomSelectionScreen_Previews.self,
+ "SFNumberedListView_Previews" : SFNumberedListView_Previews.self,
+ "SecureBackupKeyBackupScreen_Previews" : SecureBackupKeyBackupScreen_Previews.self,
+ "SecureBackupLogoutConfirmationScreen_Previews" : SecureBackupLogoutConfirmationScreen_Previews.self,
+ "SecureBackupRecoveryKeyScreen_Previews" : SecureBackupRecoveryKeyScreen_Previews.self,
+ "SecureBackupScreen_Previews" : SecureBackupScreen_Previews.self,
+ "SecurityAndPrivacyScreen_Previews" : SecurityAndPrivacyScreen_Previews.self,
+ "SendInviteConfirmationView_Previews" : SendInviteConfirmationView_Previews.self,
+ "SeparatorMediaEventsTimelineView_Previews" : SeparatorMediaEventsTimelineView_Previews.self,
+ "SeparatorRoomTimelineView_Previews" : SeparatorRoomTimelineView_Previews.self,
+ "ServerConfirmationScreen_Previews" : ServerConfirmationScreen_Previews.self,
+ "ServerSelection_Previews" : ServerSelection_Previews.self,
+ "SessionVerificationRequestDetailsView_Previews" : SessionVerificationRequestDetailsView_Previews.self,
+ "SessionVerification_Previews" : SessionVerification_Previews.self,
+ "SettingsScreen_Previews" : SettingsScreen_Previews.self,
+ "ShimmerOverlay_Previews" : ShimmerOverlay_Previews.self,
+ "SoftLogoutScreen_Previews" : SoftLogoutScreen_Previews.self,
+ "SplashScreen_Previews" : SplashScreen_Previews.self,
+ "StackedAvatarsView_Previews" : StackedAvatarsView_Previews.self,
+ "StartChatScreen_Previews" : StartChatScreen_Previews.self,
+ "StateRoomTimelineView_Previews" : StateRoomTimelineView_Previews.self,
+ "StaticLocationScreenViewer_Previews" : StaticLocationScreenViewer_Previews.self,
+ "StickerRoomTimelineView_Previews" : StickerRoomTimelineView_Previews.self,
+ "SwipeRightAction_Previews" : SwipeRightAction_Previews.self,
+ "SwipeToReplyView_Previews" : SwipeToReplyView_Previews.self,
+ "TextRoomTimelineView_Previews" : TextRoomTimelineView_Previews.self,
+ "ThreadDecorator_Previews" : ThreadDecorator_Previews.self,
+ "TimelineDeliveryStatusView_Previews" : TimelineDeliveryStatusView_Previews.self,
+ "TimelineItemBubbledStylerView_Previews" : TimelineItemBubbledStylerView_Previews.self,
+ "TimelineItemDebugView_Previews" : TimelineItemDebugView_Previews.self,
+ "TimelineItemMenu_Previews" : TimelineItemMenu_Previews.self,
+ "TimelineItemSendInfoLabel_Previews" : TimelineItemSendInfoLabel_Previews.self,
+ "TimelineItemStyler_Previews" : TimelineItemStyler_Previews.self,
+ "TimelineMediaPreviewDetailsView_Previews" : TimelineMediaPreviewDetailsView_Previews.self,
+ "TimelineMediaPreviewRedactConfirmationView_Previews" : TimelineMediaPreviewRedactConfirmationView_Previews.self,
+ "TimelineReactionView_Previews" : TimelineReactionView_Previews.self,
+ "TimelineReadReceiptsView_Previews" : TimelineReadReceiptsView_Previews.self,
+ "TimelineReplyView_Previews" : TimelineReplyView_Previews.self,
+ "TimelineStartRoomTimelineView_Previews" : TimelineStartRoomTimelineView_Previews.self,
+ "TimelineThreadSummaryView_Previews" : TimelineThreadSummaryView_Previews.self,
+ "TimelineView_Previews" : TimelineView_Previews.self,
+ "TombstonedAvatarImage_Previews" : TombstonedAvatarImage_Previews.self,
+ "TypingIndicatorView_Previews" : TypingIndicatorView_Previews.self,
+ "UnsupportedRoomTimelineView_Previews" : UnsupportedRoomTimelineView_Previews.self,
+ "UserDetailsEditScreen_Previews" : UserDetailsEditScreen_Previews.self,
+ "UserIndicatorModalView_Previews" : UserIndicatorModalView_Previews.self,
+ "UserIndicatorToastView_Previews" : UserIndicatorToastView_Previews.self,
+ "UserProfileCell_Previews" : UserProfileCell_Previews.self,
+ "UserProfileScreen_Previews" : UserProfileScreen_Previews.self,
+ "VerificationBadge_Previews" : VerificationBadge_Previews.self,
+ "VideoMediaEventsTimelineView_Previews" : VideoMediaEventsTimelineView_Previews.self,
+ "VideoRoomTimelineView_Previews" : VideoRoomTimelineView_Previews.self,
+ "VisualListItem_Previews" : VisualListItem_Previews.self,
+ "VoiceMessageButton_Previews" : VoiceMessageButton_Previews.self,
+ "VoiceMessageMediaEventsTimelineView_Previews" : VoiceMessageMediaEventsTimelineView_Previews.self,
+ "VoiceMessagePreviewComposer_Previews" : VoiceMessagePreviewComposer_Previews.self,
+ "VoiceMessageRecordingButton_Previews" : VoiceMessageRecordingButton_Previews.self,
+ "VoiceMessageRecordingComposer_Previews" : VoiceMessageRecordingComposer_Previews.self,
+ "VoiceMessageRecordingView_Previews" : VoiceMessageRecordingView_Previews.self,
+ "VoiceMessageRoomPlaybackView_Previews" : VoiceMessageRoomPlaybackView_Previews.self,
+ "VoiceMessageRoomTimelineView_Previews" : VoiceMessageRoomTimelineView_Previews.self,
+ "WaveformCursorView_Previews" : WaveformCursorView_Previews.self,
+ ]
+ }
+
+// swiftlint:enable all
+// swiftformat:enable all
diff --git a/ElementX/Sources/UITests/UITestsSignalling.swift b/ElementX/Sources/UITests/UITestsSignalling.swift
index fcbd5b7f0..8f707d306 100644
--- a/ElementX/Sources/UITests/UITestsSignalling.swift
+++ b/ElementX/Sources/UITests/UITestsSignalling.swift
@@ -29,6 +29,16 @@ enum UITestsSignal: Codable, Equatable {
/// Posts a notification.
case notification(name: Notification.Name)
+
+ case accessibilityAudit(AccessibilityAudit)
+ enum AccessibilityAudit: Codable, Equatable {
+ /// Ask the app for the next preview.
+ case nextPreview
+ /// Tell the test runner about a loaded preview.
+ case nextPreviewReady(name: String)
+ /// Tell the test runner that there are no more previews.
+ case noMorePreviews
+ }
}
enum UITestsSignalError: String, LocalizedError {
diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml
index 638241276..936901ab8 100644
--- a/ElementX/SupportingFiles/target.yml
+++ b/ElementX/SupportingFiles/target.yml
@@ -180,6 +180,18 @@ targets:
else
echo "warning: Sourcery not installed, run swift run tools setup-project"
fi
+
+ - name: 🧙 Sourcery - Generate Accessibility Tests
+ runOnlyWhenInstalling: false
+ basedOnDependencyAnalysis: false
+ shell: /bin/sh
+ script: |
+ export PATH="$PATH:/opt/homebrew/bin"
+ if which sourcery >/dev/null; then
+ sourcery --config Tools/Sourcery/TestablePreviewsDictionary.yml
+ else
+ echo "warning: Sourcery not installed, run swift run tools setup-project"
+ fi
postBuildScripts:
- name: ⚠️ SwiftLint
diff --git a/NSE/SupportingFiles/target.yml b/NSE/SupportingFiles/target.yml
index 223eeb939..97f4c2e2d 100644
--- a/NSE/SupportingFiles/target.yml
+++ b/NSE/SupportingFiles/target.yml
@@ -113,7 +113,7 @@ targets:
- path: ../../ElementX/Sources/Other/Pills/PlainMentionBuilder.swift
- path: ../../ElementX/Sources/Other/SDKListener.swift
- path: ../../ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift
- - path: ../../ElementX/Sources/Other/TestablePreview.swift
+ - path: ../../ElementX/Sources/Other/TestablePreview/TestablePreview.swift
- path: ../../ElementX/Sources/Other/UserAgentBuilder.swift
- path: ../../ElementX/Sources/Other/UserPreference.swift
- path: ../../ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift
diff --git a/Tools/Sourcery/TestablePreviewsDictionary.stencil b/Tools/Sourcery/TestablePreviewsDictionary.stencil
new file mode 100644
index 000000000..15f764459
--- /dev/null
+++ b/Tools/Sourcery/TestablePreviewsDictionary.stencil
@@ -0,0 +1,29 @@
+// swiftlint:disable all
+// swiftformat:disable all
+
+import SwiftUI
+
+{% if argument.mainTarget %}
+@testable import {{ argument.mainTarget }}
+{% endif %}
+{% for import in argument.imports %}
+{% if import != "last" %}
+import {{ import }}
+{% endif %}
+{% endfor %}
+{% for import in argument.testableImports %}
+{% if import != "last" %}
+@testable import {{ import }}
+{% endif %}
+{% endfor %}
+
+enum TestablePreviewsDictionary {
+ static let dictionary: [String: any PreviewProvider.Type] = [
+ {% for type in types.types where (type.implements.TestablePreview or type.based.TestablePreview or type|annotated:"TestablePreview") and type.name != "TestablePreview" %}
+ "{{ type.name }}" : {{ type.name }}.self,
+ {% endfor %}
+ ]
+ }
+
+// swiftlint:enable all
+// swiftformat:enable all
diff --git a/Tools/Sourcery/TestablePreviewsDictionary.yml b/Tools/Sourcery/TestablePreviewsDictionary.yml
new file mode 100644
index 000000000..7b136b61e
--- /dev/null
+++ b/Tools/Sourcery/TestablePreviewsDictionary.yml
@@ -0,0 +1,7 @@
+sources:
+ include:
+ - ../../ElementX
+templates:
+ - TestablePreviewsDictionary.stencil
+output:
+ ../../ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift
diff --git a/project.yml b/project.yml
index 10f9445e0..2331415de 100644
--- a/project.yml
+++ b/project.yml
@@ -21,6 +21,7 @@ options:
- UnitTests
- PreviewTests
- UITests
+ - AccessibilityTests
- IntegrationTests
- DevelopmentAssets
- Secrets
@@ -39,6 +40,7 @@ options:
- Screens
- Other
- UITests
+ - AccessibilityTests
postGenCommand: cd Tools/XcodeGen && sh postGenCommand.sh
settings:
@@ -59,6 +61,7 @@ include:
- path: IntegrationTests/SupportingFiles/target.yml
- path: NSE/SupportingFiles/target.yml
- path: ShareExtension/SupportingFiles/target.yml
+- path: AccessibilityTests/SupportingFiles/target.yml
# - path: MyAppVariant/override.yml
packages: