From 5b90f37f2eeeef6436d68c65a2c9a802595dcee1 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 15 Dec 2022 15:22:39 +0200 Subject: [PATCH] Various UI test fixes (#370) * Increase integration tests time limits again as they're still ocasionally failing * Fixed NavigationRootCoordinator name in logs * Refactor UI tests hierarchy and introduce new userFlowScreen * Introduce a RoomTimelineControllerFactory so that it can be mocked in the UserFlow UI tests * Start using a mock timeline controller for the UserSession flows * Remove the WeakDictionary dependency and replce it with a plain NSMapTable in the BackgroundTaskService * Allow multiple UITests screenshots per screen * Prevent the view hierarchy changing when taking screenshots * Add UserSessionScreen UI tests * Fix label triaging workflow project identifier as per vector-im/element-ios/pull/7150 * Fix settings screen tests * Fix roomPlainNoAvatar and roomEncryptedWithAvatar UI tests * Fix modal server selection screen UI tests * Fix bug report and login screen UI tests * Fix text typing missing characters on UI tests * Fix sliding sync configuration on integration tests * Stop crashing if not finding a particular room through the MockClientProxy --- .github/workflows/triage-labelled.yml | 2 +- ElementX.xcodeproj/project.pbxproj | 96 +++++------ .../Sources/Application/AppCoordinator.swift | 3 +- .../NavigationRootCoordinator.swift | 4 +- .../Other/Extensions/XCUIElement.swift | 62 +++++++ .../HomeScreen/View/HomeScreenRoomCell.swift | 1 + .../UIKitBackgroundTaskService.swift | 8 +- .../Services/Client/MockClientProxy.swift | 7 +- .../RoomSummary/MockRoomSummaryProvider.swift | 4 +- .../MockRoomTimelineController.swift | 0 .../MockRoomTimelineControllerFactory.swift | 28 +++ .../RoomTimelineController.swift | 11 +- .../RoomTimelineControllerFactory.swift | 30 ++++ ...oomTimelineControllerFactoryProtocol.swift | 22 +-- .../RoomTimelineControllerProtocol.swift | 0 .../UserSessionFlowCoordinator.swift | 19 ++- .../UITests/UITestScreenIdentifier.swift | 1 + .../UITests/UITestsAppCoordinator.swift | 159 ++++++++++++------ .../UITests/UITestsRootCoordinator.swift | 3 +- .../Sources/Vendor/WeakDictionary/LICENSE | 21 --- .../Sources/Vendor/WeakDictionary/README.md | 1 - .../WeakDictionary/WeakDictionary.swift | 116 ------------- .../WeakDictionaryKeyReference.swift | 53 ------ .../WeakDictionaryReference.swift | 35 ---- .../WeakDictionary/WeakKeyDictionary.swift | 136 --------------- ElementX/SupportingFiles/target.yml | 2 +- .../Sources/ApplicationTests.swift | 2 +- IntegrationTests/Sources/LoginTests.swift | 13 +- IntegrationTests/SupportingFiles/target.yml | 1 + UITests/Sources/Application.swift | 11 +- .../AuthenticationCoordinatorUITests.swift | 17 +- UITests/Sources/BugReportUITests.swift | 6 +- UITests/Sources/LoginScreenUITests.swift | 12 +- UITests/Sources/ServerSelectionUITests.swift | 4 +- UITests/Sources/UserSessionScreenTests.swift | 38 +++++ ...9th-generation.roomEncryptedWithAvatar.png | 4 +- ...-iPad-9th-generation.roomPlainNoAvatar.png | 4 +- .../de-DE-iPad-9th-generation.settings.png | 4 +- ...Pad-9th-generation.userSessionScreen-1.png | 3 + ...Pad-9th-generation.userSessionScreen-2.png | 3 + ...e-DE-iPhone-14.roomEncryptedWithAvatar.png | 4 +- .../de-DE-iPhone-14.roomPlainNoAvatar.png | 4 +- .../Application/de-DE-iPhone-14.settings.png | 4 +- .../de-DE-iPhone-14.userSessionScreen-1.png | 3 + .../de-DE-iPhone-14.userSessionScreen-2.png | 3 + ...9th-generation.roomEncryptedWithAvatar.png | 4 +- ...-iPad-9th-generation.roomPlainNoAvatar.png | 4 +- .../en-GB-iPad-9th-generation.settings.png | 4 +- ...Pad-9th-generation.userSessionScreen-1.png | 3 + ...Pad-9th-generation.userSessionScreen-2.png | 3 + ...n-GB-iPhone-14.roomEncryptedWithAvatar.png | 4 +- .../en-GB-iPhone-14.roomPlainNoAvatar.png | 4 +- .../Application/en-GB-iPhone-14.settings.png | 4 +- .../en-GB-iPhone-14.userSessionScreen-1.png | 3 + .../en-GB-iPhone-14.userSessionScreen-2.png | 3 + ...9th-generation.roomEncryptedWithAvatar.png | 4 +- ...-iPad-9th-generation.roomPlainNoAvatar.png | 4 +- .../fr-FR-iPad-9th-generation.settings.png | 4 +- ...Pad-9th-generation.userSessionScreen-1.png | 3 + ...Pad-9th-generation.userSessionScreen-2.png | 3 + ...r-FR-iPhone-14.roomEncryptedWithAvatar.png | 4 +- .../fr-FR-iPhone-14.roomPlainNoAvatar.png | 4 +- .../Application/fr-FR-iPhone-14.settings.png | 4 +- .../fr-FR-iPhone-14.userSessionScreen-1.png | 3 + .../fr-FR-iPhone-14.userSessionScreen-2.png | 3 + UITests/SupportingFiles/target.yml | 1 + 66 files changed, 454 insertions(+), 583 deletions(-) create mode 100644 ElementX/Sources/Other/Extensions/XCUIElement.swift rename ElementX/Sources/Services/Timeline/{ => TimelineController}/MockRoomTimelineController.swift (100%) create mode 100644 ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineControllerFactory.swift rename ElementX/Sources/Services/Timeline/{ => TimelineController}/RoomTimelineController.swift (99%) create mode 100644 ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift rename IntegrationTests/Sources/XCUIElement.swift => ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift (58%) rename ElementX/Sources/Services/Timeline/{ => TimelineController}/RoomTimelineControllerProtocol.swift (100%) delete mode 100644 ElementX/Sources/Vendor/WeakDictionary/LICENSE delete mode 100644 ElementX/Sources/Vendor/WeakDictionary/README.md delete mode 100644 ElementX/Sources/Vendor/WeakDictionary/WeakDictionary.swift delete mode 100644 ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryKeyReference.swift delete mode 100644 ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryReference.swift delete mode 100644 ElementX/Sources/Vendor/WeakDictionary/WeakKeyDictionary.swift create mode 100644 UITests/Sources/UserSessionScreenTests.swift create mode 100644 UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-1.png create mode 100644 UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-2.png create mode 100644 UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-1.png create mode 100644 UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-2.png create mode 100644 UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-1.png create mode 100644 UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-2.png create mode 100644 UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-1.png create mode 100644 UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-2.png create mode 100644 UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-1.png create mode 100644 UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-2.png create mode 100644 UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-1.png create mode 100644 UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-2.png diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml index 84d309d03..28cdb2331 100644 --- a/.github/workflows/triage-labelled.yml +++ b/.github/workflows/triage-labelled.yml @@ -32,5 +32,5 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc4ABTXY" + PROJECT_ID: "PVT_kwDOAM0swc4ABTXY" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index bf588dd75..e130176ff 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; }; 098CE03C6CC71A31F263FA33 /* ActivityCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9D14D6F914324865C7DB9F /* ActivityCoordinator.swift */; }; 09AAF04B27732046C755D914 /* SoftLogoutViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */; }; + 09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */; }; 0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; }; 0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */; }; 0BEFE400B4802FE8C9DB39B3 /* FilePreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62BDF0FF4F59AF6EA858B70B /* FilePreviewViewModel.swift */; }; @@ -48,6 +49,7 @@ 152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */; }; 1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; }; 157E5FDDF419C0B2CA7E2C28 /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */; }; + 158A2D528CC78C4E7A8ED608 /* MockRoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */; }; 15D867E638BFD0E5E71DB1EF /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEF3AC64B1358083F76B8B /* List.swift */; }; 165A883C29998EC779465068 /* SoftLogoutViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC38904A9663F7FAFD47457 /* SoftLogoutViewModelProtocol.swift */; }; 1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; }; @@ -86,6 +88,7 @@ 297CD0A27C87B0C50FF192EE /* RoomTimelineViewFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE384418EB1FEDFA62C9CD0 /* RoomTimelineViewFactoryProtocol.swift */; }; 29E20505F321071E8375F99B /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263B3B811C2B900F12C6F695 /* BuildSettings.swift */; }; 29EE1791E0AFA1ABB7F23D2F /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; }; + 2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */; }; 2B9AEEC12B1BBE5BD61D0F5E /* UserSessionFlowCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3429142FE11930422E7CC1A0 /* UserSessionFlowCoordinatorStateMachine.swift */; }; 2BA59D0AEFB4B82A2EC2A326 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; }; 2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; }; @@ -101,7 +104,6 @@ 3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; }; 323F36D880363C473B81A9EA /* MediaProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC3D31C2DA6910AA0079678A /* MediaProxyProtocol.swift */; }; 3274219F7F26A5C6C2C55630 /* FilePreviewViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F652E88106B855A2A55ADE /* FilePreviewViewModelProtocol.swift */; }; - 32BA37B01B05261FCF2D4B45 /* WeakDictionaryKeyReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 090CA61A835C151CEDF8F372 /* WeakDictionaryKeyReference.swift */; }; 33CAC1226DFB8B5D8447D286 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; }; 33D630461FC4562CC767EE9F /* FileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B0B1226DA8DB55918B34CD /* FileCache.swift */; }; 340D39DB87F3800D53A6A621 /* EmojiPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */; }; @@ -114,6 +116,7 @@ 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; }; 36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4B5B19A10D3F7C2BC5315DF /* VideoRoomTimelineItem.swift */; }; 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; }; + 38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */; }; 388FD50AC66E9E684DDFA9D8 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D2C0950F8196232D88045C /* ServerSelectionScreen.swift */; }; 38C76D586404C1FDED095F3A /* LoginModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B01468022EC826CB2FD2C0 /* LoginModels.swift */; }; 3910D3A2EF98587C0E7B9CCB /* EmojiMartEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F7F3CF7E70518BD7D25E04 /* EmojiMartEmoji.swift */; }; @@ -136,7 +139,6 @@ 440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */; }; 447E8580A0A2569E32529E17 /* MockRoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */; }; 44AE0752E001D1D10605CD88 /* Swipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FDA5344F7C4C6E4E863E13 /* Swipe.swift */; }; - 457465EC436703E8C76133A4 /* WeakDictionaryReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7955B20E2E6DA68E5BC0AB9 /* WeakDictionaryReference.swift */; }; 46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; }; 490E606044B18985055FF690 /* SettingsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */; }; 492274DA6691EE985C2FCCAA /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; }; @@ -161,6 +163,7 @@ 54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */; }; 563A05B43207D00A6B698211 /* OIDCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9010EE0CC913D095887EF36E /* OIDCService.swift */; }; 56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; }; + 588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; }; 59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; }; 5B8B51CEC4717AF487794685 /* NotificationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B490675B8E31423AF116BDA /* NotificationServiceProxy.swift */; }; 5C02841B2A86327B2C377682 /* NotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C830A64609CBD152F06E0457 /* NotificationConstants.swift */; }; @@ -192,7 +195,6 @@ 67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */; }; 6832733838C57A7D3FE8FEB5 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; }; 68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */; }; - 690ED5315B401238A3249DCB /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 3FDFF4C1153D263BAB93C1F3 /* README.md */; }; 69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; }; 6A0E7551E0D1793245F34CDD /* ClientError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09A267106B9585D3D0CFC0D /* ClientError.swift */; }; 6AC1DC1EAD9F7568360DA1BA /* ServerSelectionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A30A1758E2B73EF38E7C42F8 /* ServerSelectionModels.swift */; }; @@ -201,7 +203,6 @@ 6C9F6C7F2B35288C4230EF3F /* FilePreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55EA4B03F92F31EAA83B3F7B /* FilePreviewModels.swift */; }; 6CA81428F0970785CDCC5E86 /* UserNotificationToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31A4E5941ACBA4BB9FEF94C /* UserNotificationToastView.swift */; }; 6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */; }; - 6DF37000571B1BC6D134CC9E /* WeakDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 304FFD608DB6E612075AB1B4 /* WeakDictionary.swift */; }; 6E6E0AAF6C44C0B117EBBE5A /* SlidingSyncViewProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F3B445BD6EF1C751806B22 /* SlidingSyncViewProxy.swift */; }; 6EA61FCA55D950BDE326A1A7 /* ImageAnonymizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */; }; 6F2AB43A1EFAD8A97AF41A15 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; }; @@ -226,7 +227,6 @@ 7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */; }; 77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */; }; 77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */; }; - 78B71D53C1FC55FB7A9B75F0 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B0C97D2F560BCB72BE73B1 /* RoomTimelineController.swift */; }; 78BF60C696FFED63AAF58D10 /* SoftLogoutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22D46DB0CC6C55EBA7AE67A3 /* SoftLogoutViewModel.swift */; }; 7963F98CDFDEAC75E072BD81 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6A8C632CEF4600107792899 /* TextRoomTimelineItem.swift */; }; 7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; }; @@ -238,6 +238,7 @@ 7E3C34BC10936AD4F77975F4 /* EmojiMartJSONLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39001365B76B89983FDB7AD8 /* EmojiMartJSONLoader.swift */; }; 7E7DF1867F98B0D10A6C0A63 /* FileCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3648F2FADEF2672D6A0D489 /* FileCacheTests.swift */; }; 7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; }; + 7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */; }; 7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */; }; 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; }; 7F64FA937B95924B3A44EC12 /* OnboardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */; }; @@ -246,7 +247,6 @@ 80D00A7C62AAB44F54725C43 /* PermalinkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */; }; 8196A2E71ACC902DD69F24EE /* UserNotificationControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */; }; 83E5054739949181CA981193 /* LoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD667C4BB98CF4F3FE2CE3B0 /* LoginCoordinator.swift */; }; - 841172E1576A863F4450132D /* WeakKeyDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0ADFDC712027931F2216668 /* WeakKeyDictionary.swift */; }; 85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */; }; 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */; }; 8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; @@ -290,7 +290,6 @@ 9A47B7EFE3793760EEF68FFE /* UITestScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */; }; 9AC5F8142413862A9E3A2D98 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; }; 9B582B3EEFEA615D4A6FBF1A /* TimelineReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */; }; - 9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; }; 9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; }; 9BE7A9CF6C593251D734B461 /* MockServerSelectionScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A20AE75FF4FF35B1FF6CA7 /* MockServerSelectionScreenState.swift */; }; 9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */; }; @@ -324,7 +323,6 @@ AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */; }; AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; }; AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9760103CF316DF68698BCFE6 /* LaunchScreen.storyboard */; }; - AB4C5D62A21AD712811CE8CD /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68232D336E2B546AD95B78B5 /* XCUIElement.swift */; }; ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */; }; AC5CC8250CEAE57B73900C57 /* UserNotificationModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD80F22830C2360F3F39DDCE /* UserNotificationModalView.swift */; }; AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; }; @@ -335,9 +333,11 @@ B064D42BA087649ACAE462E8 /* SoftLogoutUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */; }; B09514A0A3EB3C19A4FD0B71 /* SoftLogoutScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCBDE671A613B3EB70794C4 /* SoftLogoutScreen.swift */; }; B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; }; + B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; }; B245583C63F8F90357B87FAE /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; }; B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; }; B3357B00F1AA930E54F76609 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; }; + B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; }; B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; }; B5111BAF5F601C139EBBD8BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; }; B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56C1BCB9E83B09A45387FCA2 /* EncryptedRoomTimelineView.swift */; }; @@ -413,7 +413,7 @@ E481C8FDCB6C089963C95344 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = BC01130651CB23340B899032 /* DeviceKit */; }; E5895C74615CBE8462FB840F /* SessionVerificationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF86010A0A719A9A50EEC59 /* SessionVerificationCoordinator.swift */; }; E67418DACEDBC29E988E6ACD /* message.caf in Resources */ = {isa = PBXBuildFile; fileRef = ED482057AE39D5C6D9C5F3D8 /* message.caf */; }; - E81EEC1675F2371D12A880A3 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */; }; + E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */; }; E8AB8D16E6D8E8E501F29BD9 /* FileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B0B1226DA8DB55918B34CD /* FileCache.swift */; }; E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; }; EA1E7949533E19C6D862680A /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885D8C42DD17625B5261BEFF /* MediaProvider.swift */; }; @@ -512,7 +512,6 @@ 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorStateMachine.swift; sourceTree = ""; }; 086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = ""; }; 08F64963396A6A23538EFCEC /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = is; path = is.lproj/Localizable.stringsdict; sourceTree = ""; }; - 090CA61A835C151CEDF8F372 /* WeakDictionaryKeyReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionaryKeyReference.swift; sourceTree = ""; }; 09199C43BAB209C0BD89A836 /* OnboardingPageIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPageIndicator.swift; sourceTree = ""; }; 0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderAvatarImage.swift; sourceTree = ""; }; 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = ""; }; @@ -558,6 +557,7 @@ 179423E34EE846E048E49CBF /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = ""; }; 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = ""; }; 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = ""; }; + 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = ""; }; 1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = ""; }; 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = ""; }; 1A3FC45B7643298BF361CEB1 /* VideoPlayerModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerModels.swift; sourceTree = ""; }; @@ -580,7 +580,6 @@ 22B384D54464FA39C6C7F6E7 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ca; path = ca.lproj/Localizable.stringsdict; sourceTree = ""; }; 22D46DB0CC6C55EBA7AE67A3 /* SoftLogoutViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModel.swift; sourceTree = ""; }; 233D5F7E5E9F49ABF3413291 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = hr; path = hr.lproj/Localizable.stringsdict; sourceTree = ""; }; - 24B0C97D2F560BCB72BE73B1 /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = ""; }; 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = ""; }; 2583416C8974272ADBADDBE1 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-TW"; path = "zh-TW.lproj/Localizable.stringsdict"; sourceTree = ""; }; 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; @@ -598,6 +597,7 @@ 2B37DCC9025452F46F91340E /* MockNotificationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNotificationServiceProxy.swift; sourceTree = ""; }; 2B80895CE021B49847BD7D74 /* TemplateViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateViewModelProtocol.swift; sourceTree = ""; }; 2B9BCACD0CC4CB8E37F17732 /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lt; path = lt.lproj/Localizable.stringsdict; sourceTree = ""; }; + 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = ""; }; 2CA028DCD4157F9A1F999827 /* BackgroundTaskProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTaskProtocol.swift; sourceTree = ""; }; 2CCBDE671A613B3EB70794C4 /* SoftLogoutScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreen.swift; sourceTree = ""; }; 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = ""; }; @@ -606,7 +606,6 @@ 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemProxy.swift; sourceTree = ""; }; 2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertInfo.swift; sourceTree = ""; }; 2F1B28C596DE541DA0AFD16C /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lo; path = lo.lproj/Localizable.stringsdict; sourceTree = ""; }; - 304FFD608DB6E612075AB1B4 /* WeakDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionary.swift; sourceTree = ""; }; 31B01468022EC826CB2FD2C0 /* LoginModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginModels.swift; sourceTree = ""; }; 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModel.swift; sourceTree = ""; }; 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModelTests.swift; sourceTree = ""; }; @@ -635,7 +634,6 @@ 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTaskService.swift; sourceTree = ""; }; 3F40F48279322E504153AB0D /* MockClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockClientProxy.swift; sourceTree = ""; }; 3F9E67AAB66638C69626866C /* UserSessionFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionFlowCoordinator.swift; sourceTree = ""; }; - 3FDFF4C1153D263BAB93C1F3 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 3FEE631F3A4AFDC6652DD9DA /* RoomTimelineViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewFactory.swift; sourceTree = ""; }; 40B21E611DADDEF00307E7AC /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; 41F3B445BD6EF1C751806B22 /* SlidingSyncViewProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlidingSyncViewProxy.swift; sourceTree = ""; }; @@ -677,6 +675,7 @@ 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = ""; }; 5282B7A2DCD076AD2CF27F46 /* VideoPlayerViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModelProtocol.swift; sourceTree = ""; }; 529513218340CC8419273165 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; + 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = ""; }; 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = ""; }; 534A5C8FCDE2CBC50266B9F2 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = gl; path = gl.lproj/Localizable.stringsdict; sourceTree = ""; }; 536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; @@ -701,7 +700,6 @@ 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageAnonymizerTests.swift; sourceTree = ""; }; 607974D08BD2AF83725D817A /* RoomMessageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageProtocol.swift; sourceTree = ""; }; 616197D81103330BF2ADD559 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/Localizable.strings; sourceTree = ""; }; - 61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = ""; }; 624244C398804ADC885239AA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; 62BDF0FF4F59AF6EA858B70B /* FilePreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewViewModel.swift; sourceTree = ""; }; 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = ""; }; @@ -711,7 +709,6 @@ 6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = ""; }; 667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = ""; }; 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = ""; }; - 68232D336E2B546AD95B78B5 /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProvider.swift; sourceTree = ""; }; 6A1AAC8EB2992918D01874AC /* rue */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rue; path = rue.lproj/Localizable.strings; sourceTree = ""; }; 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoPlistReader.swift; sourceTree = ""; }; @@ -727,6 +724,7 @@ 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = ""; }; 6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilderTests.swift; sourceTree = ""; }; 6FC5015B9634698BDB8701AF /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = ""; }; + 71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineControllerFactory.swift; sourceTree = ""; }; 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenModels.swift; sourceTree = ""; }; 71D52BAA5BADB06E5E8C295D /* Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = ""; }; 72D03D36422177EF01905D20 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; @@ -762,7 +760,6 @@ 892E29C98C4E8182C9037F84 /* TimelineStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyler.swift; sourceTree = ""; }; 8A9AE4967817E9608E22EB44 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; 8AC1A01C3A745BDF1D3697D3 /* SessionVerificationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreen.swift; sourceTree = ""; }; - 8B9A55AC2FB0FE0AEAA3DF1F /* LICENSE */ = {isa = PBXFileReference; path = LICENSE; sourceTree = ""; }; 8C0AA893D6F8A2F563E01BB9 /* in */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = in; path = in.lproj/Localizable.stringsdict; sourceTree = ""; }; 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; @@ -804,6 +801,7 @@ 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = ""; }; 9D7D706FFF438CAF16F44D8C /* ServerSelectionCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionCoordinator.swift; sourceTree = ""; }; 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = ""; }; + 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = ""; }; A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = ""; }; A05707BF550D770168A406DB /* LoginViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModelTests.swift; sourceTree = ""; }; A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = ""; }; @@ -891,7 +889,6 @@ C687844F60BFF532D49A994C /* AnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsTests.swift; sourceTree = ""; }; C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = ""; }; C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - C7955B20E2E6DA68E5BC0AB9 /* WeakDictionaryReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionaryReference.swift; sourceTree = ""; }; C830A64609CBD152F06E0457 /* NotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConstants.swift; sourceTree = ""; }; C88508B6F7974CFABEC4B261 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = ""; }; @@ -908,7 +905,6 @@ CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JoinedRoomSize+MemberCount.swift"; sourceTree = ""; }; CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestScreenIdentifier.swift; sourceTree = ""; }; - CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = ""; }; CCF86010A0A719A9A50EEC59 /* SessionVerificationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationCoordinator.swift; sourceTree = ""; }; CD80F22830C2360F3F39DDCE /* UserNotificationModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationModalView.swift; sourceTree = ""; }; CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; @@ -918,7 +914,6 @@ D06DFD894157A4C93A02D8B5 /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Localizable.strings; sourceTree = ""; }; D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = ""; }; D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = ""; }; - D0ADFDC712027931F2216668 /* WeakKeyDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakKeyDictionary.swift; sourceTree = ""; }; D1651A532305027D3F605E2B /* VideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerCoordinator.swift; sourceTree = ""; }; D1A9CCCF53495CF3D7B19FCE /* MockSessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSessionVerificationControllerProxy.swift; sourceTree = ""; }; D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = ""; }; @@ -963,9 +958,11 @@ E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = ""; }; E5F2B6443D1ED8602F328539 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingCoordinator.swift; sourceTree = ""; }; + E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = ""; }; E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = ""; }; E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = ""; }; + E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = ""; }; EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = ""; }; EBE5502760CF6CA2D7201883 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ja; path = ja.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -998,6 +995,7 @@ F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilder.swift; sourceTree = ""; }; F77C060C2ACC4CB7336A29E7 /* EmoteRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItem.swift; sourceTree = ""; }; F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = ""; }; + F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = ""; }; F9212AE02CBDD692C56A879F /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = ""; }; F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = ""; }; FA154570F693D93513E584C1 /* RoomMessageFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageFactory.swift; sourceTree = ""; }; @@ -1171,19 +1169,6 @@ path = View; sourceTree = ""; }; - 2064C5712E5DBF0A2D57A833 /* WeakDictionary */ = { - isa = PBXGroup; - children = ( - 8B9A55AC2FB0FE0AEAA3DF1F /* LICENSE */, - 3FDFF4C1153D263BAB93C1F3 /* README.md */, - 304FFD608DB6E612075AB1B4 /* WeakDictionary.swift */, - 090CA61A835C151CEDF8F372 /* WeakDictionaryKeyReference.swift */, - C7955B20E2E6DA68E5BC0AB9 /* WeakDictionaryReference.swift */, - D0ADFDC712027931F2216668 /* WeakKeyDictionary.swift */, - ); - path = WeakDictionary; - sourceTree = ""; - }; 24FD174C31912A5FACFEAFB5 /* SupportingFiles */ = { isa = PBXGroup; children = ( @@ -1234,6 +1219,19 @@ path = UITests; sourceTree = ""; }; + 2F2FED77226A43559F009463 /* TimelineController */ = { + isa = PBXGroup; + children = ( + 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */, + 71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */, + 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */, + E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */, + 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */, + 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */, + ); + path = TimelineController; + sourceTree = ""; + }; 323160803A296713F839540B /* View */ = { isa = PBXGroup; children = ( @@ -1382,6 +1380,7 @@ A40C19719687984FD9478FBE /* Task.swift */, 287FC98AF2664EAD79C0D902 /* UIDevice.swift */, 227AC5D71A4CE43512062243 /* URL.swift */, + E992D7B8BE54B2AB454613AF /* XCUIElement.swift */, ); path = Extensions; sourceTree = ""; @@ -1450,7 +1449,6 @@ 44D8C8431416EB8DFEC7E235 /* ApplicationTests.swift */, 2D256FEE2F1AF1E51D39B622 /* LoginTests.swift */, 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */, - 68232D336E2B546AD95B78B5 /* XCUIElement.swift */, ); path = Sources; sourceTree = ""; @@ -1881,6 +1879,7 @@ 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */, E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */, 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */, + F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */, ); path = Sources; sourceTree = ""; @@ -2152,14 +2151,6 @@ path = View; sourceTree = ""; }; - CEC90ED84EDEB86B209053E7 /* Vendor */ = { - isa = PBXGroup; - children = ( - 2064C5712E5DBF0A2D57A833 /* WeakDictionary */, - ); - path = Vendor; - sourceTree = ""; - }; D958761758AA1110476DE6A3 /* SessionVerification */ = { isa = PBXGroup; children = ( @@ -2251,7 +2242,6 @@ C0937E3B06A8F0E2DB7C8241 /* Other */, 2ECFF6B05DAA37EB10DBF7E8 /* UITests */, 337015ADFBA3AB96660DB3A6 /* Generated */, - CEC90ED84EDEB86B209053E7 /* Vendor */, ); path = Sources; sourceTree = ""; @@ -2296,14 +2286,12 @@ FCDF06BDB123505F0334B4F9 /* Timeline */ = { isa = PBXGroup; children = ( - 61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */, 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */, - 24B0C97D2F560BCB72BE73B1 /* RoomTimelineController.swift */, - CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */, 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */, 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */, 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */, 3EA31CC7012EA2A5653DAFC9 /* Fixtures */, + 2F2FED77226A43559F009463 /* TimelineController */, 5A7A7D6D373D411C8C48B881 /* TimeLineItemContent */, 95BE1C7CB2C80344FF0BE724 /* TimelineItems */, ); @@ -2603,7 +2591,6 @@ AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */, 5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */, 0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */, - 690ED5315B401238A3249DCB /* README.md in Resources */, CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */, 2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */, CCAA0671B46EAFD0BB528E2C /* apple_emojis_data.json in Resources */, @@ -2932,7 +2919,8 @@ AEE3981A0F090208E4445808 /* MockNotificationServiceProxy.swift in Sources */, 51DB67C5B5BC68B0A6FF54D4 /* MockRoomProxy.swift in Sources */, 2352C541AF857241489756FF /* MockRoomSummaryProvider.swift in Sources */, - E81EEC1675F2371D12A880A3 /* MockRoomTimelineController.swift in Sources */, + 09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */, + 158A2D528CC78C4E7A8ED608 /* MockRoomTimelineControllerFactory.swift in Sources */, 447E8580A0A2569E32529E17 /* MockRoomTimelineProvider.swift in Sources */, 9BE7A9CF6C593251D734B461 /* MockServerSelectionScreenState.swift in Sources */, D034A195A3494E38BF060485 /* MockSessionVerificationControllerProxy.swift in Sources */, @@ -2980,8 +2968,10 @@ A7FD7B992E6EE6E5A8429197 /* RoomSummaryDetails.swift in Sources */, 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */, AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */, - 78B71D53C1FC55FB7A9B75F0 /* RoomTimelineController.swift in Sources */, - 9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */, + 2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */, + 38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */, + 7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */, + E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */, 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */, 13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */, 70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */, @@ -3082,10 +3072,6 @@ 36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */, 64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */, 6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */, - 6DF37000571B1BC6D134CC9E /* WeakDictionary.swift in Sources */, - 32BA37B01B05261FCF2D4B45 /* WeakDictionaryKeyReference.swift in Sources */, - 457465EC436703E8C76133A4 /* WeakDictionaryReference.swift in Sources */, - 841172E1576A863F4450132D /* WeakKeyDictionary.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3116,6 +3102,8 @@ 0ED951768EC443A8728DE1D7 /* TimelineStyle.swift in Sources */, 9A47B7EFE3793760EEF68FFE /* UITestScreenIdentifier.swift in Sources */, 35C57543D245E82CBFE15DF0 /* URL.swift in Sources */, + B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */, + 588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3127,7 +3115,7 @@ 23B2CD5A06B16055BDDD0994 /* ApplicationTests.swift in Sources */, 07240B7159A3990C4C2E8FFC /* LoginTests.swift in Sources */, 290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */, - AB4C5D62A21AD712811CE8CD /* XCUIElement.swift in Sources */, + B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 4bc5b5129..bc3dc4d8b 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -219,7 +219,8 @@ class AppCoordinator: AppCoordinatorProtocol { let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: SplashScreenCoordinator()) let userSessionFlowCoordinator = UserSessionFlowCoordinator(userSession: userSession, navigationSplitCoordinator: navigationSplitCoordinator, - bugReportService: bugReportService) + bugReportService: bugReportService, + roomTimelineControllerFactory: RoomTimelineControllerFactory()) userSessionFlowCoordinator.callback = { [weak self] action in switch action { diff --git a/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift b/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift index 84dbe0fc0..8ebf5afe7 100644 --- a/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift +++ b/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift @@ -57,9 +57,9 @@ class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomSt var description: String { if let rootCoordinator = rootModule?.coordinator { - return "SingleScreenCoordinator(\(rootCoordinator)" + return "NavigationRootCoordinator(\(rootCoordinator)" } else { - return "SingleScreenCoordinator(Empty)" + return "NavigationRootCoordinator(Empty)" } } diff --git a/ElementX/Sources/Other/Extensions/XCUIElement.swift b/ElementX/Sources/Other/Extensions/XCUIElement.swift new file mode 100644 index 000000000..0e5dfbb9a --- /dev/null +++ b/ElementX/Sources/Other/Extensions/XCUIElement.swift @@ -0,0 +1,62 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import XCTest + +extension XCUIElement { + func clearAndTypeText(_ text: String) { + let maxAttemptCount = 10 + var attemptCount = 0 + + repeat { + tap() + + guard let currentValue = value as? String else { + XCTFail("Tried to clear and type text into a non string value") + return + } + + let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: currentValue.count) + + typeText(deleteString) + typeText(text) + + if !exists { // Break if the element in question doesn't exist anymore + break + } + + guard let newValue = value as? String else { + XCTFail("Tried to clear and type text into a non string value") + return + } + + if newValue == String(repeating: "•", count: text.count) { // Secure entry text field + break + } + + if newValue == text.trimmingCharacters(in: .whitespacesAndNewlines) { + break + } + + attemptCount += 1 + if attemptCount > maxAttemptCount { + XCTFail("Failed clearAndTypeText after \(maxAttemptCount) attempts.") + return + } + + } while true + } +} diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift index b3d8991fd..d9bbe6512 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift @@ -83,6 +83,7 @@ struct HomeScreenRoomCell: View { context.send(viewAction: .loadRoomData(roomIdentifier: room.id)) } } + .accessibilityIdentifier("roomName:\(room.name)") } var lastMessageFont: Font { diff --git a/ElementX/Sources/Services/Background/UIKitBackgroundTaskService.swift b/ElementX/Sources/Services/Background/UIKitBackgroundTaskService.swift index c4ff2e400..d65a5f540 100644 --- a/ElementX/Sources/Services/Background/UIKitBackgroundTaskService.swift +++ b/ElementX/Sources/Services/Background/UIKitBackgroundTaskService.swift @@ -20,7 +20,7 @@ import UIKit /// /// UIKitBackgroundTaskService is a concrete implementation of BackgroundTaskServiceProtocol using a given `ApplicationProtocol` instance. class UIKitBackgroundTaskService: BackgroundTaskServiceProtocol { private let applicationBlock: () -> ApplicationProtocol? - private var reusableTasks: WeakDictionary = WeakDictionary() + private var reusableTasks = NSMapTable(keyOptions: .strongMemory, valueOptions: .weakMemory) private var application: ApplicationProtocol? { applicationBlock() @@ -50,7 +50,7 @@ class UIKitBackgroundTaskService: BackgroundTaskServiceProtocol { var result: BackgroundTaskProtocol? if isReusable { - if let oldTask = reusableTasks[name], oldTask.isRunning { + if let oldTask = reusableTasks.object(forKey: name as NSString), oldTask.isRunning { oldTask.reuse() result = oldTask } else { @@ -59,11 +59,11 @@ class UIKitBackgroundTaskService: BackgroundTaskServiceProtocol { application: application, expirationHandler: { [weak self] task in guard let self else { return } - self.reusableTasks[task.name] = nil + self.reusableTasks.removeObject(forKey: task.name as NSString) expirationHandler?() }) { created = true - reusableTasks[name] = newTask + reusableTasks.setObject(newTask, forKey: name as NSString) result = newTask } } diff --git a/ElementX/Sources/Services/Client/MockClientProxy.swift b/ElementX/Sources/Services/Client/MockClientProxy.swift index 8f5dd713c..ae14c146d 100644 --- a/ElementX/Sources/Services/Client/MockClientProxy.swift +++ b/ElementX/Sources/Services/Client/MockClientProxy.swift @@ -41,7 +41,12 @@ class MockClientProxy: ClientProxyProtocol { func restartSync() { } func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? { - nil + guard let room = roomSummaryProvider?.roomListPublisher.value.first(where: { $0.id == identifier }), + let displayName = room.asFilled?.name else { + return nil + } + + return MockRoomProxy(displayName: displayName) } func loadUserDisplayName() async -> Result { diff --git a/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift index 1ef5ed57f..0b5a19a7e 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift @@ -55,7 +55,7 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol { isDirect: true, avatarURLString: nil, lastMessage: AttributedString("Prosciutto beef ribs pancetta filet mignon kevin hamburger, chuck ham venison picanha. Beef ribs chislic turkey biltong tenderloin."), - lastMessageTimestamp: .now, + lastMessageTimestamp: .distantPast, unreadNotificationCount: 4)), .filled(details: RoomSummaryDetails(id: "2", name: "Second room", @@ -69,7 +69,7 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol { isDirect: true, avatarURLString: nil, lastMessage: try? AttributedString(markdown: "**@mock:client.com**: T-bone beef ribs bacon"), - lastMessageTimestamp: .now, + lastMessageTimestamp: .distantPast, unreadNotificationCount: 0)), .empty(id: "3") ] diff --git a/ElementX/Sources/Services/Timeline/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift similarity index 100% rename from ElementX/Sources/Services/Timeline/MockRoomTimelineController.swift rename to ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineControllerFactory.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineControllerFactory.swift new file mode 100644 index 000000000..a69e538b6 --- /dev/null +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineControllerFactory.swift @@ -0,0 +1,28 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +struct MockRoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { + func buildRoomTimelineController(userId: String, + roomProxy: RoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol { + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk + return timelineController + } +} diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift similarity index 99% rename from ElementX/Sources/Services/Timeline/RoomTimelineController.swift rename to ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index 7a5fffaba..3bcac2931 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -32,19 +32,20 @@ class RoomTimelineController: RoomTimelineControllerProtocol { } } - let roomId: String let callbacks = PassthroughSubject() private(set) var timelineItems = [RoomTimelineItemProtocol]() + var roomId: String { + roomProxy.id + } + init(userId: String, - roomId: String, + roomProxy: RoomProxyProtocol, timelineProvider: RoomTimelineProviderProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, - mediaProvider: MediaProviderProtocol, - roomProxy: RoomProxyProtocol) { + mediaProvider: MediaProviderProtocol) { self.userId = userId - self.roomId = roomId self.timelineProvider = timelineProvider self.timelineItemFactory = timelineItemFactory self.mediaProvider = mediaProvider diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift new file mode 100644 index 000000000..b40ade4e9 --- /dev/null +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift @@ -0,0 +1,30 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { + func buildRoomTimelineController(userId: String, + roomProxy: RoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol { + RoomTimelineController(userId: userId, + roomProxy: roomProxy, + timelineProvider: RoomTimelineProvider(roomProxy: roomProxy), + timelineItemFactory: timelineItemFactory, + mediaProvider: mediaProvider) + } +} diff --git a/IntegrationTests/Sources/XCUIElement.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift similarity index 58% rename from IntegrationTests/Sources/XCUIElement.swift rename to ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift index ef588662f..28ffa43e4 100644 --- a/IntegrationTests/Sources/XCUIElement.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift @@ -14,20 +14,12 @@ // limitations under the License. // -import XCTest +import Foundation -extension XCUIElement { - func clearAndTypeText(_ text: String) { - guard let stringValue = value as? String else { - XCTFail("Tried to clear and type text into a non string value") - return - } - - tap() - - let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.count) - - typeText(deleteString) - typeText(text) - } +@MainActor +protocol RoomTimelineControllerFactoryProtocol { + func buildRoomTimelineController(userId: String, + roomProxy: RoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol } diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift similarity index 100% rename from ElementX/Sources/Services/Timeline/RoomTimelineControllerProtocol.swift rename to ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift diff --git a/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift b/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift index eef58bb99..ff6ecd3f7 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinator.swift @@ -26,6 +26,7 @@ class UserSessionFlowCoordinator: CoordinatorProtocol { private let userSession: UserSessionProtocol private let navigationSplitCoordinator: NavigationSplitCoordinator private let bugReportService: BugReportServiceProtocol + private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol private let emojiProvider: EmojiProviderProtocol = EmojiProvider() private let sidebarNavigationStackCoordinator: NavigationStackCoordinator @@ -33,11 +34,15 @@ class UserSessionFlowCoordinator: CoordinatorProtocol { var callback: ((UserSessionFlowCoordinatorAction) -> Void)? - init(userSession: UserSessionProtocol, navigationSplitCoordinator: NavigationSplitCoordinator, bugReportService: BugReportServiceProtocol) { + init(userSession: UserSessionProtocol, + navigationSplitCoordinator: NavigationSplitCoordinator, + bugReportService: BugReportServiceProtocol, + roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol) { stateMachine = UserSessionFlowCoordinatorStateMachine() self.userSession = userSession self.navigationSplitCoordinator = navigationSplitCoordinator self.bugReportService = bugReportService + self.roomTimelineControllerFactory = roomTimelineControllerFactory sidebarNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator) detailNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator) @@ -150,13 +155,11 @@ class UserSessionFlowCoordinator: CoordinatorProtocol { mediaProvider: userSession.mediaProvider, roomProxy: roomProxy, attributedStringBuilder: AttributedStringBuilder()) - - let timelineController = RoomTimelineController(userId: userId, - roomId: roomIdentifier, - timelineProvider: RoomTimelineProvider(roomProxy: roomProxy), - timelineItemFactory: timelineItemFactory, - mediaProvider: userSession.mediaProvider, - roomProxy: roomProxy) + + let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(userId: userId, + roomProxy: roomProxy, + timelineItemFactory: timelineItemFactory, + mediaProvider: userSession.mediaProvider) let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: detailNavigationStackCoordinator, timelineController: timelineController, diff --git a/ElementX/Sources/UITests/UITestScreenIdentifier.swift b/ElementX/Sources/UITests/UITestScreenIdentifier.swift index 1d64a19ff..48376f580 100644 --- a/ElementX/Sources/UITests/UITestScreenIdentifier.swift +++ b/ElementX/Sources/UITests/UITestScreenIdentifier.swift @@ -36,6 +36,7 @@ enum UITestScreenIdentifier: String { case roomSmallTimelineIncomingAndSmallPagination case roomSmallTimelineLargePagination case sessionVerification + case userSessionScreen } extension UITestScreenIdentifier: CustomStringConvertible { diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index cd44e7ae4..716d033a5 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -18,58 +18,64 @@ import SwiftUI import UIKit class UITestsAppCoordinator: AppCoordinatorProtocol { - private var currentRootCoordinator: CoordinatorProtocol? - private let navigationStackCoordinator: NavigationStackCoordinator - let notificationManager: NotificationManagerProtocol? = nil + private let navigationRootCoordinator: NavigationRootCoordinator + private var mockScreens: [MockScreen] = [] + var notificationManager: NotificationManagerProtocol? init() { UIView.setAnimationsEnabled(false) - navigationStackCoordinator = NavigationStackCoordinator() + navigationRootCoordinator = NavigationRootCoordinator() + mockScreens = UITestScreenIdentifier.allCases.map { MockScreen(id: $0, navigationRootCoordinator: navigationRootCoordinator) } ServiceLocator.shared.register(userNotificationController: MockUserNotificationController()) } func start() { - let screens = mockScreens() - let rootCoordinator = UITestsRootCoordinator(mockScreens: screens) { id in - guard let screen = screens.first(where: { $0.id == id }) else { + let rootCoordinator = UITestsRootCoordinator(mockScreens: mockScreens) { id in + guard let screen = self.mockScreens.first(where: { $0.id == id }) else { fatalError() } - // Store the initial coordinator so that it stays alive if drops it - // For example when replacing the root in the authentication flows - self.currentRootCoordinator = screen.coordinator - - self.navigationStackCoordinator.setRootCoordinator(screen.coordinator) + self.navigationRootCoordinator.setRootCoordinator(screen.coordinator) } - navigationStackCoordinator.setRootCoordinator(rootCoordinator) + navigationRootCoordinator.setRootCoordinator(rootCoordinator) Bundle.elementFallbackLanguage = "en" } - - func toPresentable() -> AnyView { - navigationStackCoordinator.toPresentable() - } - private func mockScreens() -> [MockScreen] { - UITestScreenIdentifier.allCases.map { MockScreen(id: $0, navigationStackCoordinator: navigationStackCoordinator) } + func toPresentable() -> AnyView { + navigationRootCoordinator.toPresentable() } } @MainActor class MockScreen: Identifiable { let id: UITestScreenIdentifier - let navigationStackCoordinator: NavigationStackCoordinator + + private let navigationRootCoordinator: NavigationRootCoordinator + private var retainedState = [Any]() + + init(id: UITestScreenIdentifier, navigationRootCoordinator: NavigationRootCoordinator) { + self.id = id + self.navigationRootCoordinator = navigationRootCoordinator + } + lazy var coordinator: CoordinatorProtocol = { switch id { case .login: - return LoginCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), - navigationStackCoordinator: navigationStackCoordinator)) + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = LoginCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), + navigationStackCoordinator: navigationStackCoordinator)) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .serverSelection: - return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), - userNotificationController: MockUserNotificationController(), - isModallyPresented: true)) + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), + userNotificationController: MockUserNotificationController(), + isModallyPresented: true)) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .serverSelectionNonModal: return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), userNotificationController: MockUserNotificationController(), @@ -78,8 +84,12 @@ class MockScreen: Identifiable { return AnalyticsPromptCoordinator(parameters: .init(userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"), mediaProvider: MockMediaProvider()))) case .authenticationFlow: - return AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(), - navigationStackCoordinator: navigationStackCoordinator) + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(), + navigationStackCoordinator: navigationStackCoordinator) + retainedState.append(coordinator) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .softLogout: let credentials = SoftLogoutCredentials(userId: "@mock:matrix.org", homeserverName: "matrix.org", @@ -93,47 +103,66 @@ class MockScreen: Identifiable { case .simpleUpgrade: return TemplateCoordinator(parameters: .init(promptType: .upgrade)) case .home: + let navigationStackCoordinator = NavigationStackCoordinator() let session = MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:matrix.org"), mediaProvider: MockMediaProvider()) - return HomeScreenCoordinator(parameters: .init(userSession: session, - attributedStringBuilder: AttributedStringBuilder(), - bugReportService: MockBugReportService(), - navigationStackCoordinator: navigationStackCoordinator)) + let coordinator = HomeScreenCoordinator(parameters: .init(userSession: session, + attributedStringBuilder: AttributedStringBuilder(), + bugReportService: MockBugReportService(), + navigationStackCoordinator: navigationStackCoordinator)) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .settings: - return SettingsCoordinator(parameters: .init(navigationStackCoordinator: navigationStackCoordinator, - userNotificationController: MockUserNotificationController(), - userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"), - mediaProvider: MockMediaProvider()), - bugReportService: MockBugReportService())) + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = SettingsCoordinator(parameters: .init(navigationStackCoordinator: navigationStackCoordinator, + userNotificationController: MockUserNotificationController(), + userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"), + mediaProvider: MockMediaProvider()), + bugReportService: MockBugReportService())) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .bugReport: - return BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(), - userNotificationController: MockUserNotificationController(), - screenshot: nil, - isModallyPresented: false)) + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(), + userNotificationController: MockUserNotificationController(), + screenshot: nil, + isModallyPresented: true)) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .bugReportWithScreenshot: - return BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(), - userNotificationController: MockUserNotificationController(), - screenshot: Asset.Images.appLogo.image, - isModallyPresented: false)) + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(), + userNotificationController: MockUserNotificationController(), + screenshot: Asset.Images.appLogo.image, + isModallyPresented: false)) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .onboarding: return OnboardingCoordinator() case .roomPlainNoAvatar: + let navigationStackCoordinator = NavigationStackCoordinator() let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator, timelineController: MockRoomTimelineController(), mediaProvider: MockMediaProvider(), roomName: "Some room name", roomAvatarUrl: nil, emojiProvider: EmojiProvider()) - return RoomScreenCoordinator(parameters: parameters) + let coordinator = RoomScreenCoordinator(parameters: parameters) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .roomEncryptedWithAvatar: + let navigationStackCoordinator = NavigationStackCoordinator() let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator, timelineController: MockRoomTimelineController(), mediaProvider: MockMediaProvider(), roomName: "Some room name", roomAvatarUrl: "mock_url", emojiProvider: EmojiProvider()) - return RoomScreenCoordinator(parameters: parameters) + let coordinator = RoomScreenCoordinator(parameters: parameters) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .roomSmallTimeline: + let navigationStackCoordinator = NavigationStackCoordinator() let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator, @@ -142,8 +171,12 @@ class MockScreen: Identifiable { roomName: "New room", roomAvatarUrl: "mock_url", emojiProvider: EmojiProvider()) - return RoomScreenCoordinator(parameters: parameters) + let coordinator = RoomScreenCoordinator(parameters: parameters) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .roomSmallTimelineIncomingAndSmallPagination: + let navigationStackCoordinator = NavigationStackCoordinator() + let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk] @@ -155,8 +188,13 @@ class MockScreen: Identifiable { roomName: "Small timeline", roomAvatarUrl: "mock_url", emojiProvider: EmojiProvider()) - return RoomScreenCoordinator(parameters: parameters) + let coordinator = RoomScreenCoordinator(parameters: parameters) + + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .roomSmallTimelineLargePagination: + let navigationStackCoordinator = NavigationStackCoordinator() + let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] @@ -166,15 +204,28 @@ class MockScreen: Identifiable { roomName: "Small timeline, paginating", roomAvatarUrl: "mock_url", emojiProvider: EmojiProvider()) - return RoomScreenCoordinator(parameters: parameters) + let coordinator = RoomScreenCoordinator(parameters: parameters) + + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator case .sessionVerification: let parameters = SessionVerificationCoordinatorParameters(sessionVerificationControllerProxy: MockSessionVerificationControllerProxy()) return SessionVerificationCoordinator(parameters: parameters) + case .userSessionScreen: + let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: SplashScreenCoordinator()) + + let clientProxy = MockClientProxy(userIdentifier: "@mock:client.com", roomSummaryProvider: MockRoomSummaryProvider(state: .loaded)) + + let coordinator = UserSessionFlowCoordinator(userSession: MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider()), + navigationSplitCoordinator: navigationSplitCoordinator, + bugReportService: MockBugReportService(), + roomTimelineControllerFactory: MockRoomTimelineControllerFactory()) + + coordinator.start() + + retainedState.append(coordinator) + + return navigationSplitCoordinator } }() - - init(id: UITestScreenIdentifier, navigationStackCoordinator: NavigationStackCoordinator) { - self.id = id - self.navigationStackCoordinator = navigationStackCoordinator - } } diff --git a/ElementX/Sources/UITests/UITestsRootCoordinator.swift b/ElementX/Sources/UITests/UITestsRootCoordinator.swift index bfa96708e..ae2711335 100644 --- a/ElementX/Sources/UITests/UITestsRootCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsRootCoordinator.swift @@ -31,8 +31,7 @@ struct UITestsRootCoordinator: CoordinatorProtocol { } .accessibilityIdentifier(coordinator.id.rawValue) } + .padding(.top, 50) // Add some top padding so the iPad split screen button isn't tapped by mistake .listStyle(.plain) - .navigationTitle("Screens") - .navigationViewStyle(.stack) } } diff --git a/ElementX/Sources/Vendor/WeakDictionary/LICENSE b/ElementX/Sources/Vendor/WeakDictionary/LICENSE deleted file mode 100644 index 6136eb5c1..000000000 --- a/ElementX/Sources/Vendor/WeakDictionary/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2016 Nicholas Cross - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/ElementX/Sources/Vendor/WeakDictionary/README.md b/ElementX/Sources/Vendor/WeakDictionary/README.md deleted file mode 100644 index f054fc05f..000000000 --- a/ElementX/Sources/Vendor/WeakDictionary/README.md +++ /dev/null @@ -1 +0,0 @@ -Files copied over from [nicholascross/WeakDictionary](https://github.com/nicholascross/WeakDictionary) because of a lack SPM support. \ No newline at end of file diff --git a/ElementX/Sources/Vendor/WeakDictionary/WeakDictionary.swift b/ElementX/Sources/Vendor/WeakDictionary/WeakDictionary.swift deleted file mode 100644 index 90e77ff29..000000000 --- a/ElementX/Sources/Vendor/WeakDictionary/WeakDictionary.swift +++ /dev/null @@ -1,116 +0,0 @@ -// MIT License -// -// Copyright (c) 2016 Nicholas Cross -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import Foundation - -public struct WeakDictionary { - private var storage: [Key: WeakDictionaryReference] - - public init() { - self.init(storage: [Key: WeakDictionaryReference]()) - } - - public init(dictionary: [Key: Value]) { - var newStorage = [Key: WeakDictionaryReference]() - dictionary.forEach { key, value in newStorage[key] = WeakDictionaryReference(value: value) } - self.init(storage: newStorage) - } - - private init(storage: [Key: WeakDictionaryReference]) { - self.storage = storage - } - - public mutating func reap() { - storage = weakDictionary().storage - } - - public func weakDictionary() -> WeakDictionary { - self[startIndex.. [Key: Value] { - var newStorage = [Key: Value]() - - storage.forEach { key, value in - if let retainedValue = value.value { - newStorage[key] = retainedValue - } - } - - return newStorage - } -} - -extension WeakDictionary: Collection { - public typealias Index = DictionaryIndex> - - public var startIndex: Index { - storage.startIndex - } - - public var endIndex: Index { - storage.endIndex - } - - public func index(after index: Index) -> Index { - storage.index(after: index) - } - - public subscript(position: Index) -> (Key, WeakDictionaryReference) { - return storage[position] - } - - public subscript(key: Key) -> Value? { - get { - guard let valueRef = storage[key] else { - return nil - } - - return valueRef.value - } - - set { - guard let value = newValue else { - storage[key] = nil - return - } - - storage[key] = WeakDictionaryReference(value: value) - } - } - - public subscript(bounds: Range) -> WeakDictionary { - let subStorage = storage[bounds.lowerBound..]() - - subStorage.filter { _, value in value.value != nil } - .forEach { key, value in newStorage[key] = value } - - return WeakDictionary(storage: newStorage) - } -} - -public extension Dictionary where Value: AnyObject { - func weakDictionary() -> WeakDictionary { - WeakDictionary(dictionary: self) - } -} diff --git a/ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryKeyReference.swift b/ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryKeyReference.swift deleted file mode 100644 index 0af9b74d6..000000000 --- a/ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryKeyReference.swift +++ /dev/null @@ -1,53 +0,0 @@ -// MIT License -// -// Copyright (c) 2016 Nicholas Cross -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import Foundation - -public struct WeakDictionaryKey: Hashable { - private weak var baseKey: Key? - private let hash: Int - private var retainedValue: Value? - private let nilKeyHash = UUID().hashValue - - public init(key: Key, value: Value? = nil) { - baseKey = key - retainedValue = value - hash = key.hashValue - } - - public static func == (lhs: WeakDictionaryKey, rhs: WeakDictionaryKey) -> Bool { - (lhs.baseKey != nil && rhs.baseKey != nil && lhs.baseKey == rhs.baseKey) - || lhs.hashValue == rhs.hashValue - } - - public func hash(into hasher: inout Hasher) { - if baseKey == nil { - hasher.combine(nilKeyHash) - } else { - hasher.combine(baseKey) - } - } - - public var key: Key? { - baseKey - } -} diff --git a/ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryReference.swift b/ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryReference.swift deleted file mode 100644 index de03cda93..000000000 --- a/ElementX/Sources/Vendor/WeakDictionary/WeakDictionaryReference.swift +++ /dev/null @@ -1,35 +0,0 @@ -// MIT License -// -// Copyright (c) 2016 Nicholas Cross -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import Foundation - -public struct WeakDictionaryReference { - private weak var referencedValue: Value? - - init(value: Value) { - referencedValue = value - } - - public var value: Value? { - referencedValue - } -} diff --git a/ElementX/Sources/Vendor/WeakDictionary/WeakKeyDictionary.swift b/ElementX/Sources/Vendor/WeakDictionary/WeakKeyDictionary.swift deleted file mode 100644 index 3bf6a4c84..000000000 --- a/ElementX/Sources/Vendor/WeakDictionary/WeakKeyDictionary.swift +++ /dev/null @@ -1,136 +0,0 @@ -// MIT License -// -// Copyright (c) 2016 Nicholas Cross -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import Foundation - -public struct WeakKeyDictionary { - private var storage: WeakDictionary, Value> - private let valuesRetainedByKey: Bool - - public init(valuesRetainedByKey: Bool = false) { - self.init( - storage: WeakDictionary, Value>(), - valuesRetainedByKey: valuesRetainedByKey - ) - } - - public init(dictionary: [Key: Value], valuesRetainedByKey: Bool = false) { - var newStorage = WeakDictionary, Value>() - - dictionary.forEach { key, value in - var keyRef: WeakDictionaryKey! - - if valuesRetainedByKey { - keyRef = WeakDictionaryKey(key: key, value: value) - } else { - keyRef = WeakDictionaryKey(key: key) - } - - newStorage[keyRef] = value - } - - self.init(storage: newStorage, valuesRetainedByKey: valuesRetainedByKey) - } - - private init(storage: WeakDictionary, Value>, valuesRetainedByKey: Bool = false) { - self.storage = storage - self.valuesRetainedByKey = valuesRetainedByKey - } - - public mutating func reap() { - storage = weakKeyDictionary().storage - } - - public func weakDictionary() -> WeakDictionary { - dictionary().weakDictionary() - } - - public func weakKeyDictionary() -> WeakKeyDictionary { - self[startIndex.. [Key: Value] { - var newStorage = [Key: Value]() - - storage.forEach { key, value in - if let retainedKey = key.key, let retainedValue = value.value { - newStorage[retainedKey] = retainedValue - } - } - - return newStorage - } -} - -extension WeakKeyDictionary: Collection { - public typealias Index = DictionaryIndex, WeakDictionaryReference> - - public var startIndex: Index { - storage.startIndex - } - - public var endIndex: Index { - storage.endIndex - } - - public func index(after index: Index) -> Index { - storage.index(after: index) - } - - public subscript(position: Index) -> (WeakDictionaryKey, WeakDictionaryReference) { - return storage[position] - } - - public subscript(key: Key) -> Value? { - get { - storage[WeakDictionaryKey(key: key)] - } - - set { - let retainedValue = valuesRetainedByKey ? newValue : nil - let weakKey = WeakDictionaryKey(key: key, value: retainedValue) - storage[weakKey] = newValue - } - } - - public subscript(bounds: Range) -> WeakKeyDictionary { - let subStorage = storage[bounds.lowerBound.., Value>() - - subStorage.filter { key, value in key.key != nil && value.value != nil } - .forEach { key, value in newStorage[key] = value.value } - - return WeakKeyDictionary(storage: newStorage) - } -} - -public extension WeakDictionary where Key: AnyObject { - func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary { - WeakKeyDictionary(dictionary: dictionary(), valuesRetainedByKey: valuesRetainedByKey) - } -} - -public extension Dictionary where Key: AnyObject, Value: AnyObject { - func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary { - WeakKeyDictionary(dictionary: self, valuesRetainedByKey: valuesRetainedByKey) - } -} diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index 1d6fd06d1..9ed414446 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -128,7 +128,7 @@ targets: sources: - path: ../Sources excludes: - - Screens/Templates + - Other/Extensions/XCUIElement.swift - path: ../Resources - path: ../SupportingFiles - path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX diff --git a/IntegrationTests/Sources/ApplicationTests.swift b/IntegrationTests/Sources/ApplicationTests.swift index 78cb2eab0..83968a664 100644 --- a/IntegrationTests/Sources/ApplicationTests.swift +++ b/IntegrationTests/Sources/ApplicationTests.swift @@ -31,7 +31,7 @@ class ApplicationTests: XCTestCase { return } - let expectedDuration = 4.0 + let expectedDuration = 5.0 XCTAssertLessThanOrEqual(actualDuration, expectedDuration) } } diff --git a/IntegrationTests/Sources/LoginTests.swift b/IntegrationTests/Sources/LoginTests.swift index 582b8aaaf..4a5017196 100644 --- a/IntegrationTests/Sources/LoginTests.swift +++ b/IntegrationTests/Sources/LoginTests.swift @@ -17,7 +17,7 @@ import XCTest class LoginTests: XCTestCase { - let expectedDuration = 30.0 + let expectedDuration = 32.0 func testLoginFlow() throws { let parser = TestMeasurementParser() @@ -52,6 +52,11 @@ class LoginTests: XCTestCase { homeserverTextField.clearAndTypeText(app.homeserver) + let slidingSyncTextField = app.textFields["slidingSyncProxyAddressTextField"] + XCTAssertTrue(slidingSyncTextField.waitForExistence(timeout: 5.0)) + + slidingSyncTextField.clearAndTypeText(app.homeserver) + let confirmButton = app.buttons["confirmButton"] XCTAssertTrue(confirmButton.exists) confirmButton.tap() @@ -59,14 +64,12 @@ class LoginTests: XCTestCase { let usernameTextField = app.textFields["usernameTextField"] XCTAssertTrue(usernameTextField.exists) - usernameTextField.tap() - usernameTextField.typeText(app.username) + usernameTextField.clearAndTypeText(app.username) let passwordTextField = app.secureTextFields["passwordTextField"] XCTAssertTrue(passwordTextField.exists) - passwordTextField.tap() - passwordTextField.typeText(app.password) + passwordTextField.clearAndTypeText(app.password) let nextButton = app.buttons["nextButton"] XCTAssertTrue(nextButton.exists) diff --git a/IntegrationTests/SupportingFiles/target.yml b/IntegrationTests/SupportingFiles/target.yml index 936c3ca97..41ebbcb59 100644 --- a/IntegrationTests/SupportingFiles/target.yml +++ b/IntegrationTests/SupportingFiles/target.yml @@ -57,3 +57,4 @@ targets: sources: - path: ../Sources - path: ../SupportingFiles + - path: ../../ElementX/Sources/Other/Extensions/XCUIElement.swift diff --git a/UITests/Sources/Application.swift b/UITests/Sources/Application.swift index d3827df2d..48ea39f1f 100644 --- a/UITests/Sources/Application.swift +++ b/UITests/Sources/Application.swift @@ -41,10 +41,15 @@ extension XCUIApplication { /// Assert screenshot for a screen with the given identifier. Does not fail if a screenshot is newly created. /// - Parameter identifier: Identifier of the UI test screen - func assertScreenshot(_ identifier: UITestScreenIdentifier) { - let failure = verifySnapshot(matching: screenshot().image, + func assertScreenshot(_ identifier: UITestScreenIdentifier, step: Int? = nil) { + var snapshotName = identifier.rawValue + if let step { + snapshotName += "-\(step)" + } + + let failure = verifySnapshot(matching: XCUIScreen.main.screenshot().image, as: .image(precision: 0.99, perceptualPrecision: 0.98, scale: nil), - named: identifier.rawValue, + named: snapshotName, testName: testName) if let failure, diff --git a/UITests/Sources/AuthenticationCoordinatorUITests.swift b/UITests/Sources/AuthenticationCoordinatorUITests.swift index e18b66220..f099b3c70 100644 --- a/UITests/Sources/AuthenticationCoordinatorUITests.swift +++ b/UITests/Sources/AuthenticationCoordinatorUITests.swift @@ -29,10 +29,9 @@ class AuthenticationCoordinatorUITests: XCTestCase { app.buttons["getStartedButton"].tap() // Login Screen: Enter valid credentials - app.textFields["usernameTextField"].tap() - app.typeText("alice\n") - app.secureTextFields["passwordTextField"].tap() - app.typeText("12345678") + + app.textFields["usernameTextField"].clearAndTypeText("alice\n") + app.secureTextFields["passwordTextField"].clearAndTypeText("12345678") app.assertScreenshot(.authenticationFlow) @@ -52,10 +51,8 @@ class AuthenticationCoordinatorUITests: XCTestCase { app.buttons["getStartedButton"].tap() // Login Screen: Enter invalid credentials - app.textFields["usernameTextField"].tap() - app.typeText("alice") - app.secureTextFields["passwordTextField"].tap() - app.typeText("87654321") + app.textFields["usernameTextField"].clearAndTypeText("alice") + app.secureTextFields["passwordTextField"].clearAndTypeText("87654321") // Login Screen: Tap next let nextButton = app.buttons["nextButton"] @@ -80,9 +77,7 @@ class AuthenticationCoordinatorUITests: XCTestCase { app.buttons["editServerButton"].tap() // Server Selection: Clear the default and enter OIDC server. - app.textFields["addressTextField"].tap() - app.textFields["addressTextField"].buttons.element.tap() - app.typeText("company.com") + app.textFields["addressTextField"].clearAndTypeText("company.com") // Dismiss server screen. app.buttons["confirmButton"].tap() diff --git a/UITests/Sources/BugReportUITests.swift b/UITests/Sources/BugReportUITests.swift index a35d64a90..db6083e0e 100644 --- a/UITests/Sources/BugReportUITests.swift +++ b/UITests/Sources/BugReportUITests.swift @@ -46,13 +46,11 @@ class BugReportUITests: XCTestCase { app.goToScreenWithIdentifier(.bugReport) // type 4 chars - app.textViews["reportTextView"].tap() - app.textViews["reportTextView"].typeText("Test") + app.textViews["reportTextView"].clearAndTypeText("Text") XCTAssertFalse(app.buttons["sendButton"].isEnabled) // type one more char and see the button enabled - app.textViews["reportTextView"].tap() - app.textViews["reportTextView"].typeText("-") + app.textViews["reportTextView"].clearAndTypeText("Longer text") XCTAssert(app.buttons["sendButton"].isEnabled) } diff --git a/UITests/Sources/LoginScreenUITests.swift b/UITests/Sources/LoginScreenUITests.swift index 0503ce7af..040bfc7b9 100644 --- a/UITests/Sources/LoginScreenUITests.swift +++ b/UITests/Sources/LoginScreenUITests.swift @@ -40,11 +40,9 @@ class LoginScreenUITests: XCTestCase { app.assertScreenshot(.login) // When typing in a username and password. - app.textFields.element.tap() - app.typeText("@test:matrix.org") + app.textFields.element.clearAndTypeText("@test:matrix.org") - app.secureTextFields.element.tap() - app.typeText("12345678") + app.secureTextFields.element.clearAndTypeText("12345678") // Then the form should be ready to submit. validateNextButtonIsEnabled(for: "matrix.org with credentials entered") @@ -56,8 +54,7 @@ class LoginScreenUITests: XCTestCase { app.goToScreenWithIdentifier(.login) // When entering a username on a homeserver that only supports OIDC. - app.textFields.element.tap() - app.typeText("@test:company.com\n") + app.textFields.element.clearAndTypeText("@test:company.com\n") // Then the screen should be configured for OIDC. let state = "an OIDC only server" @@ -72,8 +69,7 @@ class LoginScreenUITests: XCTestCase { app.goToScreenWithIdentifier(.login) // When entering a username on a homeserver with an unsupported flow. - app.textFields.element.tap() - app.typeText("@test:server.net\n") + app.textFields.element.clearAndTypeText("@test:server.net\n") // Then the screen should not allow login to continue. let state = "an unsupported server" diff --git a/UITests/Sources/ServerSelectionUITests.swift b/UITests/Sources/ServerSelectionUITests.swift index df351d1eb..fe99e7efd 100644 --- a/UITests/Sources/ServerSelectionUITests.swift +++ b/UITests/Sources/ServerSelectionUITests.swift @@ -66,9 +66,7 @@ class ServerSelectionUITests: XCTestCase { app.goToScreenWithIdentifier(.serverSelection) // When typing in an invalid homeserver - app.textFields[textFieldIdentifier].tap() - app.textFields.element.buttons.element.tap() - app.typeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ + app.textFields[textFieldIdentifier].clearAndTypeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ // Then an error should be shown and the confirmation button disabled. XCTAssertEqual(app.textFields[textFieldIdentifier].value as? String, "thisisbad", "The text field should show the entered server.") diff --git a/UITests/Sources/UserSessionScreenTests.swift b/UITests/Sources/UserSessionScreenTests.swift new file mode 100644 index 000000000..97a9ad443 --- /dev/null +++ b/UITests/Sources/UserSessionScreenTests.swift @@ -0,0 +1,38 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import ElementX +import XCTest + +@MainActor +class UserSessionScreenTests: XCTestCase { + func testUserSessionFlows() async throws { + let roomName = "First room" + + let app = Application.launch() + app.goToScreenWithIdentifier(.userSessionScreen) + + app.assertScreenshot(.userSessionScreen, step: 1) + + app.buttons["roomName:\(roomName)"].tap() + + XCTAssert(app.staticTexts[roomName].exists) + + try await Task.sleep(for: .seconds(1)) + + app.assertScreenshot(.userSessionScreen, step: 2) + } +} diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomEncryptedWithAvatar.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomEncryptedWithAvatar.png index 42b48c81e..b0ebc89bd 100644 --- a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomEncryptedWithAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomEncryptedWithAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b5fb88d76d9d6b0c2ab6f9f96d80cac1cb41cfa7e938b2cf9746553c7ef55fc -size 208681 +oid sha256:9902bf55f027c729fd31b790d875699bf4a2e0f2852b9ceb2178c84bc8aca226 +size 211684 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomPlainNoAvatar.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomPlainNoAvatar.png index 95609c29b..eb4169f9b 100644 --- a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomPlainNoAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.roomPlainNoAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce6df94c886ae302976ab1748fc000fdaf535a8178b5415f9e44f87f2c5677a7 -size 208028 +oid sha256:1fbf57e59072a7e06026a69a0858ed9f65a72e0bfa4fabdf4de6a28e1bc4b364 +size 211052 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.settings.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.settings.png index 7bf103de9..b3bbd3f04 100644 --- a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.settings.png +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c957491840909920efbb8b445cecb039e0cfe50127918bace68d34bcf1b0501 -size 101235 +oid sha256:27d058762e6eafc940c71b8e4edeef26f6ccad34e086ad6a0f0a30252848485f +size 93290 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-1.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-1.png new file mode 100644 index 000000000..f6af9f5e6 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d90a2dd77853c9707a2805b480983dc46d92d1606e22a61ff18ad12a0cb70228 +size 123022 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-2.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-2.png new file mode 100644 index 000000000..67dddd625 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPad-9th-generation.userSessionScreen-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89c5cd9ca5283ec107581a2e45b3f904fad92119848eb9bd7d8c3c7295802a75 +size 334531 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomEncryptedWithAvatar.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomEncryptedWithAvatar.png index da2f26eb8..5d1d36f7f 100644 --- a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomEncryptedWithAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomEncryptedWithAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0305582dd212396d3443d10e675a5e2dcb9e964e6543acb0033d4f58e3c66be6 -size 296035 +oid sha256:dd603c2e38d5281190788cfa06425a512587fbb49a32d5d895361533ab48419a +size 373824 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomPlainNoAvatar.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomPlainNoAvatar.png index 1f801f0fe..189fe485d 100644 --- a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomPlainNoAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.roomPlainNoAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5beeaa7dea7a8d7cc8e6acb8928dd2b72fda9caa8a03e79d230e8a31392be58c -size 295025 +oid sha256:066c66947a2d47092dde8db56d885cd62127f24a817a06198e2ab0d29fa61857 +size 371508 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.settings.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.settings.png index e055cdcee..ba6a3cf68 100644 --- a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.settings.png +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed05c76fb48fb1440ae419caed6833c3d25858513b85417d19921cac444cc781 -size 125722 +oid sha256:97980472cdf36a0d07109fc066bd8184013b0a99cbbd164e82dbfb0a20cbc09f +size 115670 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-1.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-1.png new file mode 100644 index 000000000..d4fa79043 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3de2e5153d1b685c253df7f20d91a5355015fae183f4882315c56fe4eede0889 +size 112151 diff --git a/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-2.png b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-2.png new file mode 100644 index 000000000..2d426bb96 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/de-DE-iPhone-14.userSessionScreen-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6aaa8bf274c693ca1fd3dffd4fbeab41df2698e401bb1c16f9bd6190d694a0df +size 334188 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomEncryptedWithAvatar.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomEncryptedWithAvatar.png index 3ccf4d741..d9bee8094 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomEncryptedWithAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomEncryptedWithAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba9218275999d949200c620d5019bb03e99935081a70c6e7151217b1787e9ccb -size 207960 +oid sha256:0a34acc9936b4fbff9aad17617ee77dd8c89356d652b2a7132f5bb7d20c4f715 +size 210981 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomPlainNoAvatar.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomPlainNoAvatar.png index 5e22c20d5..cf6f89061 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomPlainNoAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.roomPlainNoAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82b057602fc6b76294eed9232a9fa9f5b9f8348bff50ba5cdd05a9299674b1dc -size 207307 +oid sha256:ec8c0bdbf78d2bd1019cd8319aed419fd729be3d8be566b729d171cc21adec8b +size 210340 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.settings.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.settings.png index 590d16461..1de039054 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.settings.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5bafccc43ded94082a5182afe1af60e3a17f0d943ac981c704f313914eaa640 -size 101898 +oid sha256:cbbb771047c24948ad5b38308273fc1262667bdaafcf0bac61704b3186f66f1d +size 93992 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-1.png new file mode 100644 index 000000000..30bd99c73 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25ba24b61f830ca4a975957059dd912f587a06436e9bc1899a01bec845e4125c +size 123049 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-2.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-2.png new file mode 100644 index 000000000..77eac0da2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreen-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df9c30fd83057e62b3ac28d820bae1ad17e520270e21ef1a4c1429a181877ee4 +size 334367 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomEncryptedWithAvatar.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomEncryptedWithAvatar.png index 42033d798..fadf71b69 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomEncryptedWithAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomEncryptedWithAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74b59a7a3f639eefa579333d77e301c4fb417889846b82c828242bcb87822ecc -size 295099 +oid sha256:f7322585bdb968fa0ad5244e5ca05401e7b32e3c27a0e3b1abb4f74f2cc736f9 +size 372873 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomPlainNoAvatar.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomPlainNoAvatar.png index 83766882b..200f6d99f 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomPlainNoAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.roomPlainNoAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ade4638eba012fdae7d0b60dd92b634a2dce225f4e24d52e53abf7617838a9ef -size 294155 +oid sha256:bf8edaf502cb0a8ea89699280a31ef2a8505b2107fb67d81975b9a63813bdd2e +size 370584 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.settings.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.settings.png index 5350f3cc8..9f851def0 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.settings.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fdad77450c1fdf345f2c8f94fd36148f984819bb5e99f0079e72d9efaa03e34 -size 125447 +oid sha256:063feeb819831472533b47c11eb8a69924843fea616ef3f56651274fd8f970c9 +size 115397 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-1.png new file mode 100644 index 000000000..5b9b27e26 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b31c6c701af4e18f3bee3e28ce2d43044934f9a16dfb8726dadc233a616a27e +size 112187 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-2.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-2.png new file mode 100644 index 000000000..f92778c04 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreen-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d340ed581bb489d166f6d358cde52fd1a5c735faba60fb921bc71fc68489ef3d +size 334229 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomEncryptedWithAvatar.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomEncryptedWithAvatar.png index b98a57234..2c749b52e 100644 --- a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomEncryptedWithAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomEncryptedWithAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df627a68a56f879f53298d8af24e6c66cf8cbf77745c94a50e365fce7f1f8922 -size 208173 +oid sha256:aa4dc34fbb2b7412232fb048d1ddde465f949784bc4e9af0374d7cae490a5dd3 +size 211181 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomPlainNoAvatar.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomPlainNoAvatar.png index 3f6c7cffa..5f0310083 100644 --- a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomPlainNoAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.roomPlainNoAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58ac026654258e9713f5f5877f35de33e117c54405ec40aa90c4328414eeac79 -size 207519 +oid sha256:ca335bfdc0d02a56eb7584e9f18004361abcb0365c30733861bbd20b7a385b3b +size 210546 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.settings.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.settings.png index 5d0c14902..de9889de9 100644 --- a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.settings.png +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c20831ac18ee32022faf98abe3866d67581a3b466ed9eb7ceaa20bff6dfc9ec5 -size 102302 +oid sha256:df1a88376fa6e083729329fcf221093c4704d900de8acc40600a61b7fd812a2c +size 94430 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-1.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-1.png new file mode 100644 index 000000000..854be3dd0 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1713e05e0292fcd03384f297d171fe9f7494c4ca7d82c65bff68c490a5cf398 +size 124142 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-2.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-2.png new file mode 100644 index 000000000..4ffec54c2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPad-9th-generation.userSessionScreen-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48524ce3e3adfbb8cf6db5d24af0ab50a188daf015cbab033fcecc6eeafd8439 +size 335408 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomEncryptedWithAvatar.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomEncryptedWithAvatar.png index 129c11175..55d72231f 100644 --- a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomEncryptedWithAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomEncryptedWithAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6170f6628637496185cd3d89509735bd91ecc9a00e6e9e449e79d4f09f19fc96 -size 295475 +oid sha256:794a4b78bd5e5cda370bfac8168d19951ef5005c5d9267d372b9b55c9accfa4b +size 373232 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomPlainNoAvatar.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomPlainNoAvatar.png index df11747a8..99d6ec3e1 100644 --- a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomPlainNoAvatar.png +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.roomPlainNoAvatar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4da4a01c13823486548c8e24926e7cae5f3e779597c39aaaddd57393c743c7a -size 294447 +oid sha256:39a5f3d31a13112058a4b4c3d0b83066ff1e3a546b65e82234970b76748812ed +size 370940 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.settings.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.settings.png index 56aa42009..bc2466729 100644 --- a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.settings.png +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b643263191776badaf326c825ed53af855836443b9ec9dbede5e9ee6063bafac -size 127431 +oid sha256:d4b3f25e56c50b01e3ce87c4bd0537e752664e23b7b761a5bdb1e2b88ed4dc35 +size 117371 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-1.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-1.png new file mode 100644 index 000000000..e39e67792 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfbeb2402f34533a88a49185d5642188fe38821a090e6e34ad550b413b5fa912 +size 116841 diff --git a/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-2.png b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-2.png new file mode 100644 index 000000000..2b2921549 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/fr-FR-iPhone-14.userSessionScreen-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04ab9dbb2bb167bbe6d4b8a6c9c392477b8b387f79313f0a9ecdc099ef7c0f97 +size 339899 diff --git a/UITests/SupportingFiles/target.yml b/UITests/SupportingFiles/target.yml index f95fbf0a9..55a0be520 100644 --- a/UITests/SupportingFiles/target.yml +++ b/UITests/SupportingFiles/target.yml @@ -68,3 +68,4 @@ targets: - path: ../../ElementX/Sources/Other/Extensions/FileManager.swift - path: ../../ElementX/Sources/Other/InfoPlistReader.swift - path: ../../ElementX/Sources/Other/Extensions/URL.swift + - path: ../../ElementX/Sources/Other/Extensions/XCUIElement.swift