From 95d50125e4bc21ce959e731b395a08ce4a849400 Mon Sep 17 00:00:00 2001 From: yasser khan Date: Mon, 9 Feb 2026 19:46:27 +0530 Subject: [PATCH] iOS & Android: Migrate 29 Channel Settings tests from Rainforest to Detox (#9313) --- .github/workflows/e2e-ios-template.yml | 10 +- detox/.detoxrc.json | 4 +- detox/README.md | 1 - detox/e2e/config.js | 2 +- detox/e2e/support/adb_utils.ts | 80 - detox/e2e/support/ui/component/alert.ts | 1 + detox/e2e/support/ui/screen/add_members.ts | 77 + detox/e2e/support/ui/screen/channel.ts | 25 +- detox/e2e/support/ui/screen/channel_info.ts | 52 + .../ui/screen/create_direct_message.ts | 2 +- detox/e2e/support/ui/screen/index.ts | 2 + detox/e2e/support/ui/screen/login.ts | 11 +- .../ui/screen/manage_channel_members.ts | 32 +- detox/e2e/support/ui/screen/server.ts | 2 +- detox/e2e/support/ui/screen/thread.ts | 2 +- detox/e2e/support/utils/detoxhelpers.ts | 52 - detox/e2e/support/utils/index.ts | 19 +- .../channels/account/custom_status.e2e.ts | 1 - .../channels/autocomplete/edit_post.e2e.ts | 1 - .../channel_create_edit.e2e.ts | 276 +++ .../channel_join_leave.e2e.ts | 123 ++ .../channel_settings/channel_members.e2e.ts | 332 ++++ .../channel_navigation.e2e.ts | 152 ++ .../channel_notifications.e2e.ts | 64 + .../channel_system_messages.e2e.ts | 107 ++ .../channels/channel_post_list.e2e.ts | 1 - .../interactive_dialog_plugin.e2e.ts | 0 .../channels/messaging/channel_link.e2e.ts | 3 - .../messaging/emojis_and_reactions.e2e.ts | 4 - .../follow_and_unfollow_messsage.e2e.ts | 2 - .../channels/messaging/message_delete.e2e.ts | 4 - .../channels/messaging/message_edit.e2e.ts | 4 - .../channels/messaging/message_reply.e2e.ts | 4 - .../messaging/pin_and_unpin_message.e2e.ts | 3 +- .../messaging/save_and_unsave_message.e2e.ts | 2 - .../channels/search/pinned_messages.e2e.ts | 5 - .../threads/follow_and_unfollow_thread.e2e.ts | 4 - .../channels/threads/global_threads.e2e.ts | 1 - .../threads/open_thread_in_channel.e2e.ts | 2 - .../channels/threads/reply_to_thread.e2e.ts | 6 - .../threads/save_and_unsave_thread.e2e.ts | 4 - detox/e2e/test/setup.ts | 74 +- detox/package-lock.json | 1637 ++++++++--------- detox/package.json | 10 +- 44 files changed, 2088 insertions(+), 1112 deletions(-) delete mode 100644 detox/e2e/support/adb_utils.ts create mode 100644 detox/e2e/support/ui/screen/add_members.ts create mode 100644 detox/e2e/test/products/channels/channel_settings/channel_create_edit.e2e.ts create mode 100644 detox/e2e/test/products/channels/channel_settings/channel_join_leave.e2e.ts create mode 100644 detox/e2e/test/products/channels/channel_settings/channel_members.e2e.ts create mode 100644 detox/e2e/test/products/channels/channel_settings/channel_navigation.e2e.ts create mode 100644 detox/e2e/test/products/channels/channel_settings/channel_notifications.e2e.ts create mode 100644 detox/e2e/test/products/channels/channel_settings/channel_system_messages.e2e.ts rename detox/e2e/test/{ => products/channels}/interactive_dialog/interactive_dialog_plugin.e2e.ts (100%) diff --git a/.github/workflows/e2e-ios-template.yml b/.github/workflows/e2e-ios-template.yml index e995acc6b..63346be8b 100644 --- a/.github/workflows/e2e-ios-template.yml +++ b/.github/workflows/e2e-ios-template.yml @@ -115,7 +115,7 @@ jobs: id: generate-specs uses: ./.github/actions/generate-specs with: - parallelism: 5 + parallelism: 10 search_path: detox/e2e/test device_name: ${{ env.DEVICE_NAME }} device_os_version: ${{ env.DEVICE_OS_VERSION }} @@ -244,8 +244,8 @@ jobs: # Open Simulator.app in background to speed up UI rendering open -a Simulator --args -CurrentDeviceUDID "$SIMULATOR_ID" - # Give Simulator.app time to fully initialize UI - sleep 3 + # Give Simulator.app time to fully initialize UI (iOS 26.2 needs more time) + sleep 5 echo "SIMULATOR_ID=$SIMULATOR_ID" >> $GITHUB_ENV @@ -319,9 +319,9 @@ jobs: tail -30 metro.log else echo "Metro is serving on http://localhost:8081" - # Give Metro extra time to fully initialize for iOS 26.2 + # Give Metro extra time to fully initialize for iOS 26.2 (React Native bridge needs more time) echo "Allowing Metro to fully stabilize..." - sleep 3 + sleep 8 fi cd detox diff --git a/detox/.detoxrc.json b/detox/.detoxrc.json index 5c627b0c4..a6f9f8cde 100644 --- a/detox/.detoxrc.json +++ b/detox/.detoxrc.json @@ -83,10 +83,10 @@ "behavior": { "init": { "reinstallApp": false, - "launchApp": true + "launchApp": false }, "cleanup": { - "shutdownDevice": true + "shutdownDevice": false } }, "session": { diff --git a/detox/README.md b/detox/README.md index e4823f4aa..db1fc4348 100644 --- a/detox/README.md +++ b/detox/README.md @@ -181,4 +181,3 @@ To run Playbooks tests: For complete documentation, see: - [Wix Pilot Technical Overview](https://wix-pilot.com/docs/guides/technical-overview) - [Pilot Best Practices Guide](https://wix-pilot.com/docs/guides/pilot-best-practices) - diff --git a/detox/e2e/config.js b/detox/e2e/config.js index c05375edf..079c02c63 100644 --- a/detox/e2e/config.js +++ b/detox/e2e/config.js @@ -6,7 +6,7 @@ const shard = process.env.CI_NODE_INDEX ? process.env.CI_NODE_INDEX : ''; module.exports = { setupFilesAfterEnv: ['./test/setup.ts'], - maxWorkers: 1, + maxWorkers: process.env.CI ? 1 : 2, testSequencer: './custom_sequencer.js', testTimeout: process.env.LOW_BANDWIDTH_MODE === 'true' ? 240000 : 180000, rootDir: '.', diff --git a/detox/e2e/support/adb_utils.ts b/detox/e2e/support/adb_utils.ts deleted file mode 100644 index 39ece3124..000000000 --- a/detox/e2e/support/adb_utils.ts +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. -/* eslint-disable no-console */ - -import {execSync} from 'child_process'; - -/** - * Check if we're running on Android platform - * Uses environment variable as fallback if device is not initialized - */ -function isAndroid(): boolean { - try { - // Try to get platform from device (if initialized) - if (typeof device !== 'undefined' && device.getPlatform) { - return device.getPlatform() === 'android'; - } - } catch { - // Device not initialized yet, fall back to env var - } - - // Fall back to environment variable check - return process.env.IOS !== 'true'; -} - -/** - * Clean up ADB reverse port mappings to prevent "Address already in use" errors - * This is particularly important in CI environments where previous test runs may have crashed - * iOS: This function safely no-ops on iOS - no side effects - */ -export async function cleanupAdbReversePorts(): Promise { - // Only run on Android - safe no-op for iOS - if (!isAndroid()) { - return; - } - - try { - console.info('[ADB Cleanup] Removing all reverse port mappings...'); - - // Remove all reverse port mappings - execSync('adb reverse --remove-all', { - stdio: 'pipe', - timeout: 5000, - }); - - console.info('[ADB Cleanup] Successfully cleaned up reverse port mappings'); - } catch (error) { - // Don't fail if cleanup fails - this is best-effort - console.warn(`[ADB Cleanup] Warning: Failed to cleanup reverse ports: ${(error as Error).message}`); - } -} - -/** - * Reset ADB server connection to clear any stale state - * This can help recover from connection issues in CI - * iOS: This function safely no-ops on iOS - no side effects - */ -export async function resetAdbServer(): Promise { - // Only run on Android - safe no-op for iOS - if (!isAndroid()) { - return; - } - - try { - console.info('[ADB Reset] Restarting ADB server...'); - - // Kill and restart ADB server - execSync('adb kill-server && adb start-server', { - stdio: 'pipe', - timeout: 10000, - }); - - // Wait a bit for server to stabilize - await new Promise((resolve) => setTimeout(resolve, 2000)); - - console.info('[ADB Reset] Successfully restarted ADB server'); - } catch (error) { - // Don't fail if reset fails - this is best-effort - console.warn(`[ADB Reset] Warning: Failed to reset ADB server: ${(error as Error).message}`); - } -} diff --git a/detox/e2e/support/ui/component/alert.ts b/detox/e2e/support/ui/component/alert.ts index 38393040f..f64f265fa 100644 --- a/detox/e2e/support/ui/component/alert.ts +++ b/detox/e2e/support/ui/component/alert.ts @@ -40,6 +40,7 @@ class Alert { // alert buttons cancelButton = isAndroid() ? element(by.text('CANCEL')) : element(by.label('Cancel')).atIndex(1); confirmButton = isAndroid() ? element(by.text('CONFIRM')) : element(by.label('Confirm')).atIndex(1); + doneButton = isAndroid() ? element(by.text('DONE')) : element(by.label('Done')).atIndex(1); deleteButton = isAndroid() ? element(by.text('DELETE')) : element(by.label('Delete')).atIndex(0); deleteScheduledMessageButton = isAndroid() ? element(by.text('DELETE')) : element(by.label('Delete')).atIndex(1); leaveButton = isAndroid() ? element(by.text('LEAVE')) : element(by.label('Leave')).atIndex(0); diff --git a/detox/e2e/support/ui/screen/add_members.ts b/detox/e2e/support/ui/screen/add_members.ts new file mode 100644 index 000000000..58e8f0e53 --- /dev/null +++ b/detox/e2e/support/ui/screen/add_members.ts @@ -0,0 +1,77 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {ProfilePicture} from '@support/ui/component'; +import {timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +class AddMembersScreen { + testID = { + addMembersScreen: 'add_members.screen', + searchInput: 'add_members.search_bar.search.input', + userList: 'add_members.user_list', + userItemPrefix: 'add_members.user_list.user_item.', + addButton: 'add_members.add.button', + addChannelMembersButton: 'add_members.selected.start.button', + backButton: 'screen.back.button', + tutorialTooltip: 'tutorial_highlight', + }; + + addChannelMembersButton = element(by.id(this.testID.addChannelMembersButton)); + addMembersScreen = element(by.id(this.testID.addMembersScreen)); + searchInput = element(by.id(this.testID.searchInput)); + userList = element(by.id(this.testID.userList)); + addButton = element(by.id(this.testID.addButton)); + backButton = element(by.id(this.testID.backButton)); + tutorialTooltip = element(by.id(this.testID.tutorialTooltip)); + + getUserItem = (userId: string) => { + return element(by.id(`${this.testID.userItemPrefix}${userId}.${userId}`)); + }; + + getUserItemProfilePicture = (userId: string) => { + return element(ProfilePicture.getProfilePictureItemMatcher(this.testID.userItemPrefix, userId)); + }; + + getUserItemDisplayName = (userId: string) => { + return element(by.id(`${this.testID.userItemPrefix}${userId}.${userId}.display_name`)); + }; + + toBeVisible = async () => { + await waitFor(this.searchInput).toBeVisible().withTimeout(timeouts.TEN_SEC); + return this.addMembersScreen; + }; + + close = async () => { + await this.backButton.tap(); + await expect(this.addMembersScreen).not.toBeVisible(); + }; + + dismissTutorial = async () => { + try { + const tutorialText = element(by.text('Long-press on an item to view a user\'s profile')); + await waitFor(tutorialText).toBeVisible().withTimeout(timeouts.TWO_SEC); + await tutorialText.tap(); + await wait(timeouts.HALF_SEC); + } catch { + // Tutorial not visible, continue + } + }; + + searchAndAddUser = async (username: string, userId: string) => { + await this.searchInput.typeText(`${username}\n`); + await wait(timeouts.TWO_SEC); + + const userItem = this.getUserItem(userId); + await waitFor(userItem).toBeVisible().withTimeout(timeouts.TEN_SEC); + await userItem.tap(); + await wait(timeouts.ONE_SEC); + + await waitFor(this.addChannelMembersButton).toBeVisible().withTimeout(timeouts.TEN_SEC); + await this.addChannelMembersButton.tap(); + await wait(timeouts.TWO_SEC); + }; +} + +const addMembersScreen = new AddMembersScreen(); +export default addMembersScreen; diff --git a/detox/e2e/support/ui/screen/channel.ts b/detox/e2e/support/ui/screen/channel.ts index 1a0220836..cb495ce99 100644 --- a/detox/e2e/support/ui/screen/channel.ts +++ b/detox/e2e/support/ui/screen/channel.ts @@ -17,7 +17,7 @@ import { PostOptionsScreen, ThreadScreen, } from '@support/ui/screen'; -import {isAndroid, isIos, timeouts, wait} from '@support/utils'; +import {isIos, timeouts, wait} from '@support/utils'; import {expect} from 'detox'; class ChannelScreen { @@ -153,13 +153,13 @@ class ChannelScreen { dismissScheduledPostTooltip = async () => { // Try to close scheduled post tooltip if it exists (try both regular and admin account versions) try { - await waitFor(this.scheduledPostTooltipCloseButton).toBeVisible().withTimeout(timeouts.ONE_SEC); + await waitFor(this.scheduledPostTooltipCloseButton).toBeVisible().withTimeout(timeouts.FOUR_SEC); await this.scheduledPostTooltipCloseButton.tap(); await wait(timeouts.HALF_SEC); } catch { // Try admin account version try { - await waitFor(this.scheduledPostTooltipCloseButtonAdminAccount).toBeVisible().withTimeout(timeouts.ONE_SEC); + await waitFor(this.scheduledPostTooltipCloseButtonAdminAccount).toBeVisible().withTimeout(timeouts.FOUR_SEC); await this.scheduledPostTooltipCloseButtonAdminAccount.tap(); await wait(timeouts.HALF_SEC); } catch { @@ -204,23 +204,6 @@ class ChannelScreen { } }; - dismissKeyboard = async () => { - // Explicitly dismiss keyboard before long press - if (isAndroid()) { - try { - await device.pressBack(); - await wait(timeouts.THREE_SEC); - } catch (error) { - // Keyboard might not be open, continue - } - } - if (isIos()) { - // On iOS, tap outside the input area to dismiss keyboard - await this.postInput.tapReturnKey(); - await wait(timeouts.TWO_SEC); - } - }; - openPostOptionsFor = async (postId: string, text: string) => { const {postListPostItem} = this.getPostListPostItem(postId, text); await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC); @@ -243,7 +226,7 @@ class ChannelScreen { // # Post message await this.postInput.tap(); await this.postInput.clearText(); - await this.postInput.typeText(message); + await this.postInput.replaceText(`${message}\n`); await this.tapSendButton(); await wait(timeouts.TWO_SEC); }; diff --git a/detox/e2e/support/ui/screen/channel_info.ts b/detox/e2e/support/ui/screen/channel_info.ts index 96dabe87e..5f57b14c3 100644 --- a/detox/e2e/support/ui/screen/channel_info.ts +++ b/detox/e2e/support/ui/screen/channel_info.ts @@ -233,6 +233,58 @@ class ChannelInfoScreen { unarchivePublicChannel = async ({confirm = true} = {}) => { await this.unarchiveChannel(Alert.unarchivePublicChannelTitle, {confirm}); }; + + copyChannelHeader = async (headerText: string) => { + // Long press on header text + await element(by.text(headerText)).longPress(); + + // Wait for bottom sheet + await waitFor(element(by.id('channel_info.extra.header.bottom_sheet.copy_header_text'))). + toBeVisible(). + withTimeout(timeouts.TWO_SEC); + + // Tap copy option (actual copy action) + await element(by.id('channel_info.extra.header.bottom_sheet.copy_header_text')).tap(); + }; + + cancelCopyChannelHeader = async (headerText: string) => { + // Long press on header text + await element(by.text(headerText)).longPress(); + + // Wait for bottom sheet + await waitFor(element(by.id('channel_info.extra.header.bottom_sheet.copy_header_text'))). + toBeVisible(). + withTimeout(timeouts.TWO_SEC); + + // Cancel + await element(by.id('channel_info.extra.header.bottom_sheet.cancel')).tap(); + }; + + copyChannelPurpose = async (purposeText: string) => { + // Long press on purpose text + await element(by.text(purposeText)).longPress(); + + // Wait for bottom sheet + await waitFor(element(by.id('channel_info.title.public_private.bottom_sheet.copy_purpose'))). + toBeVisible(). + withTimeout(timeouts.TWO_SEC); + + // Tap copy option + await element(by.id('channel_info.title.public_private.bottom_sheet.copy_purpose')).tap(); + }; + + cancelCopyChannelPurpose = async (purposeText: string) => { + // Long press on purpose text + await element(by.text(purposeText)).longPress(); + + // Wait for bottom sheet + await waitFor(element(by.id('channel_info.title.public_private.bottom_sheet.copy_purpose'))). + toBeVisible(). + withTimeout(timeouts.TWO_SEC); + + // Cancel + await element(by.id('channel_info.title.public_private.bottom_sheet.cancel')).tap(); + }; } const channelInfoScreen = new ChannelInfoScreen(); diff --git a/detox/e2e/support/ui/screen/create_direct_message.ts b/detox/e2e/support/ui/screen/create_direct_message.ts index 088608fb9..2ffbfab87 100644 --- a/detox/e2e/support/ui/screen/create_direct_message.ts +++ b/detox/e2e/support/ui/screen/create_direct_message.ts @@ -77,7 +77,7 @@ class CreateDirectMessageScreen { await ChannelListScreen.headerPlusButton.tap(); await wait(timeouts.ONE_SEC); await ChannelListScreen.openDirectMessageItem.tap(); - await wait(timeouts.TEN_SEC); + await wait(timeouts.FOUR_SEC); return this.toBeVisible(); }; diff --git a/detox/e2e/support/ui/screen/index.ts b/detox/e2e/support/ui/screen/index.ts index a941876f6..3e0a4e9cf 100644 --- a/detox/e2e/support/ui/screen/index.ts +++ b/detox/e2e/support/ui/screen/index.ts @@ -3,6 +3,7 @@ import AboutScreen from './about'; import AccountScreen from './account'; +import AddMembersScreen from './add_members'; import AdvancedSettingsScreen from './advanced_settings'; import AutoResponderNotificationSettingsScreen from './auto_responder_notification_settings'; import BrowseChannelsScreen from './browse_channels'; @@ -55,6 +56,7 @@ import UserProfileScreen from './user_profile'; export { AboutScreen, AccountScreen, + AddMembersScreen, AdvancedSettingsScreen, AutoResponderNotificationSettingsScreen, BrowseChannelsScreen, diff --git a/detox/e2e/support/ui/screen/login.ts b/detox/e2e/support/ui/screen/login.ts index 5b76c5976..735c047ff 100644 --- a/detox/e2e/support/ui/screen/login.ts +++ b/detox/e2e/support/ui/screen/login.ts @@ -1,6 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +import {serverOneUrl} from '@support/test_config'; import {ChannelListScreen, ServerScreen} from '@support/ui/screen'; import {isAndroid, retryWithReload, timeouts, wait} from '@support/utils'; import {expect} from 'detox'; @@ -79,7 +80,15 @@ class LoginScreen { while (attempt < maxAttempts) { try { // eslint-disable-next-line no-await-in-loop - await retryWithReload(() => this.loginWithRetryIfStuck(user)); + await retryWithReload( + async () => { + return this.loginWithRetryIfStuck(user); + }, + 3, // retries + ServerScreen, + serverOneUrl, // serverUrl - reconnect after reload + 'Server 1', // serverDisplayName + ); return; } catch (error) { lastError = error; diff --git a/detox/e2e/support/ui/screen/manage_channel_members.ts b/detox/e2e/support/ui/screen/manage_channel_members.ts index 513ed750b..225872c1a 100644 --- a/detox/e2e/support/ui/screen/manage_channel_members.ts +++ b/detox/e2e/support/ui/screen/manage_channel_members.ts @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {ProfilePicture} from '@support/ui/component'; +import {Alert, ProfilePicture} from '@support/ui/component'; import {ChannelInfoScreen} from '@support/ui/screen'; import {isIos, timeouts, wait} from '@support/utils'; import {expect, waitFor} from 'detox'; @@ -10,20 +10,28 @@ class ManageChannelMembersScreen { testID = { backButton: 'screen.back.button', manageMembersScreen: 'manage_members.screen', + channelMembersScreen: 'channel_members.screen', manageDoneButton: 'manage_members.button', // Same button, text changes between "Manage" and "Done" searchBar: 'manage_members.search_bar', + searchInput: 'manage_members.search_bar.search.input', userList: 'manage_members.user_list', - userItemPrefix: 'create_direct_message.user_list.user_item.', + userItemPrefix: 'manage_members.user_list.user_item.', + removeButton: 'channel.remove_member', notice: 'manage_members.notice', tutorialHighlight: 'tutorial_highlight', tutorialSwipeLeft: 'tutorial_swipe_left', + gmMemberSectionList: 'manage_members.user_list.section_list', }; + gmMemberSectionList = element(by.id(this.testID.gmMemberSectionList)); manageMembersScreen = element(by.id(this.testID.manageMembersScreen)); + channelMembersScreen = element(by.id(this.testID.channelMembersScreen)); manageButton = element(by.id(this.testID.manageDoneButton)); doneButton = element(by.id(this.testID.manageDoneButton)); // Same element as manageButton, different text searchBar = element(by.id(this.testID.searchBar)); + searchInput = element(by.id(this.testID.searchInput)); userList = element(by.id(this.testID.userList)); + removeButton = element(by.id(this.testID.removeButton)); notice = element(by.id(this.testID.notice)); tutorialHighlight = element(by.id(this.testID.tutorialHighlight)); tutorialSwipeLeft = element(by.id(this.testID.tutorialSwipeLeft)); @@ -91,6 +99,26 @@ class ManageChannelMembersScreen { console.log('Tutorial element not visible, skipping action:'); } }; + + searchAndRemoveUser = async (username: string, userId: string) => { + await expect(this.searchInput).toBeVisible(); + await this.searchInput.typeText(`${username}`); + await wait(timeouts.TWO_SEC); + + const userItem = this.getUserItem(userId); + await waitFor(userItem).toBeVisible().withTimeout(timeouts.TEN_SEC); + await userItem.tap(); + await wait(timeouts.TWO_SEC); + + await expect(this.removeButton).toBeVisible(); + await this.removeButton.tap(); + await wait(timeouts.TWO_SEC); + + await Alert.removeButton.tap(); + await wait(timeouts.TWO_SEC); + + await device.pressBack(); + }; } const manageChannelMembersScreen = new ManageChannelMembersScreen(); diff --git a/detox/e2e/support/ui/screen/server.ts b/detox/e2e/support/ui/screen/server.ts index fa71487c0..59867922d 100644 --- a/detox/e2e/support/ui/screen/server.ts +++ b/detox/e2e/support/ui/screen/server.ts @@ -75,7 +75,7 @@ class ServerScreen { // The bridge can be busy during login transition, use waitFor without idle check const timeout = isAndroid() ? timeouts.ONE_MIN : timeouts.HALF_MIN; - await waitFor(this.usernameInput).toBeVisible().withTimeout(timeout); + await waitForElementToBeVisible(this.usernameInput, timeout, timeouts.ONE_SEC); }; close = async () => { diff --git a/detox/e2e/support/ui/screen/thread.ts b/detox/e2e/support/ui/screen/thread.ts index 8a23b7db8..ad5c58c98 100644 --- a/detox/e2e/support/ui/screen/thread.ts +++ b/detox/e2e/support/ui/screen/thread.ts @@ -118,7 +118,7 @@ class ThreadScreen { postMessage = async (message: string) => { // # Post message await this.postInput.tap(); - await this.postInput.replaceText(message); + await this.postInput.replaceText(`${message}\n`); await this.tapSendButton(); // # Wait for message to be rendered diff --git a/detox/e2e/support/utils/detoxhelpers.ts b/detox/e2e/support/utils/detoxhelpers.ts index 74e8d9ba2..16bc0d6d7 100644 --- a/detox/e2e/support/utils/detoxhelpers.ts +++ b/detox/e2e/support/utils/detoxhelpers.ts @@ -24,58 +24,6 @@ export async function waitForLoadingSpinner(testID: string, timeout = 10000): Pr await waitFor(element(by.id(testID))).not.toBeVisible().withTimeout(timeout); } -/** - * Safely dismiss keyboard with retry logic - * Prevents keyboard input session invalidation errors - * @param maxAttempts - Maximum number of dismissal attempts - */ -export async function dismissKeyboardSafely(maxAttempts = 3): Promise { - /* eslint-disable no-await-in-loop, no-console */ - for (let attempt = 1; attempt <= maxAttempts; attempt++) { - try { - await device.pressBack(); // Works on both iOS (dismisses keyboard) and Android - // Wait a bit for keyboard to dismiss - await new Promise((resolve) => setTimeout(resolve, 300)); - return; - } catch (error) { - if (attempt === maxAttempts) { - // On final attempt, log warning but don't throw to prevent test failures - console.warn(`[dismissKeyboardSafely] Failed to dismiss keyboard after ${maxAttempts} attempts:`, error); - } else { - await new Promise((resolve) => setTimeout(resolve, 200)); - } - } - } - /* eslint-enable no-await-in-loop, no-console */ -} - -/** - * Perform text input with keyboard state verification - * Ensures text input session is valid before typing - * @param element - Detox element to type into - * @param text - Text to type - */ -export async function typeTextSafely(elementToType: Detox.IndexableNativeElement, text: string): Promise { - try { - // Tap element to ensure it's focused - await elementToType.tap(); - await new Promise((resolve) => setTimeout(resolve, 300)); - - // Type text - await elementToType.typeText(text); - } catch (error) { - // eslint-disable-next-line no-console - console.warn('[typeTextSafely] Text input failed, retrying:', error); - - // Retry once with dismissal and refocus - await dismissKeyboardSafely(); - await new Promise((resolve) => setTimeout(resolve, 500)); - await elementToType.tap(); - await new Promise((resolve) => setTimeout(resolve, 300)); - await elementToType.typeText(text); - } -} - /** * Retry an element visibility check with exponential backoff * Helps handle race conditions during navigation and UI transitions diff --git a/detox/e2e/support/utils/index.ts b/detox/e2e/support/utils/index.ts index 4b2362cb7..892da8378 100644 --- a/detox/e2e/support/utils/index.ts +++ b/detox/e2e/support/utils/index.ts @@ -83,10 +83,18 @@ export const timeouts = { * Retry a function with reload * @param {function} func - function to retry * @param {number} retries - number of retries + * @param {string} serverUrl - optional server URL to reconnect after reload + * @param {string} serverDisplayName - optional server display name to reconnect after reload * @return {Promise} - promise that resolves when the function succeeds * @throws {Error} - if the function fails after the specified number of retries */ -export async function retryWithReload(func: () => Promise, retries: number = 2): Promise { +export async function retryWithReload( + func: () => Promise, + retries: number = 2, + ServerScreen: any, + serverUrl?: string, + serverDisplayName?: string, +): Promise { for (let attempt = 0; attempt <= retries; attempt++) { try { // eslint-disable-next-line no-await-in-loop @@ -97,7 +105,14 @@ export async function retryWithReload(func: () => Promise, retries: number // eslint-disable-next-line no-await-in-loop await device.reloadReactNative(); // eslint-disable-next-line no-await-in-loop - await new Promise((res) => setTimeout(res, 3000)); + await new Promise((res) => setTimeout(res, 10000)); + + // If server connection details provided, reconnect after reload + if (serverUrl && serverDisplayName) { + // Dynamically import to avoid circular dependencies + // eslint-disable-next-line no-await-in-loop + await ServerScreen.connectToServer(serverUrl, serverDisplayName); + } } else { throw err; } diff --git a/detox/e2e/test/products/channels/account/custom_status.e2e.ts b/detox/e2e/test/products/channels/account/custom_status.e2e.ts index 9c1727447..30da8a996 100644 --- a/detox/e2e/test/products/channels/account/custom_status.e2e.ts +++ b/detox/e2e/test/products/channels/account/custom_status.e2e.ts @@ -394,7 +394,6 @@ describe('Account - Custom Status', () => { await ChannelListScreen.open(); await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(messageText); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem, postListPostItemHeaderDisplayName} = diff --git a/detox/e2e/test/products/channels/autocomplete/edit_post.e2e.ts b/detox/e2e/test/products/channels/autocomplete/edit_post.e2e.ts index 71d360553..270639133 100644 --- a/detox/e2e/test/products/channels/autocomplete/edit_post.e2e.ts +++ b/detox/e2e/test/products/channels/autocomplete/edit_post.e2e.ts @@ -45,7 +45,6 @@ describe('Autocomplete - Edit Post', () => { const message = `Messsage ${getRandomId()}`; await ChannelScreen.open(channelsCategory, channel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, channel.id); await ChannelScreen.openPostOptionsFor(post.id, message); await EditPostScreen.open(); diff --git a/detox/e2e/test/products/channels/channel_settings/channel_create_edit.e2e.ts b/detox/e2e/test/products/channels/channel_settings/channel_create_edit.e2e.ts new file mode 100644 index 000000000..4e4a4cb09 --- /dev/null +++ b/detox/e2e/test/products/channels/channel_settings/channel_create_edit.e2e.ts @@ -0,0 +1,276 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +/** + * Test Cases Included: + * - MM-T3201: RN apps Create public channel + * - MM-T3203: RN apps Create private channel + * - MM-T3199: RN apps Edit public channel + * - MM-T3206: RN apps Edit private channel + * - MM-T854: RN apps Channel can be created using 2 non-latin characters + * - MM-T867: RN apps Copying channel header text + * - MM-T865: RN apps Copying channel purpose text + */ + +import {Channel, Setup} from '@support/server_api'; +import { + serverOneUrl, + siteOneUrl, +} from '@support/test_config'; +import { + ChannelInfoScreen, + ChannelListScreen, + ChannelScreen, + CreateOrEditChannelScreen, + LoginScreen, + HomeScreen, + ServerScreen, +} from '@support/ui/screen'; +import {getRandomId, timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +describe('Channels', () => { + const serverOneDisplayName = 'Server 1'; + const channelsCategory = 'channels'; + let testUser: any; + let testTeam: any; + let publicChannelName: string; + let publicChannelDisplayName: string; + let privateChannelName: string; + let privateChannelDisplayName: string; + let channelWithMetadata: any; + + beforeAll(async () => { + const {user, team} = await Setup.apiInit(siteOneUrl); + testUser = user; + testTeam = team; + + // Create a channel with header and purpose for copy tests + const {channel: metadataChannel} = await Channel.apiCreateChannel(siteOneUrl, { + teamId: testTeam.id, + name: `channel-metadata-${getRandomId()}`, + displayName: `Channel Metadata ${getRandomId()}`, + type: 'O', + header: 'This is test header', + purpose: 'Test purpose for copying', + }); + channelWithMetadata = metadataChannel; + + await wait(timeouts.THREE_SEC); + await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, channelWithMetadata.id); + await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName); + await LoginScreen.login(testUser); + }); + + afterAll(async () => { + await HomeScreen.logout(); + }); + + it('MM-T3201 - RN apps Create public channel', async () => { + publicChannelName = `channel-${getRandomId()}`; + publicChannelDisplayName = publicChannelName.replace(/-/g, ' '); + const channelPurpose = 'This is a test purpose for the channel'; + const channelHeader = ':taco:'; + + await ChannelListScreen.headerPlusButton.tap(); + await ChannelListScreen.createNewChannelItem.tap(); + + await CreateOrEditChannelScreen.toBeVisible(); + await expect(CreateOrEditChannelScreen.displayNameInput).toBeVisible(); + await expect(CreateOrEditChannelScreen.createButton).toBeVisible(); + + await CreateOrEditChannelScreen.displayNameInput.replaceText(publicChannelDisplayName); + + await CreateOrEditChannelScreen.purposeInput.tap(); + await CreateOrEditChannelScreen.purposeInput.replaceText(channelPurpose); + + await CreateOrEditChannelScreen.headerInput.tap(); + await CreateOrEditChannelScreen.headerInput.replaceText(channelHeader); + + await CreateOrEditChannelScreen.createButton.tap(); + await ChannelScreen.dismissScheduledPostTooltip(); + + await ChannelScreen.toBeVisible(); + await expect(ChannelScreen.headerTitle).toHaveText(publicChannelDisplayName); + + await ChannelInfoScreen.open(); + await expect(ChannelInfoScreen.publicPrivateTitleDisplayName).toHaveText(publicChannelDisplayName); + await expect(ChannelInfoScreen.publicPrivateTitlePurpose).toHaveText(channelPurpose); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T3203 - RN apps Create private channel', async () => { + privateChannelName = `private-channel-${getRandomId()}`; + privateChannelDisplayName = privateChannelName.replace(/-/g, ' '); + const channelPurpose = 'This is a private test channel purpose'; + const channelHeader = 'Private channel header'; + + await ChannelListScreen.headerPlusButton.tap(); + await ChannelListScreen.createNewChannelItem.tap(); + + await CreateOrEditChannelScreen.toBeVisible(); + await expect(CreateOrEditChannelScreen.displayNameInput).toBeVisible(); + + await CreateOrEditChannelScreen.toggleMakePrivateOn(); + await expect(CreateOrEditChannelScreen.makePrivateToggledOn).toBeVisible(); + + await CreateOrEditChannelScreen.displayNameInput.replaceText(privateChannelDisplayName); + + await CreateOrEditChannelScreen.purposeInput.tap(); + await CreateOrEditChannelScreen.purposeInput.replaceText(channelPurpose); + + await CreateOrEditChannelScreen.headerInput.tap(); + await CreateOrEditChannelScreen.headerInput.replaceText(channelHeader); + + await CreateOrEditChannelScreen.createButton.tap(); + + await ChannelScreen.toBeVisible(); + await expect(ChannelScreen.headerTitle).toHaveText(privateChannelDisplayName); + + await ChannelInfoScreen.open(); + await expect(ChannelInfoScreen.publicPrivateTitleDisplayName).toHaveText(privateChannelDisplayName); + await expect(ChannelInfoScreen.publicPrivateTitlePurpose).toHaveText(channelPurpose); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T3199 - RN apps Edit public channel', async () => { + await ChannelScreen.open(channelsCategory, publicChannelName); + await ChannelInfoScreen.open(); + await CreateOrEditChannelScreen.openEditChannel(); + await expect(CreateOrEditChannelScreen.saveButton).toBeVisible(); + + const updatedDisplayName = publicChannelDisplayName + ' edited'; + await CreateOrEditChannelScreen.displayNameInput.clearText(); + await CreateOrEditChannelScreen.displayNameInput.replaceText(updatedDisplayName); + + const purposeText = 'Updated purpose for this channel'; + await CreateOrEditChannelScreen.purposeInput.tap(); + await CreateOrEditChannelScreen.purposeInput.clearText(); + await CreateOrEditChannelScreen.purposeInput.replaceText(purposeText); + + const headerLine1 = 'First line of header'; + await CreateOrEditChannelScreen.headerInput.tap(); + await CreateOrEditChannelScreen.headerInput.clearText(); + await CreateOrEditChannelScreen.headerInput.replaceText(headerLine1 + '\n'); + + const headerLine2 = 'Second line of header'; + await CreateOrEditChannelScreen.headerInput.replaceText(headerLine2); + + await CreateOrEditChannelScreen.saveButton.tap(); + + await wait(timeouts.TWO_SEC); + await ChannelInfoScreen.toBeVisible(); + await expect(ChannelInfoScreen.publicPrivateTitleDisplayName).toHaveText(updatedDisplayName); + await expect(ChannelInfoScreen.publicPrivateTitlePurpose).toHaveText(purposeText); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T3206 - RN apps Edit private channel', async () => { + await ChannelScreen.open(channelsCategory, privateChannelName); + await ChannelInfoScreen.open(); + await CreateOrEditChannelScreen.openEditChannel(); + await expect(CreateOrEditChannelScreen.saveButton).toBeVisible(); + + const updatedDisplayName = privateChannelDisplayName + ' edited'; + await CreateOrEditChannelScreen.displayNameInput.clearText(); + await CreateOrEditChannelScreen.displayNameInput.replaceText(updatedDisplayName); + + const purposeText = 'Updated purpose for private channel'; + await CreateOrEditChannelScreen.purposeInput.tap(); + await CreateOrEditChannelScreen.purposeInput.clearText(); + await CreateOrEditChannelScreen.purposeInput.replaceText(purposeText); + + const headerLine1 = 'First line of header'; + await CreateOrEditChannelScreen.headerInput.tap(); + await CreateOrEditChannelScreen.headerInput.clearText(); + await CreateOrEditChannelScreen.headerInput.replaceText(headerLine1 + '\n'); + + const headerLine2 = 'Second line of header'; + await CreateOrEditChannelScreen.headerInput.replaceText(headerLine2); + + await CreateOrEditChannelScreen.saveButton.tap(); + + await wait(timeouts.TWO_SEC); + await ChannelInfoScreen.toBeVisible(); + await expect(ChannelInfoScreen.publicPrivateTitleDisplayName).toHaveText(updatedDisplayName); + await expect(ChannelInfoScreen.publicPrivateTitlePurpose).toHaveText(purposeText); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T854 - RN apps Channel can be created using 2 non-latin characters', async () => { + await ChannelListScreen.headerPlusButton.tap(); + await ChannelListScreen.createNewChannelItem.tap(); + + await CreateOrEditChannelScreen.toBeVisible(); + + await wait(timeouts.ONE_SEC); + await CreateOrEditChannelScreen.toBeVisible(); + + const nonLatinChannelName = 'ÁÜ'; + await CreateOrEditChannelScreen.displayNameInput.replaceText(nonLatinChannelName); + await wait(timeouts.ONE_SEC); + + await CreateOrEditChannelScreen.createButton.tap(); + + await wait(timeouts.TWO_SEC); + + await ChannelScreen.dismissScheduledPostTooltip(); + + await ChannelScreen.toBeVisible(); + await expect(ChannelScreen.headerTitle).toHaveText(nonLatinChannelName); + + await ChannelScreen.back(); + }); + + it('MM-T867 - RN apps Copying channel header text', async () => { + // # Navigate to the channel with metadata + await ChannelScreen.open(channelsCategory, channelWithMetadata.name); + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + // * Verify header is visible + await expect(ChannelInfoScreen.extraHeader).toBeVisible(); + + // # Test long-press and cancel flow + await ChannelInfoScreen.cancelCopyChannelHeader(channelWithMetadata.header); + + // * Verify we're still on channel info screen + await expect(ChannelInfoScreen.channelInfoScreen).toBeVisible(); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T865 - RN apps Copying channel purpose text', async () => { + // # Navigate to the channel with metadata + await ChannelScreen.open(channelsCategory, channelWithMetadata.name); + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + // * Verify purpose is visible + await expect(ChannelInfoScreen.publicPrivateTitlePurpose).toBeVisible(); + + // # Test long-press and cancel flow + await ChannelInfoScreen.cancelCopyChannelPurpose(channelWithMetadata.purpose); + + // * Verify we're still on channel info screen + await expect(ChannelInfoScreen.channelInfoScreen).toBeVisible(); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); +}); diff --git a/detox/e2e/test/products/channels/channel_settings/channel_join_leave.e2e.ts b/detox/e2e/test/products/channels/channel_settings/channel_join_leave.e2e.ts new file mode 100644 index 000000000..e44d56d67 --- /dev/null +++ b/detox/e2e/test/products/channels/channel_settings/channel_join_leave.e2e.ts @@ -0,0 +1,123 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +/** + * Test Cases Included: + * - MM-T3200: RN apps Join existing channel + * - MM-T3202: RN apps Leave public channel + * - MM-T3207: RN apps Leave private channel + * - MM-T3188: RN apps Search for public channel Cancel search join channel + */ + +import {Channel, Setup} from '@support/server_api'; +import { + serverOneUrl, + siteOneUrl, +} from '@support/test_config'; +import {Alert} from '@support/ui/component'; +import { + BrowseChannelsScreen, + ChannelInfoScreen, + ChannelListScreen, + ChannelScreen, + LoginScreen, + ServerScreen, + HomeScreen, +} from '@support/ui/screen'; +import {timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +describe('Channels', () => { + const serverOneDisplayName = 'Server 1'; + const channelsCategory = 'channels'; + let testUser: any; + let testChannel: any; + let privateChannel: any; + + beforeAll(async () => { + const {user, channel, team} = await Setup.apiInit(siteOneUrl); + testUser = user; + testChannel = channel; + + const {channel: privateChannelData} = await Channel.apiCreateChannel(siteOneUrl, {type: 'P', prefix: 'channel', teamId: team.id}); + privateChannel = privateChannelData; + + await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, privateChannel.id); + await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName); + await LoginScreen.login(testUser); + }); + + afterAll(async () => { + await HomeScreen.logout(); + }); + + it('MM-T3200 - RN apps Join existing channel', async () => { + + await ChannelScreen.open(channelsCategory, testChannel.name); + await wait(timeouts.TWO_SEC); + const joinMessage = `${testUser.username} joined the channel`; + await waitFor(element(by.text(joinMessage).withAncestor(by.id('post_list')))). + toBeVisible(); + + await ChannelScreen.back(); + }); + + it('MM-T3202 - RN apps Leave public channel', async () => { + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelInfoScreen.open(); + await ChannelInfoScreen.scrollView.scrollTo('bottom'); + await expect(ChannelInfoScreen.leaveChannelOption).toBeVisible(); + await ChannelInfoScreen.leaveChannelOption.tap(); + + await wait(timeouts.ONE_SEC); + const leaveAlertTitle = 'Leave channel'; + await expect(element(by.text(leaveAlertTitle))).toBeVisible(); + await expect(element(by.text(`Are you sure you want to leave the public channel ${testChannel.display_name}? You can always rejoin.`))).toBeVisible(); + + await Alert.leaveButton.tap(); + await wait(timeouts.TWO_SEC); + await ChannelListScreen.toBeVisible(); + }); + + it('MM-T3207 - RN apps Leave private channel', async () => { + + await ChannelScreen.open(channelsCategory, privateChannel.name); + await ChannelInfoScreen.open(); + await ChannelInfoScreen.scrollView.scrollTo('bottom'); + + await expect(ChannelInfoScreen.leaveChannelOption).toBeVisible(); + await ChannelInfoScreen.leaveChannelOption.tap(); + + await wait(timeouts.ONE_SEC); + await expect(element(by.text('Leave channel'))).toBeVisible(); + await expect(element(by.text(`Are you sure you want to leave the private channel ${privateChannel.display_name}? You cannot rejoin the channel unless you're invited again.`))).toBeVisible(); + await Alert.leaveButton.tap(); + + await wait(timeouts.TWO_SEC); + await ChannelListScreen.toBeVisible(); + }); + + it('MM-T3188 - RN apps Search for public channel Cancel search join channel', async () => { + const channelName = testChannel.name; + + await BrowseChannelsScreen.open(); + + const searchTerm = channelName.substring(0, 4); + await BrowseChannelsScreen.searchInput.typeText(searchTerm); + await wait(timeouts.TWO_SEC); + + await expect(BrowseChannelsScreen.getChannelItemDisplayName(testChannel.name)).toHaveText(testChannel.display_name); + await BrowseChannelsScreen.getChannelItem(testChannel.name).multiTap(2); + await wait(timeouts.ONE_SEC); + + await ChannelScreen.toBeVisible(); + await expect(ChannelScreen.headerTitle).toHaveText(testChannel.display_name); + await ChannelScreen.back(); + }); +}); diff --git a/detox/e2e/test/products/channels/channel_settings/channel_members.e2e.ts b/detox/e2e/test/products/channels/channel_settings/channel_members.e2e.ts new file mode 100644 index 000000000..b113fefe4 --- /dev/null +++ b/detox/e2e/test/products/channels/channel_settings/channel_members.e2e.ts @@ -0,0 +1,332 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +/** + * Test Cases Included: + * - MM-T3195: RN apps Add members to channel + * - MM-T856: Add existing users to public channel from drop-down Add Members + * - MM-T3196: RN apps Manage members in channel + * - MM-T3204: RN apps Add user to private channel + * - MM-T3205: RN apps Remove user from private channel + * - MM-T878: RN apps View Members in GM + */ + +import {Channel, Setup, Team, User} from '@support/server_api'; +import { + serverOneUrl, + siteOneUrl, +} from '@support/test_config'; +import { + AddMembersScreen, + ChannelInfoScreen, + ChannelScreen, + CreateDirectMessageScreen, + HomeScreen, + LoginScreen, + ManageChannelMembersScreen, + ServerScreen, +} from '@support/ui/screen'; +import {isAndroid, timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +describe('Channels', () => { + const serverOneDisplayName = 'Server 1'; + const channelsCategory = 'channels'; + + // Base setup (shared across all tests) + let testUser: any; + let testTeam: any; + let testChannel: any; + + // Test-specific data + let addMemberUser: any; // For MM-T3195 + let user2: any; // For MM-T856 + let memberUser: any; // For MM-T3196 + let privateChannel1: any; // For MM-T3204 + let privUser: any; // For MM-T3204 + let privateChannel2: any; // For MM-T3205 + let removeMeUser: any; // For MM-T3205 + let gmUser1: any; // For MM-T878 + let gmUser2: any; // For MM-T878 + + beforeAll(async () => { + // 1. Base setup (shared across all tests) + const {user, team, channel} = await Setup.apiInit(siteOneUrl); + testUser = user; + testTeam = team; + testChannel = channel; + + // 2. Test 1 (MM-T3195): User for adding to channel + const {user: newUser1} = await User.apiCreateUser(siteOneUrl, {prefix: 'addmember'}); + await Team.apiAddUserToTeam(siteOneUrl, newUser1.id, testTeam.id); + addMemberUser = newUser1; + + // 3. Test 2 (MM-T856): Another user for adding to channel + const {user: newUser2} = await User.apiCreateUser(siteOneUrl, {prefix: 'user2'}); + await Team.apiAddUserToTeam(siteOneUrl, newUser2.id, testTeam.id); + user2 = newUser2; + + // 4. Test 3 (MM-T3196): User already in channel for removal + const {user: newUser3} = await User.apiCreateUser(siteOneUrl, {prefix: 'member'}); + await Team.apiAddUserToTeam(siteOneUrl, newUser3.id, testTeam.id); + await Channel.apiAddUserToChannel(siteOneUrl, newUser3.id, testChannel.id); + memberUser = newUser3; + + // 5. Test 4 (MM-T3204): Private channel + user to add + const {channel: privChan1} = await Channel.apiCreateChannel(siteOneUrl, { + teamId: testTeam.id, + type: 'P', + }); + await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, privChan1.id); + privateChannel1 = privChan1; + + const {user: newUser4} = await User.apiCreateUser(siteOneUrl, {prefix: 'privuser'}); + await Team.apiAddUserToTeam(siteOneUrl, newUser4.id, testTeam.id); + privUser = newUser4; + + // 6. Test 5 (MM-T3205): Private channel + user already in it for removal + const {channel: privChan2} = await Channel.apiCreateChannel(siteOneUrl, { + teamId: testTeam.id, + type: 'P', + }); + await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, privChan2.id); + privateChannel2 = privChan2; + + const {user: newUser5} = await User.apiCreateUser(siteOneUrl, {prefix: 'removeme'}); + await Team.apiAddUserToTeam(siteOneUrl, newUser5.id, testTeam.id); + await Channel.apiAddUserToChannel(siteOneUrl, newUser5.id, privChan2.id); + removeMeUser = newUser5; + + // 7. Test 6 (MM-T878): Two users for GM creation + const {user: gmUserOne} = await User.apiCreateUser(siteOneUrl, {prefix: 'gmuser1'}); + await wait(timeouts.ONE_SEC); + const {user: gmUserTwo} = await User.apiCreateUser(siteOneUrl, {prefix: 'gmuser2'}); + await wait(timeouts.ONE_SEC); + await Team.apiAddUserToTeam(siteOneUrl, gmUserOne.id, testTeam.id); + await wait(timeouts.ONE_SEC); + await Team.apiAddUserToTeam(siteOneUrl, gmUserTwo.id, testTeam.id); + await wait(timeouts.ONE_SEC); + gmUser1 = gmUserOne; + gmUser2 = gmUserTwo; + + // 8. Login once with test user + await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName); + await LoginScreen.login(testUser); + }); + + afterAll(async () => { + // # Log out + await HomeScreen.logout(); + }); + + it('MM-T3195 - RN apps Add members to channel', async () => { + // # Use pre-created user + const newUser = addMemberUser; + + // # Open default test channel + await ChannelScreen.open(channelsCategory, testChannel.name); + + // # Open channel info and tap add members + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + await expect(ChannelInfoScreen.addMembersAction).toBeVisible(); + await ChannelInfoScreen.addMembersAction.tap(); + await wait(timeouts.TWO_SEC); + + // # Dismiss tutorial if present + await AddMembersScreen.dismissTutorial(); + await AddMembersScreen.toBeVisible(); + + // # Search and add user + await AddMembersScreen.searchAndAddUser(newUser.username, newUser.id); + + // * Verify user added system message appears + await ChannelScreen.toBeVisible(); + await wait(timeouts.TWO_SEC); + + const systemMessage = `${newUser.username} added to the channel by ${testUser.username}`; + await waitFor(element(by.text(systemMessage).withAncestor(by.id('post_list')))). + toBeVisible(); + await ChannelScreen.back(); + + }); + + it('MM-T856 - Add existing users to public channel from drop-down Add Members', async () => { + // # Use pre-created user + const newUser = user2; + + // # Open default test channel + await ChannelScreen.open(channelsCategory, testChannel.name); + + // # Open channel info and tap add members + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + await expect(ChannelInfoScreen.addMembersAction).toBeVisible(); + await ChannelInfoScreen.addMembersAction.tap(); + await wait(timeouts.TWO_SEC); + + // # Dismiss tutorial if present and search and add user + await AddMembersScreen.dismissTutorial(); + await AddMembersScreen.toBeVisible(); + await AddMembersScreen.searchAndAddUser(newUser.username, newUser.id); + + // * Verify user added system message appears + await ChannelScreen.toBeVisible(); + await wait(timeouts.TWO_SEC); + + const systemMessage = `${newUser.username} added to the channel by ${testUser.username}`; + await waitFor(element(by.text(systemMessage).withAncestor(by.id('post_list')))). + toBeVisible(); + await ChannelScreen.back(); + }); + + it('MM-T3196 - RN apps Manage members in channel', async () => { + // # Use pre-created user (already in channel) + const removedUser = memberUser; + + // # Open default test channel + await ChannelScreen.open(channelsCategory, testChannel.name); + + // # Open channel info and tap members option + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + await expect(ChannelInfoScreen.membersOption).toBeVisible(); + await ChannelInfoScreen.membersOption.tap(); + + await wait(timeouts.TWO_SEC); + await element(by.text(isAndroid()? 'MANAGE': 'Manage')).tap(); + await wait(timeouts.TWO_SEC); + + // # Search and remove user + await ManageChannelMembersScreen.searchAndRemoveUser(removedUser.username, removedUser.id); + + // * Verify user removed system message appears + await ChannelInfoScreen.close(); + await ChannelScreen.toBeVisible(); + await wait(timeouts.TWO_SEC); + + const systemMessage = `${removedUser.username} was removed from the channel`; + await waitFor(element(by.text(systemMessage).withAncestor(by.id('post_list')))). + toBeVisible(); + await ChannelScreen.back(); + }); + + it('MM-T3204 - RN apps Add user to private channel', async () => { + // # Use pre-created private channel and user + const privateChannel = privateChannel1; + const newUser = privUser; + + // # Open private channel + await ChannelScreen.open(channelsCategory, privateChannel.name); + + // # Open channel info and tap add members + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + await expect(ChannelInfoScreen.addMembersAction).toBeVisible(); + await ChannelInfoScreen.addMembersAction.tap(); + await wait(timeouts.TWO_SEC); + + // # Dismiss tutorial if present and search and add user + await AddMembersScreen.dismissTutorial(); + await AddMembersScreen.toBeVisible(); + await AddMembersScreen.searchAndAddUser(newUser.username, newUser.id); + + // * Verify user added system message appears + await ChannelScreen.toBeVisible(); + await wait(timeouts.TWO_SEC); + + const systemMessage = `${newUser.username} added to the channel by ${testUser.username}`; + await waitFor(element(by.text(systemMessage).withAncestor(by.id('post_list')))). + toBeVisible(); + + await ChannelScreen.back(); + }); + + it('MM-T3205 - RN apps Remove user from private channel', async () => { + // # Use pre-created private channel and user (already in channel) + const privateChannel = privateChannel2; + const removedUser = removeMeUser; + + // # Open private channel + await ChannelScreen.open(channelsCategory, privateChannel.name); + + // # Open channel info and tap members option + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + await expect(ChannelInfoScreen.membersOption).toBeVisible(); + await ChannelInfoScreen.membersOption.tap(); + await wait(timeouts.TWO_SEC); + + await element(by.text(isAndroid()? 'MANAGE': 'Manage')).tap(); + await wait(timeouts.TWO_SEC); + + // # Search and remove user + await ManageChannelMembersScreen.searchAndRemoveUser(removedUser.username, removedUser.id); + + // * Verify user removed system message appears + await ChannelInfoScreen.close(); + await ChannelScreen.toBeVisible(); + await wait(timeouts.TWO_SEC); + + const systemMessage = `${removedUser.username} was removed from the channel`; + await waitFor(element(by.text(systemMessage).withAncestor(by.id('post_list')))). + toBeVisible(); + + await ChannelScreen.back(); + }); + + it('MM-T878 - RN apps View Members in GM', async () => { + + await CreateDirectMessageScreen.open(); + await CreateDirectMessageScreen.searchInput.replaceText(`${gmUser1.username}`); + await CreateDirectMessageScreen.searchInput.tapReturnKey(); + await wait(timeouts.ONE_SEC); + await CreateDirectMessageScreen.getUserItem(gmUser1.id).tap(); + + // * Verify the first new user is selected + await expect(CreateDirectMessageScreen.getSelectedDMUserDisplayName(gmUser1.id)).toBeVisible(); + + // # Search for the second new user and tap on the second new user item + await CreateDirectMessageScreen.searchInput.replaceText(`${gmUser2.username}`); + await CreateDirectMessageScreen.searchInput.tapReturnKey(); + await wait(timeouts.ONE_SEC); + await CreateDirectMessageScreen.getUserItem(gmUser2.id).tap(); + + // * Verify the second new user is selected + await expect(CreateDirectMessageScreen.getSelectedDMUserDisplayName(gmUser2.id)).toBeVisible(); + + // # Tap on start button + await CreateDirectMessageScreen.startButton.tap(); + await ChannelScreen.dismissScheduledPostTooltip(); + await ChannelScreen.toBeVisible(); + + // # Open channel info and tap members option + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + await expect(ChannelInfoScreen.membersOption).toBeVisible(); + await ChannelInfoScreen.membersOption.tap(); + await wait(timeouts.TWO_SEC); + + // * Verify members list is visible + await expect(ManageChannelMembersScreen.gmMemberSectionList).toBeVisible(); + + // # Go back + await ManageChannelMembersScreen.backButton.tap(); + await wait(timeouts.ONE_SEC); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); +}); diff --git a/detox/e2e/test/products/channels/channel_settings/channel_navigation.e2e.ts b/detox/e2e/test/products/channels/channel_settings/channel_navigation.e2e.ts new file mode 100644 index 000000000..5a4d8d8b7 --- /dev/null +++ b/detox/e2e/test/products/channels/channel_settings/channel_navigation.e2e.ts @@ -0,0 +1,152 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +import {Channel, Setup} from '@support/server_api'; +import { + serverOneUrl, + siteOneUrl, +} from '@support/test_config'; +import { + ChannelInfoScreen, + ChannelListScreen, + ChannelScreen, + FindChannelsScreen, + LoginScreen, + ServerScreen, + HomeScreen, +} from '@support/ui/screen'; +import {getRandomId, timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +describe('Channels', () => { + const serverOneDisplayName = 'Server 1'; + const channelsCategory = 'channels'; + const favoritesCategory = 'favorites'; + let testUser: any; + let testTeam: any; + let testChannel: any; + let archiveChannel: any; + + beforeAll(async () => { + const {user, channel, team} = await Setup.apiInit(siteOneUrl); + testUser = user; + testChannel = channel; + testTeam = team; + + // Create a separate channel for archiving test + const {channel: archiveCh} = await Channel.apiCreateChannel(siteOneUrl, { + teamId: testTeam.id, + name: `archive-test-${getRandomId()}`, + displayName: `Archive Test ${getRandomId()}`, + type: 'O', + }); + archiveChannel = archiveCh; + + await wait(timeouts.THREE_SEC); + await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, archiveChannel.id); + await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName); + await LoginScreen.login(testUser); + }); + + afterAll(async () => { + await HomeScreen.logout(); + }); + + it('MM-T3189 - RN apps Display channel list', async () => { + await expect(ChannelListScreen.channelListScreen).toBeVisible(); + await wait(timeouts.ONE_SEC); + }); + + it('MM-T3190 - RN apps Display Channel Info', async () => { + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.toBeVisible(); + + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + await expect(ChannelInfoScreen.channelInfoScreen).toBeVisible(); + await wait(timeouts.ONE_SEC); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T3191 - RN apps Change channel', async () => { + + await FindChannelsScreen.open(); + await wait(timeouts.ONE_SEC); + + const searchTerm = testChannel.name.substring(0, 3); + await FindChannelsScreen.searchInput.typeText(searchTerm); + await wait(timeouts.TWO_SEC); + + await expect(FindChannelsScreen.getFilteredChannelItem(testChannel.name)).toBeVisible(); + await FindChannelsScreen.getFilteredChannelItem(testChannel.name).tap(); + await wait(timeouts.ONE_SEC); + + await ChannelScreen.toBeVisible(); + await expect(ChannelScreen.headerTitle).toHaveText(testChannel.display_name); + await ChannelScreen.back(); + }); + + it('MM-T850 - RN apps Favorite a channel', async () => { + await ChannelScreen.open(channelsCategory, testChannel.name); + + await ChannelInfoScreen.open(); + await expect(ChannelInfoScreen.favoriteAction).toBeVisible(); + await ChannelInfoScreen.favoriteAction.tap(); + + await wait(timeouts.ONE_SEC); + await expect(ChannelInfoScreen.unfavoriteAction).toBeVisible(); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + + // * Verify channel is listed under favorites category + await expect(ChannelListScreen.getChannelItemDisplayName(favoritesCategory, testChannel.name)).toBeVisible(); + }); + + it('MM-T3192 - RN apps Un-favorite a channel', async () => { + await ChannelScreen.open(favoritesCategory, testChannel.name); + await ChannelInfoScreen.open(); + await expect(ChannelInfoScreen.unfavoriteAction).toBeVisible(); + + await ChannelInfoScreen.unfavoriteAction.tap(); + + await wait(timeouts.THREE_SEC); + await expect(ChannelInfoScreen.favoriteAction).toBeVisible(); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + + await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, testChannel.name)).toBeVisible(); + }); + + it('MM-T3197 - RN apps Archive public or private channel', async () => { + // # Navigate to the archive channel + await ChannelScreen.open(channelsCategory, archiveChannel.name); + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + // # Scroll to bottom to reveal archive option + await ChannelInfoScreen.scrollView.scrollTo('bottom'); + await wait(timeouts.ONE_SEC); + + // # Archive the channel + await ChannelInfoScreen.archivePublicChannel({confirm: true}); + + // * Verify channel info screen is closed + await wait(timeouts.TWO_SEC); + await expect(ChannelInfoScreen.channelInfoScreen).not.toBeVisible(); + + // * Verify we're back at channel list + await ChannelListScreen.toBeVisible(); + + // * Verify archived channel is not visible in the list + await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, archiveChannel.name)).not.toBeVisible(); + }); +}); diff --git a/detox/e2e/test/products/channels/channel_settings/channel_notifications.e2e.ts b/detox/e2e/test/products/channels/channel_settings/channel_notifications.e2e.ts new file mode 100644 index 000000000..65b750f49 --- /dev/null +++ b/detox/e2e/test/products/channels/channel_settings/channel_notifications.e2e.ts @@ -0,0 +1,64 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +import {Setup} from '@support/server_api'; +import { + serverOneUrl, + siteOneUrl, +} from '@support/test_config'; +import { + ChannelInfoScreen, + ChannelScreen, + LoginScreen, + ServerScreen, + HomeScreen, +} from '@support/ui/screen'; +import {timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +describe('Channels', () => { + const serverOneDisplayName = 'Server 1'; + const channelsCategory = 'channels'; + let testUser: any; + let testChannel: any; + + beforeAll(async () => { + const {user, channel} = await Setup.apiInit(siteOneUrl); + testUser = user; + testChannel = channel; + + await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName); + await LoginScreen.login(testUser); + }); + + afterAll(async () => { + await HomeScreen.logout(); + }); + + it('MM-T3198 - Channel notifications Mobile Push', async () => { + await ChannelScreen.open(channelsCategory, testChannel.name); + + await ChannelInfoScreen.open(); + await wait(timeouts.ONE_SEC); + + await expect(ChannelInfoScreen.notificationPreferenceOption).toBeVisible(); + await ChannelInfoScreen.notificationPreferenceOption.tap(); + await wait(timeouts.TWO_SEC); + + const notificationSettingsScreen = element(by.id('push_notification_settings.screen')); + await expect(notificationSettingsScreen).toBeVisible(); + + const backButton = element(by.id('screen.back.button')); + await backButton.tap(); + await wait(timeouts.ONE_SEC); + + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); +}); diff --git a/detox/e2e/test/products/channels/channel_settings/channel_system_messages.e2e.ts b/detox/e2e/test/products/channels/channel_settings/channel_system_messages.e2e.ts new file mode 100644 index 000000000..6db611346 --- /dev/null +++ b/detox/e2e/test/products/channels/channel_settings/channel_system_messages.e2e.ts @@ -0,0 +1,107 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +/** + * Test Cases Included: + * - MM-T858: Combined joinleave messages in public channel + */ + +import {Channel, Post, Setup, Team, User} from '@support/server_api'; +import { + serverOneUrl, + siteOneUrl, +} from '@support/test_config'; +import { + ChannelScreen, + LoginScreen, + ServerScreen, + HomeScreen, +} from '@support/ui/screen'; +import {timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +describe('Channels', () => { + const serverOneDisplayName = 'Server 1'; + const channelsCategory = 'channels'; + let testUser: any; + let testTeam: any; + let testChannel: any; + let user1: any; + let user5: any; + + beforeAll(async () => { + const {user, channel, team} = await Setup.apiInit(siteOneUrl); + testUser = user; + testTeam = team; + testChannel = channel; + + ({user: user1} = await User.apiCreateUser(siteOneUrl, {prefix: 'user1'})); + const {user: user2} = await User.apiCreateUser(siteOneUrl, {prefix: 'user2'}); + const {user: user3} = await User.apiCreateUser(siteOneUrl, {prefix: 'user3'}); + + await Team.apiAddUserToTeam(siteOneUrl, user1.id, testTeam.id); + await Team.apiAddUserToTeam(siteOneUrl, user2.id, testTeam.id); + await Team.apiAddUserToTeam(siteOneUrl, user3.id, testTeam.id); + + await Channel.apiAddUserToChannel(siteOneUrl, user1.id, testChannel.id); + await Channel.apiAddUserToChannel(siteOneUrl, user2.id, testChannel.id); + await Channel.apiAddUserToChannel(siteOneUrl, user3.id, testChannel.id); + await wait(timeouts.TWO_SEC); + + await Channel.apiRemoveUserFromChannel(siteOneUrl, testChannel.id, user1.id); + await wait(timeouts.TWO_SEC); + + const {user: user4} = await User.apiCreateUser(siteOneUrl, {prefix: 'user4'}); + await Team.apiAddUserToTeam(siteOneUrl, user4.id, testTeam.id); + await Channel.apiAddUserToChannel(siteOneUrl, user4.id, testChannel.id); + await wait(timeouts.TWO_SEC); + + await Post.apiCreatePost(siteOneUrl, { + channelId: testChannel.id, + message: 'Test message to interrupt system messages', + }); + await wait(timeouts.TWO_SEC); + + ({user: user5} = await User.apiCreateUser(siteOneUrl, {prefix: 'user5'})); + await Team.apiAddUserToTeam(siteOneUrl, user5.id, testTeam.id); + await Channel.apiAddUserToChannel(siteOneUrl, user5.id, testChannel.id); + await wait(timeouts.TWO_SEC); + + await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName); + await LoginScreen.login(testUser); + }); + + afterAll(async () => { + await HomeScreen.logout(); + }); + + it('MM-T858 - Combined joinleave messages in public channel', async () => { + // Verify the posts via API to ensure correct structure + const {posts} = await Post.apiGetPostsInChannel(siteOneUrl, testChannel.id); + + // Verify we have the expected post types (no expect needed) + const hasJoinPost = posts.some((p: { type: string }) => p.type === 'system_join_channel'); + const hasAddPosts = posts.filter((p: { type: string }) => p.type === 'system_add_to_channel').length >= 4; + const hasRemovePost = posts.some((p: { type: string }) => p.type === 'system_remove_from_channel'); + const hasRegularPost = posts.some((p: { message: string }) => p.message === 'Test message to interrupt system messages'); + + if (!hasJoinPost || !hasAddPosts || !hasRemovePost || !hasRegularPost) { + throw new Error(`Missing expected posts. Join: ${hasJoinPost}, Adds: ${hasAddPosts}, Remove: ${hasRemovePost}, Regular: ${hasRegularPost}`); + } + + // Now verify the UI displays these messages correctly + await ChannelScreen.open(channelsCategory, testChannel.name); + await wait(timeouts.TWO_SEC); + + // Verify the regular message is visible + await expect(element(by.text('Test message to interrupt system messages'))).toBeVisible(); + + await ChannelScreen.back(); + }); +}); diff --git a/detox/e2e/test/products/channels/channels/channel_post_list.e2e.ts b/detox/e2e/test/products/channels/channels/channel_post_list.e2e.ts index e270a0479..0c791200a 100644 --- a/detox/e2e/test/products/channels/channels/channel_post_list.e2e.ts +++ b/detox/e2e/test/products/channels/channels/channel_post_list.e2e.ts @@ -93,7 +93,6 @@ describe('Channels - Channel Post List', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open('channels', testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is added to post list const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); diff --git a/detox/e2e/test/interactive_dialog/interactive_dialog_plugin.e2e.ts b/detox/e2e/test/products/channels/interactive_dialog/interactive_dialog_plugin.e2e.ts similarity index 100% rename from detox/e2e/test/interactive_dialog/interactive_dialog_plugin.e2e.ts rename to detox/e2e/test/products/channels/interactive_dialog/interactive_dialog_plugin.e2e.ts diff --git a/detox/e2e/test/products/channels/messaging/channel_link.e2e.ts b/detox/e2e/test/products/channels/messaging/channel_link.e2e.ts index e15e17a67..0f84db162 100644 --- a/detox/e2e/test/products/channels/messaging/channel_link.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/channel_link.e2e.ts @@ -23,7 +23,6 @@ import { LoginScreen, ServerScreen, } from '@support/ui/screen'; -import channelScreen from '@support/ui/screen/channel'; import {timeouts, wait} from '@support/utils'; import {expect, waitFor} from 'detox'; @@ -62,7 +61,6 @@ describe('Messaging - Channel Link', () => { await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id); const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`; await ChannelScreen.postMessage(channelLink); - await channelScreen.dismissKeyboard(); // # Tap on channel link await element(by.text(channelLink)).tap(); @@ -82,7 +80,6 @@ describe('Messaging - Channel Link', () => { await Channel.apiAddUserToChannel(siteOneUrl, testUser.id, targetChannel.id); const channelLink = `${serverOneUrl}/${testTeam.name}/channels/${targetChannel.name}`; await ChannelScreen.postMessage(channelLink); - await channelScreen.dismissKeyboard(); // # Wait for keyboard to dismiss and message to be visible await wait(timeouts.TWO_SEC); diff --git a/detox/e2e/test/products/channels/messaging/emojis_and_reactions.e2e.ts b/detox/e2e/test/products/channels/messaging/emojis_and_reactions.e2e.ts index 8e919c695..6e4a2abcf 100644 --- a/detox/e2e/test/products/channels/messaging/emojis_and_reactions.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/emojis_and_reactions.e2e.ts @@ -60,7 +60,6 @@ describe('Messaging - Emojis and Reactions', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); await ChannelScreen.openPostOptionsFor(post.id, message); @@ -105,7 +104,6 @@ describe('Messaging - Emojis and Reactions', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); await ChannelScreen.openPostOptionsFor(post.id, message); await EmojiPickerScreen.open(); @@ -140,7 +138,6 @@ describe('Messaging - Emojis and Reactions', () => { const message = 'brown fox :fox_face: lazy dog :dog:'; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is posted with emojis const resolvedMessage = 'brown fox 🦊 lazy dog 🐶'; @@ -174,7 +171,6 @@ describe('Messaging - Emojis and Reactions', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const searchTerm = 'blahblahblahblah'; await ChannelScreen.openPostOptionsFor(post.id, message); diff --git a/detox/e2e/test/products/channels/messaging/follow_and_unfollow_messsage.e2e.ts b/detox/e2e/test/products/channels/messaging/follow_and_unfollow_messsage.e2e.ts index 869f6a1a0..d281ed745 100644 --- a/detox/e2e/test/products/channels/messaging/follow_and_unfollow_messsage.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/follow_and_unfollow_messsage.e2e.ts @@ -66,7 +66,6 @@ describe('Messaging - Follow and Unfollow Message', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // # Wait for keyboard to dismiss and message to be visible await wait(timeouts.ONE_SEC); @@ -106,7 +105,6 @@ describe('Messaging - Follow and Unfollow Message', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // # Wait for keyboard to dismiss and message to be visible await wait(timeouts.ONE_SEC); diff --git a/detox/e2e/test/products/channels/messaging/message_delete.e2e.ts b/detox/e2e/test/products/channels/messaging/message_delete.e2e.ts index ea4eb01bc..380e621a9 100644 --- a/detox/e2e/test/products/channels/messaging/message_delete.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/message_delete.e2e.ts @@ -56,7 +56,6 @@ describe('Messaging - Message Delete', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is added to post list const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -78,7 +77,6 @@ describe('Messaging - Message Delete', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is added to post list const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -100,7 +98,6 @@ describe('Messaging - Message Delete', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: parentPostListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, message); @@ -114,7 +111,6 @@ describe('Messaging - Message Delete', () => { // # Post a reply, open post options for the reply message, tap delete option and confirm const replyMessage = `${message} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage); diff --git a/detox/e2e/test/products/channels/messaging/message_edit.e2e.ts b/detox/e2e/test/products/channels/messaging/message_edit.e2e.ts index 86165770d..979df80a1 100644 --- a/detox/e2e/test/products/channels/messaging/message_edit.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/message_edit.e2e.ts @@ -57,7 +57,6 @@ describe('Messaging - Message Edit', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is added to post list const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -95,7 +94,6 @@ describe('Messaging - Message Edit', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is added to post list const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -129,7 +127,6 @@ describe('Messaging - Message Edit', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: parentPostListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, message); @@ -143,7 +140,6 @@ describe('Messaging - Message Edit', () => { // # Post a reply, open post options for the reply message and tap edit option const replyMessage = `${message} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage); diff --git a/detox/e2e/test/products/channels/messaging/message_reply.e2e.ts b/detox/e2e/test/products/channels/messaging/message_reply.e2e.ts index 2c4d3b796..e3684aa5f 100644 --- a/detox/e2e/test/products/channels/messaging/message_reply.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/message_reply.e2e.ts @@ -61,7 +61,6 @@ describe('Messaging - Message Reply', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is added to post list const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -80,7 +79,6 @@ describe('Messaging - Message Reply', () => { // # Reply to parent post const replyMessage = `${message} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); // * Verify reply message is posted const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -96,7 +94,6 @@ describe('Messaging - Message Reply', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is added to post list const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -118,7 +115,6 @@ describe('Messaging - Message Reply', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message); diff --git a/detox/e2e/test/products/channels/messaging/pin_and_unpin_message.e2e.ts b/detox/e2e/test/products/channels/messaging/pin_and_unpin_message.e2e.ts index 2609c7bce..41d7fe0cd 100644 --- a/detox/e2e/test/products/channels/messaging/pin_and_unpin_message.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/pin_and_unpin_message.e2e.ts @@ -57,7 +57,6 @@ describe('Messaging - Pin and Unpin Message', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is posted const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -90,7 +89,7 @@ describe('Messaging - Pin and Unpin Message', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); + const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message); await expect(postListPostItem).toBeVisible(); diff --git a/detox/e2e/test/products/channels/messaging/save_and_unsave_message.e2e.ts b/detox/e2e/test/products/channels/messaging/save_and_unsave_message.e2e.ts index 39266d46c..8e3422224 100644 --- a/detox/e2e/test/products/channels/messaging/save_and_unsave_message.e2e.ts +++ b/detox/e2e/test/products/channels/messaging/save_and_unsave_message.e2e.ts @@ -57,7 +57,6 @@ describe('Messaging - Save and Unsave Message', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); // * Verify message is posted const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -90,7 +89,6 @@ describe('Messaging - Save and Unsave Message', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message); diff --git a/detox/e2e/test/products/channels/search/pinned_messages.e2e.ts b/detox/e2e/test/products/channels/search/pinned_messages.e2e.ts index 687c076e1..3e8137f47 100644 --- a/detox/e2e/test/products/channels/search/pinned_messages.e2e.ts +++ b/detox/e2e/test/products/channels/search/pinned_messages.e2e.ts @@ -73,7 +73,6 @@ describe('Search - Pinned Messages', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(post.id, message); @@ -115,7 +114,6 @@ describe('Search - Pinned Messages', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(pinnedPost.id, message); @@ -156,7 +154,6 @@ describe('Search - Pinned Messages', () => { // # Post a reply const replyMessage = `${updatedMessage} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); // * Verify reply is posted const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -189,7 +186,6 @@ describe('Search - Pinned Messages', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(pinnedPost.id, message); @@ -223,7 +219,6 @@ describe('Search - Pinned Messages', () => { const message = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(message); - await ChannelScreen.dismissKeyboard(); const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem: channelPostItem} = ChannelScreen.getPostListPostItem(pinnedPost.id, message); diff --git a/detox/e2e/test/products/channels/threads/follow_and_unfollow_thread.e2e.ts b/detox/e2e/test/products/channels/threads/follow_and_unfollow_thread.e2e.ts index 25ccb0085..92f8ffbc1 100644 --- a/detox/e2e/test/products/channels/threads/follow_and_unfollow_thread.e2e.ts +++ b/detox/e2e/test/products/channels/threads/follow_and_unfollow_thread.e2e.ts @@ -58,7 +58,6 @@ describe('Threads - Follow and Unfollow Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage); await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC); @@ -93,7 +92,6 @@ describe('Threads - Follow and Unfollow Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); await ThreadScreen.postMessage(`${parentMessage} reply`); @@ -126,7 +124,6 @@ describe('Threads - Follow and Unfollow Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); await ThreadScreen.postMessage(`${parentMessage} reply`); @@ -175,7 +172,6 @@ describe('Threads - Follow and Unfollow Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); const replyMessage = `${parentMessage} reply`; diff --git a/detox/e2e/test/products/channels/threads/global_threads.e2e.ts b/detox/e2e/test/products/channels/threads/global_threads.e2e.ts index 4a9e29054..b23832cb9 100644 --- a/detox/e2e/test/products/channels/threads/global_threads.e2e.ts +++ b/detox/e2e/test/products/channels/threads/global_threads.e2e.ts @@ -72,7 +72,6 @@ describe('Threads - Global Threads', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); diff --git a/detox/e2e/test/products/channels/threads/open_thread_in_channel.e2e.ts b/detox/e2e/test/products/channels/threads/open_thread_in_channel.e2e.ts index 06b2bf002..e0ef39d26 100644 --- a/detox/e2e/test/products/channels/threads/open_thread_in_channel.e2e.ts +++ b/detox/e2e/test/products/channels/threads/open_thread_in_channel.e2e.ts @@ -58,7 +58,6 @@ describe('Threads - Open Thread in Channel', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); await ChannelScreen.dismissScheduledPostTooltip(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage); @@ -100,7 +99,6 @@ describe('Threads - Open Thread in Channel', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage); await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.FOUR_SEC); diff --git a/detox/e2e/test/products/channels/threads/reply_to_thread.e2e.ts b/detox/e2e/test/products/channels/threads/reply_to_thread.e2e.ts index 272c44386..2e1950ff7 100644 --- a/detox/e2e/test/products/channels/threads/reply_to_thread.e2e.ts +++ b/detox/e2e/test/products/channels/threads/reply_to_thread.e2e.ts @@ -57,7 +57,6 @@ describe('Threads - Reply to Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage); @@ -66,7 +65,6 @@ describe('Threads - Reply to Thread', () => { await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); const replyMessage = `${parentMessage} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); await ThreadScreen.back(); await ChannelScreen.back(); await GlobalThreadsScreen.open(); @@ -84,7 +82,6 @@ describe('Threads - Reply to Thread', () => { // # Add new reply to thread const newReplyMessage = `${parentMessage} new reply`; await ThreadScreen.postMessage(newReplyMessage); - await ChannelScreen.dismissKeyboard(); // * Verify new reply is posted const {post: newReplyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); @@ -101,14 +98,12 @@ describe('Threads - Reply to Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage); await waitFor(postListPostItem).toBeVisible().withTimeout(timeouts.TEN_SEC); await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); const replyMessage = `${parentMessage} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); await ThreadScreen.back(); await ChannelScreen.back(); @@ -126,7 +121,6 @@ describe('Threads - Reply to Thread', () => { // # Add new reply to thread const newReplyMessage = `${parentMessage} new reply`; await ThreadScreen.postMessage(newReplyMessage); - await ChannelScreen.dismissKeyboard(); // * Verify new reply is posted const {post: newReplyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); diff --git a/detox/e2e/test/products/channels/threads/save_and_unsave_thread.e2e.ts b/detox/e2e/test/products/channels/threads/save_and_unsave_thread.e2e.ts index 3e8069de9..fcc018508 100644 --- a/detox/e2e/test/products/channels/threads/save_and_unsave_thread.e2e.ts +++ b/detox/e2e/test/products/channels/threads/save_and_unsave_thread.e2e.ts @@ -58,7 +58,6 @@ describe('Threads - Save and Unsave Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); const {postListPostItem} = ChannelScreen.getPostListPostItem(parentPost.id, parentMessage); @@ -67,7 +66,6 @@ describe('Threads - Save and Unsave Thread', () => { await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); const replyMessage = `${parentMessage} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); await ThreadScreen.back(); await ChannelScreen.back(); await GlobalThreadsScreen.open(); @@ -103,12 +101,10 @@ describe('Threads - Save and Unsave Thread', () => { const parentMessage = `Message ${getRandomId()}`; await ChannelScreen.open(channelsCategory, testChannel.name); await ChannelScreen.postMessage(parentMessage); - await ChannelScreen.dismissKeyboard(); const {post: parentPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); await ChannelScreen.openReplyThreadFor(parentPost.id, parentMessage); const replyMessage = `${parentMessage} reply`; await ThreadScreen.postMessage(replyMessage); - await ChannelScreen.dismissKeyboard(); await ThreadScreen.back(); await ChannelScreen.back(); await GlobalThreadsScreen.open(); diff --git a/detox/e2e/test/setup.ts b/detox/e2e/test/setup.ts index b1b621c17..6459a0fc3 100644 --- a/detox/e2e/test/setup.ts +++ b/detox/e2e/test/setup.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. /* eslint-disable no-await-in-loop, no-console */ -import {cleanupAdbReversePorts, resetAdbServer} from '@support/adb_utils'; import {ClaudePromptHandler} from '@support/pilot/ClaudePromptHandler'; import {Plugin, System, User} from '@support/server_api'; import {siteOneUrl} from '@support/test_config'; @@ -111,40 +110,19 @@ export async function launchAppWithRetry(): Promise { } console.info(`✅ App launched successfully on attempt ${attempt}`); - return; // Success, exit the function + return; } catch (error) { lastError = error; console.warn(`❌ App launch failed on attempt ${attempt}/${MAX_RETRY_ATTEMPTS}: ${(error as Error).message}`); - // If this is the last attempt, don't wait if (attempt < MAX_RETRY_ATTEMPTS) { - // Check if this is an ADB port binding issue (Android-specific, common in CI) - const errorMessage = (error as Error).message; - const isAdbPortError = errorMessage.includes('cannot bind listener') || - errorMessage.includes('Address already in use') || - errorMessage.includes('adb'); - - // Only attempt ADB cleanup if we detect an ADB-related error - // These functions are safe no-ops on iOS - if (isAdbPortError) { - console.warn('Detected ADB-related error, attempting cleanup...'); - await cleanupAdbReversePorts(); - - // On second retry with port issues, also reset ADB server - if (attempt >= 2) { - console.warn('Multiple failures detected, attempting ADB server reset...'); - await resetAdbServer(); - } - } - console.warn(`Waiting ${RETRY_DELAY}ms before retrying...`); await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY)); } } } - // If we get here, all attempts failed throw new Error(`Failed to launch app after ${MAX_RETRY_ATTEMPTS} attempts. Last error: ${(lastError as Error).message}`); } @@ -153,28 +131,20 @@ export async function launchAppWithRetry(): Promise { * @returns {Promise} */ async function initializeClaudePromptHandler(): Promise { - if (process.env.ANTHROPIC_API_KEY) { + try { + if (!process.env.ANTHROPIC_API_KEY) { + return; + } const promptHandler = new ClaudePromptHandler(process.env.ANTHROPIC_API_KEY); pilot.init(promptHandler); - } else { - console.info('To use ClaudePromptHandler, please set the ANTHROPIC_API_KEY environment variable.'); + } catch (e) { + console.warn('Claude init failed, continuing without AI:', e); } } beforeAll(async () => { // Reset flag to ensure each test file starts with a clean app launch isFirstLaunch = true; - - await initializeClaudePromptHandler(); - - // Clean up any stale ADB reverse port mappings from previous runs - // This is crucial in CI where crashed tests may leave stale connections - await cleanupAdbReversePorts(); - - // Login as sysadmin and reset server configuration - await System.apiCheckSystemHealth(siteOneUrl); - await User.apiAdminLogin(siteOneUrl); - await Plugin.apiDisableNonPrepackagedPlugins(siteOneUrl); await launchAppWithRetry(); // Verify Detox connection is healthy after app launch @@ -182,28 +152,10 @@ beforeAll(async () => { // Wait for app to be fully ready (database initialized, bridge ready) await waitForAppReady(); -}); - -// Add this to speed up test cleanup -afterAll(async () => { - try { - // Dismiss keyboard if visible to prevent session invalidation issues - try { - await device.sendToHome(); - await new Promise((resolve) => setTimeout(resolve, 500)); - } catch (error) { - console.warn('[Teardown] Could not send app to home:', error); - } - - await device.terminateApp(); - } catch (error) { - console.error('[Teardown] Error terminating app:', error); - } - - // Clean up ADB connections after tests complete - try { - await cleanupAdbReversePorts(); - } catch (error) { - console.error('[Teardown] Error cleaning up ADB ports:', error); - } + await initializeClaudePromptHandler(); + + // Login as sysadmin and reset server configuration + await System.apiCheckSystemHealth(siteOneUrl); + await User.apiAdminLogin(siteOneUrl); + await Plugin.apiDisableNonPrepackagedPlugins(siteOneUrl); }); diff --git a/detox/package-lock.json b/detox/package-lock.json index a4b0f5298..08bdeccae 100644 --- a/detox/package-lock.json +++ b/detox/package-lock.json @@ -9,8 +9,8 @@ "@anthropic-ai/sdk": "^0.56.0" }, "devDependencies": { - "@aws-sdk/client-s3": "3.712.0", - "@aws-sdk/lib-storage": "3.712.0", + "@aws-sdk/client-s3": "3.937.0", + "@aws-sdk/lib-storage": "3.937.0", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/plugin-transform-modules-commonjs": "7.26.3", "@babel/plugin-transform-runtime": "7.25.9", @@ -28,7 +28,7 @@ "babel-plugin-module-resolver": "5.0.2", "client-oauth2": "4.3.3", "deepmerge": "4.3.1", - "detox": "20.46.3", + "detox": "20.47.0", "dotenv": "17.2.1", "form-data": "4.0.1", "jest": "29.7.0", @@ -292,703 +292,664 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.712.0.tgz", - "integrity": "sha512-Hq1IIwOFutmHtTz3mROR1XhTDL8rxcYbYw3ajjgeMJB5tjcvodpfkfz/L4dxXZMwqylWf6SNQNAiaGh5mlsGGQ==", + "version": "3.937.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.937.0.tgz", + "integrity": "sha512-ioeNe6HSc7PxjsUQY7foSHmgesxM5KwAeUtPhIHgKx99nrM+7xYCfW4FMvHypUzz7ZOvqlCdH7CEAZ8ParBvVg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.712.0", - "@aws-sdk/client-sts": "3.712.0", - "@aws-sdk/core": "3.709.0", - "@aws-sdk/credential-provider-node": "3.712.0", - "@aws-sdk/middleware-bucket-endpoint": "3.709.0", - "@aws-sdk/middleware-expect-continue": "3.709.0", - "@aws-sdk/middleware-flexible-checksums": "3.709.0", - "@aws-sdk/middleware-host-header": "3.709.0", - "@aws-sdk/middleware-location-constraint": "3.709.0", - "@aws-sdk/middleware-logger": "3.709.0", - "@aws-sdk/middleware-recursion-detection": "3.709.0", - "@aws-sdk/middleware-sdk-s3": "3.709.0", - "@aws-sdk/middleware-ssec": "3.709.0", - "@aws-sdk/middleware-user-agent": "3.709.0", - "@aws-sdk/region-config-resolver": "3.709.0", - "@aws-sdk/signature-v4-multi-region": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@aws-sdk/util-endpoints": "3.709.0", - "@aws-sdk/util-user-agent-browser": "3.709.0", - "@aws-sdk/util-user-agent-node": "3.712.0", - "@aws-sdk/xml-builder": "3.709.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/eventstream-serde-browser": "^3.0.14", - "@smithy/eventstream-serde-config-resolver": "^3.0.11", - "@smithy/eventstream-serde-node": "^3.0.13", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-blob-browser": "^3.1.10", - "@smithy/hash-node": "^3.0.11", - "@smithy/hash-stream-node": "^3.1.10", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/md5-js": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.5", - "@smithy/middleware-retry": "^3.0.30", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.30", - "@smithy/util-defaults-mode-node": "^3.0.30", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", - "@smithy/util-stream": "^3.3.2", - "@smithy/util-utf8": "^3.0.0", - "@smithy/util-waiter": "^3.2.0", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/credential-provider-node": "3.936.0", + "@aws-sdk/middleware-bucket-endpoint": "3.936.0", + "@aws-sdk/middleware-expect-continue": "3.936.0", + "@aws-sdk/middleware-flexible-checksums": "3.936.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-location-constraint": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-sdk-s3": "3.936.0", + "@aws-sdk/middleware-ssec": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.936.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/signature-v4-multi-region": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/eventstream-serde-browser": "^4.2.5", + "@smithy/eventstream-serde-config-resolver": "^4.3.5", + "@smithy/eventstream-serde-node": "^4.2.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-blob-browser": "^4.2.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/hash-stream-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/md5-js": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.5", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.712.0.tgz", - "integrity": "sha512-tBo/eW3YpZ9f3Q1qA7aA8uliNFJJX0OP7R2IUJ8t6rqVTk15wWCEPNmXzUZKgruDnKUfCaF4+r9q/Yy4fBc9PA==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.936.0.tgz", + "integrity": "sha512-0G73S2cDqYwJVvqL08eakj79MZG2QRaB56Ul8/Ps9oQxllr7DMI1IQ/N3j3xjxgpq/U36pkoFZ8aK1n7Sbr3IQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.709.0", - "@aws-sdk/middleware-host-header": "3.709.0", - "@aws-sdk/middleware-logger": "3.709.0", - "@aws-sdk/middleware-recursion-detection": "3.709.0", - "@aws-sdk/middleware-user-agent": "3.709.0", - "@aws-sdk/region-config-resolver": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@aws-sdk/util-endpoints": "3.709.0", - "@aws-sdk/util-user-agent-browser": "3.709.0", - "@aws-sdk/util-user-agent-node": "3.712.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-node": "^3.0.11", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.5", - "@smithy/middleware-retry": "^3.0.30", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.30", - "@smithy/util-defaults-mode-node": "^3.0.30", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", - "@smithy/util-utf8": "^3.0.0", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.936.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.712.0.tgz", - "integrity": "sha512-xNFrG9syrG6pxUP7Ld/nu3afQ9+rbJM9qrE+wDNz4VnNZ3vLiJty4fH85zBFhOQ5OF2DIJTWsFzXGi2FYjsCMA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.709.0", - "@aws-sdk/credential-provider-node": "3.712.0", - "@aws-sdk/middleware-host-header": "3.709.0", - "@aws-sdk/middleware-logger": "3.709.0", - "@aws-sdk/middleware-recursion-detection": "3.709.0", - "@aws-sdk/middleware-user-agent": "3.709.0", - "@aws-sdk/region-config-resolver": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@aws-sdk/util-endpoints": "3.709.0", - "@aws-sdk/util-user-agent-browser": "3.709.0", - "@aws-sdk/util-user-agent-node": "3.712.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-node": "^3.0.11", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.5", - "@smithy/middleware-retry": "^3.0.30", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.30", - "@smithy/util-defaults-mode-node": "^3.0.30", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.712.0" - } - }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.712.0.tgz", - "integrity": "sha512-gIO6BD+hkEe3GKQhbiFP0zcNQv0EkP1Cl9SOstxS+X9CeudEgVX/xEPUjyoFVkfkntPBJ1g0I1u5xOzzRExl4g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.712.0", - "@aws-sdk/core": "3.709.0", - "@aws-sdk/credential-provider-node": "3.712.0", - "@aws-sdk/middleware-host-header": "3.709.0", - "@aws-sdk/middleware-logger": "3.709.0", - "@aws-sdk/middleware-recursion-detection": "3.709.0", - "@aws-sdk/middleware-user-agent": "3.709.0", - "@aws-sdk/region-config-resolver": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@aws-sdk/util-endpoints": "3.709.0", - "@aws-sdk/util-user-agent-browser": "3.709.0", - "@aws-sdk/util-user-agent-node": "3.712.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-node": "^3.0.11", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.5", - "@smithy/middleware-retry": "^3.0.30", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.30", - "@smithy/util-defaults-mode-node": "^3.0.30", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/core": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.709.0.tgz", - "integrity": "sha512-7kuSpzdOTAE026j85wq/fN9UDZ70n0OHw81vFqMWwlEFtm5IQ/MRCLKcC4HkXxTdfy1PqFlmoXxWqeBa15tujw==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.936.0.tgz", + "integrity": "sha512-eGJ2ySUMvgtOziHhDRDLCrj473RJoL4J1vPjVM3NrKC/fF3/LoHjkut8AAnKmrW6a2uTzNKubigw8dEnpmpERw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/core": "^2.5.5", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/property-provider": "^3.1.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/signature-v4": "^4.2.4", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/util-middleware": "^3.0.11", - "fast-xml-parser": "4.4.1", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/xml-builder": "3.930.0", + "@smithy/core": "^3.18.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.709.0.tgz", - "integrity": "sha512-ZMAp9LSikvHDFVa84dKpQmow6wsg956Um20cKuioPpX2GGreJFur7oduD+tRJT6FtIOHn+64YH+0MwiXLhsaIQ==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.936.0.tgz", + "integrity": "sha512-dKajFuaugEA5i9gCKzOaVy9uTeZcApE+7Z5wdcZ6j40523fY1a56khDAUYkCfwqa7sHci4ccmxBkAo+fW1RChA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.709.0.tgz", - "integrity": "sha512-lIS7XLwCOyJnLD70f+VIRr8DNV1HPQe9oN6aguYrhoczqz7vDiVZLe3lh714cJqq9rdxzFypK5DqKHmcscMEPQ==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.936.0.tgz", + "integrity": "sha512-5FguODLXG1tWx/x8fBxH+GVrk7Hey2LbXV5h9SFzYCx/2h50URBm0+9hndg0Rd23+xzYe14F6SI9HA9c1sPnjg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/property-provider": "^3.1.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/util-stream": "^3.3.2", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.712.0.tgz", - "integrity": "sha512-sTsdQ/Fm/suqMdpjhMuss/5uKL18vcuWnNTQVrG9iGNRqZLbq65MXquwbUpgzfoUmIcH+4CrY6H2ebpTIECIag==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.936.0.tgz", + "integrity": "sha512-TbUv56ERQQujoHcLMcfL0Q6bVZfYF83gu/TjHkVkdSlHPOIKaG/mhE2XZSQzXv1cud6LlgeBbfzVAxJ+HPpffg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.709.0", - "@aws-sdk/credential-provider-env": "3.709.0", - "@aws-sdk/credential-provider-http": "3.709.0", - "@aws-sdk/credential-provider-process": "3.709.0", - "@aws-sdk/credential-provider-sso": "3.712.0", - "@aws-sdk/credential-provider-web-identity": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/credential-provider-imds": "^3.2.8", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/credential-provider-env": "3.936.0", + "@aws-sdk/credential-provider-http": "3.936.0", + "@aws-sdk/credential-provider-login": "3.936.0", + "@aws-sdk/credential-provider-process": "3.936.0", + "@aws-sdk/credential-provider-sso": "3.936.0", + "@aws-sdk/credential-provider-web-identity": "3.936.0", + "@aws-sdk/nested-clients": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.936.0.tgz", + "integrity": "sha512-8DVrdRqPyUU66gfV7VZNToh56ZuO5D6agWrkLQE/xbLJOm2RbeRgh6buz7CqV8ipRd6m+zCl9mM4F3osQLZn8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.936.0", + "@aws-sdk/nested-clients": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.712.0" + "engines": { + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.712.0.tgz", - "integrity": "sha512-gXrHymW3rMRYORkPVQwL8Gi5Lu92F16SoZR543x03qCi7rm00oL9tRD85ACxkhprS1Wh8lUIUMNoeiwnYWTNuQ==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.936.0.tgz", + "integrity": "sha512-rk/2PCtxX9xDsQW8p5Yjoca3StqmQcSfkmD7nQ61AqAHL1YgpSQWqHE+HjfGGiHDYKG7PvE33Ku2GyA7lEIJAw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.709.0", - "@aws-sdk/credential-provider-http": "3.709.0", - "@aws-sdk/credential-provider-ini": "3.712.0", - "@aws-sdk/credential-provider-process": "3.709.0", - "@aws-sdk/credential-provider-sso": "3.712.0", - "@aws-sdk/credential-provider-web-identity": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/credential-provider-imds": "^3.2.8", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/credential-provider-env": "3.936.0", + "@aws-sdk/credential-provider-http": "3.936.0", + "@aws-sdk/credential-provider-ini": "3.936.0", + "@aws-sdk/credential-provider-process": "3.936.0", + "@aws-sdk/credential-provider-sso": "3.936.0", + "@aws-sdk/credential-provider-web-identity": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.709.0.tgz", - "integrity": "sha512-IAC+jPlGQII6jhIylHOwh3RgSobqlgL59nw2qYTURr8hMCI0Z1p5y2ee646HTVt4WeCYyzUAXfxr6YI/Vitv+Q==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.936.0.tgz", + "integrity": "sha512-GpA4AcHb96KQK2PSPUyvChvrsEKiLhQ5NWjeef2IZ3Jc8JoosiedYqp6yhZR+S8cTysuvx56WyJIJc8y8OTrLA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.712.0.tgz", - "integrity": "sha512-8lCMxY7Lb9VK9qdlNXRJXE3W1UDVURnJZ3a4XWYNY6yr1TfQaN40mMyXX1oNlXXJtMV0szRvjM8dZj37E/ESAw==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.936.0.tgz", + "integrity": "sha512-wHlEAJJvtnSyxTfNhN98JcU4taA1ED2JvuI2eePgawqBwS/Tzi0mhED1lvNIaWOkjfLd+nHALwszGrtJwEq4yQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.712.0", - "@aws-sdk/core": "3.709.0", - "@aws-sdk/token-providers": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/client-sso": "3.936.0", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/token-providers": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.709.0.tgz", - "integrity": "sha512-2lbDfE0IQ6gma/7BB2JpkjW5G0wGe4AS0x80oybYAYYviJmUtIR3Cn2pXun6bnAWElt4wYKl4su7oC36rs5rNA==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.936.0.tgz", + "integrity": "sha512-v3qHAuoODkoRXsAF4RG+ZVO6q2P9yYBT4GMpMEfU9wXVNn7AIfwZgTwzSUfnjNiGva5BKleWVpRpJ9DeuLFbUg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/nested-clients": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sts": "^3.709.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.712.0.tgz", - "integrity": "sha512-wVIgJCHMn4Rgq0PR1Y5na2onSCZfcGKM4iseF8VN0v/hxiqckBu28OrwqFVbgAGvC2Vzfy6NwfaXSu3ibWTrGg==", + "version": "3.937.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.937.0.tgz", + "integrity": "sha512-G+AxZX14MaVUT93BGeG17yBC+rR5yOOvE0QLpSViSARjPLI7el1zEEpOzC18OKIchFoM81VfC0xavfNMIp/bfw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^3.1.9", - "@smithy/middleware-endpoint": "^3.2.5", - "@smithy/smithy-client": "^3.5.0", + "@smithy/abort-controller": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/smithy-client": "^4.9.8", "buffer": "5.6.0", "events": "3.3.0", "stream-browserify": "3.0.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-s3": "^3.712.0" + "@aws-sdk/client-s3": "^3.937.0" } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.709.0.tgz", - "integrity": "sha512-03+tJOd7KIZOiqWH7Z8BOfQIWkKJgjcpKOJKZ6FR2KjWGUOE1G+bo11wF4UuHQ0RmpKnApt+pQghZmSnE7WEeg==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.936.0.tgz", + "integrity": "sha512-XLSVVfAorUxZh6dzF+HTOp4R1B5EQcdpGcPliWr0KUj2jukgjZEcqbBmjyMF/p9bmyQsONX80iURF1HLAlW0qg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@aws-sdk/util-arn-parser": "3.693.0", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-config-provider": "^3.0.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.709.0.tgz", - "integrity": "sha512-Tbl/DFvE4rHl8lMb9IzetwK4tf5R3VeHZkvEXQalsWoK0tbEQ8kXWi7wAYO4qbE7bFVvaxKX+irjJjTxf3BrCQ==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.936.0.tgz", + "integrity": "sha512-Eb4ELAC23bEQLJmUMYnPWcjD3FZIsmz2svDiXEcxRkQU9r7NRID7pM7C5NPH94wOfiCk0b2Y8rVyFXW0lGQwbA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.936.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.709.0.tgz", - "integrity": "sha512-wbYm9tkyCaqMeU82yjaXw7V5BxCSlSLNupENW63LC7Fvyo/aQzj6LjSMHcBpR2QwjBEhXCtF47L7aQ8SPTNhdw==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.936.0.tgz", + "integrity": "sha512-l3GG6CrSQtMCM6fWY7foV3JQv0WJWT+3G6PSP3Ceb/KEE/5Lz5PrYFXTBf+bVoYL1b0bGjGajcgAXpstBmtHtQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-stream": "^3.3.2", - "@smithy/util-utf8": "^3.0.0", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.709.0.tgz", - "integrity": "sha512-8gQYCYAaIw4lOCd5WYdf15Y/61MgRsAnrb2eiTl+icMlUOOzl8aOl5iDwm/Idp0oHZTflwxM4XSvGXO83PRWcw==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz", + "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.936.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.709.0.tgz", - "integrity": "sha512-5YQWPXfZq7OE0jB2G0PP8K10GBod/YPJXb+1CfJS6FbQaglRoIm8KZmVEvJNnptSKyGtE62veeCcCQcfAUfFig==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.936.0.tgz", + "integrity": "sha512-SCMPenDtQMd9o5da9JzkHz838w3327iqXk3cbNnXWqnNRx6unyW8FL0DZ84gIY12kAyVHz5WEqlWuekc15ehfw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.709.0.tgz", - "integrity": "sha512-jDoGSccXv9zebnpUoisjWd5u5ZPIalrmm6TjvPzZ8UqzQt3Beiz0tnQwmxQD6KRc7ADweWP5Ntiqzbw9xpVajg==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz", + "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.709.0.tgz", - "integrity": "sha512-PObL/wLr4lkfbQ0yXUWaoCWu/jcwfwZzCjsUiXW/H6hW9b/00enZxmx7OhtJYaR6xmh/Lcx5wbhIoDCbzdv0tw==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz", + "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.936.0", + "@aws/lambda-invoke-store": "^0.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.709.0.tgz", - "integrity": "sha512-FwtOG9t9xsLoLOQZ6qAdsWOjx9dsO6t28IjIDV1l6Ixiu2oC0Yks7goONjJUH0IDE4pDDDGzmuq0sn1XtHhheA==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.936.0.tgz", + "integrity": "sha512-UQs/pVq4cOygsnKON0pOdSKIWkfgY0dzq4h+fR+xHi/Ng3XzxPJhWeAE6tDsKrcyQc1X8UdSbS70XkfGYr5hng==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@aws-sdk/util-arn-parser": "3.693.0", - "@smithy/core": "^2.5.5", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/protocol-http": "^4.1.8", - "@smithy/signature-v4": "^4.2.4", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-stream": "^3.3.2", - "@smithy/util-utf8": "^3.0.0", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/core": "^3.18.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.709.0.tgz", - "integrity": "sha512-2muiLe7YkmlwZp2SKz+goZrDThGfRq3o0FcJF3Puc0XGmcEPEDjih537mCoTrGgcXNFlBc7YChd84r3t72ySaQ==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.936.0.tgz", + "integrity": "sha512-/GLC9lZdVp05ozRik5KsuODR/N7j+W+2TbfdFL3iS+7un+gnP6hC8RDOZd6WhpZp7drXQ9guKiTAxkZQwzS8DA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.709.0.tgz", - "integrity": "sha512-ooc9ZJvgkjPhi9q05XwSfNTXkEBEIfL4hleo5rQBKwHG3aTHvwOM7LLzhdX56QZVa6sorPBp6fwULuRDSqiQHw==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.936.0.tgz", + "integrity": "sha512-YB40IPa7K3iaYX0lSnV9easDOLPLh+fJyUDF3BH8doX4i1AOSsYn86L4lVldmOaSX+DwiaqKHpvk4wPBdcIPWw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@aws-sdk/util-endpoints": "3.709.0", - "@smithy/core": "^2.5.5", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@smithy/core": "^3.18.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.936.0.tgz", + "integrity": "sha512-eyj2tz1XmDSLSZQ5xnB7cLTVKkSJnYAEoNDSUNhzWPxrBDYeJzIbatecOKceKCU8NBf8gWWZCK/CSY0mDxMO0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.936.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.709.0.tgz", - "integrity": "sha512-/NoCAMEVKAg3kBKOrNtgOfL+ECt6nrl+L7q2SyYmrcY4tVCmwuECVqewQaHc03fTnJijfKLccw0Fj+6wOCnB6w==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz", + "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", + "@aws-sdk/types": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.709.0.tgz", - "integrity": "sha512-m0vhJEy6SLbjL11K9cHzX/ZhCIj//1GkTbYk2d4tTQFSuPyJEkjmoeHk9dYm2mJy0wH48j29OJadI1JUsR5bOw==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.936.0.tgz", + "integrity": "sha512-8qS0GFUqkmwO7JZ0P8tdluBmt1UTfYUah8qJXGzNh9n1Pcb0AIeT117cCSiCUtwk+gDbJvd4hhRIhJCNr5wgjg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/signature-v4": "^4.2.4", - "@smithy/types": "^3.7.2", + "@aws-sdk/middleware-sdk-s3": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.709.0.tgz", - "integrity": "sha512-q5Ar6k71nci43IbULFgC8a89d/3EHpmd7HvBzqVGRcHnoPwh8eZDBfbBXKH83NGwcS1qPSRYiDbVfeWPm4/1jA==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.936.0.tgz", + "integrity": "sha512-vvw8+VXk0I+IsoxZw0mX9TMJawUJvEsg3EF7zcCSetwhNPAU8Xmlhv7E/sN/FgSmm7b7DsqKoW6rVtQiCs1PWQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.936.0", + "@aws-sdk/nested-clients": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-sso-oidc": "^3.709.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/types": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.709.0.tgz", - "integrity": "sha512-ArtLTMxgjf13Kfu3gWH3Ez9Q5TkDdcRZUofpKH3pMGB/C6KAbeSCtIIDKfoRTUABzyGlPyCrZdnFjKyH+ypIpg==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz", + "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.693.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.693.0.tgz", - "integrity": "sha512-WC8x6ca+NRrtpAH64rWu+ryDZI3HuLwlEr8EU6/dbC/pt+r/zC0PBoC15VEygUaBA+isppCikQpGyEDu0Yj7gQ==", + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.893.0.tgz", + "integrity": "sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.709.0.tgz", - "integrity": "sha512-Mbc7AtL5WGCTKC16IGeUTz+sjpC3ptBda2t0CcK0kMVw3THDdcSq6ZlNKO747cNqdbwUvW34oHteUiHv4/z88Q==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz", + "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/types": "^3.7.2", - "@smithy/util-endpoints": "^2.1.7", + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-endpoints": "^3.2.5", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@aws-sdk/util-locate-window": { @@ -1005,33 +966,33 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.709.0.tgz", - "integrity": "sha512-/rL2GasJzdTWUURCQKFldw2wqBtY4k4kCiA2tVZSKg3y4Ey7zO34SW8ebaeCE2/xoWOyLR2/etdKyphoo4Zrtg==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz", + "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.709.0", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.712.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.712.0.tgz", - "integrity": "sha512-26X21bZ4FWsVpqs33uOXiB60TOWQdVlr7T7XONDFL/XN7GEpUJkWuuIB4PTok6VOmh1viYcdxZQqekXPuzXexQ==", + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.936.0.tgz", + "integrity": "sha512-XOEc7PF9Op00pWV2AYCGDSu5iHgYjIO53Py2VUQTIvP7SRCaCsXmA33mjBvC2Ms6FhSyWNa4aK4naUGIz0hQcw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.709.0", - "@aws-sdk/types": "3.709.0", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/middleware-user-agent": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { "aws-crt": ">=1.0.0" @@ -1043,17 +1004,28 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.709.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.709.0.tgz", - "integrity": "sha512-2GPCwlNxeHspoK/Mc8nbk9cBOkSpp3j2SJUQmFnyQK6V/pR6II2oPRyZkMomug1Rc10hqlBHByMecq4zhV2uUw==", + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", + "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", + "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.1.tgz", + "integrity": "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" } }, "node_modules/@babel/code-frame": { @@ -3433,757 +3405,786 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.9.tgz", - "integrity": "sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", + "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/chunked-blob-reader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-4.0.0.tgz", - "integrity": "sha512-jSqRnZvkT4egkq/7b6/QRCNXmmYVcHwnJldqJ3IhVpQE2atObVJ137xmGeuGFhjFUr8gCEVAOKwSY79OvpbDaQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz", + "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/chunked-blob-reader-native": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.1.tgz", - "integrity": "sha512-VEYtPvh5rs/xlyqpm5NRnfYLZn+q0SRPELbvBV+C/G7IQ+ouTuo+NKKa3ShG5OaFR8NYVMXls9hPYLTvIKKDrQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz", + "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/util-base64": "^3.0.0", + "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/config-resolver": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.13.tgz", - "integrity": "sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", + "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/core": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.5.tgz", - "integrity": "sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==", + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.5.tgz", + "integrity": "sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^3.0.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-stream": "^3.3.2", - "@smithy/util-utf8": "^3.0.0", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/credential-provider-imds": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz", - "integrity": "sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", + "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/eventstream-codec": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.10.tgz", - "integrity": "sha512-323B8YckSbUH0nMIpXn7HZsAVKHYHFUODa8gG9cHo0ySvA1fr5iWaNT+iIL0UCqUzG6QPHA3BSsBtRQou4mMqQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.5.tgz", + "integrity": "sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^3.7.2", - "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/types": "^4.9.0", + "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.14.tgz", - "integrity": "sha512-kbrt0vjOIihW3V7Cqj1SXQvAI5BR8SnyQYsandva0AOR307cXAc+IhPngxIPslxTLfxwDpNu0HzCAq6g42kCPg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.5.tgz", + "integrity": "sha512-HohfmCQZjppVnKX2PnXlf47CW3j92Ki6T/vkAT2DhBR47e89pen3s4fIa7otGTtrVxmj7q+IhH0RnC5kpR8wtw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^3.0.13", - "@smithy/types": "^3.7.2", + "@smithy/eventstream-serde-universal": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.11.tgz", - "integrity": "sha512-P2pnEp4n75O+QHjyO7cbw/vsw5l93K/8EWyjNCAAybYwUmj3M+hjSQZ9P5TVdUgEG08ueMAP5R4FkuSkElZ5tQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.5.tgz", + "integrity": "sha512-ibjQjM7wEXtECiT6my1xfiMH9IcEczMOS6xiCQXoUIYSj5b1CpBbJ3VYbdwDy8Vcg5JHN7eFpOCGk8nyZAltNQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.13.tgz", - "integrity": "sha512-zqy/9iwbj8Wysmvi7Lq7XFLeDgjRpTbCfwBhJa8WbrylTAHiAu6oQTwdY7iu2lxigbc9YYr9vPv5SzYny5tCXQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.5.tgz", + "integrity": "sha512-+elOuaYx6F2H6x1/5BQP5ugv12nfJl66GhxON8+dWVUEDJ9jah/A0tayVdkLRP0AeSac0inYkDz5qBFKfVp2Gg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^3.0.13", - "@smithy/types": "^3.7.2", + "@smithy/eventstream-serde-universal": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.13.tgz", - "integrity": "sha512-L1Ib66+gg9uTnqp/18Gz4MDpJPKRE44geOjOQ2SVc0eiaO5l255ADziATZgjQjqumC7yPtp1XnjHlF1srcwjKw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.5.tgz", + "integrity": "sha512-G9WSqbST45bmIFaeNuP/EnC19Rhp54CcVdX9PDL1zyEB514WsDVXhlyihKlGXnRycmHNmVv88Bvvt4EYxWef/Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-codec": "^3.1.10", - "@smithy/types": "^3.7.2", + "@smithy/eventstream-codec": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/fetch-http-handler": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz", - "integrity": "sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", + "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^4.1.8", - "@smithy/querystring-builder": "^3.0.11", - "@smithy/types": "^3.7.2", - "@smithy/util-base64": "^3.0.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/hash-blob-browser": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.10.tgz", - "integrity": "sha512-elwslXOoNunmfS0fh55jHggyhccobFkexLYC1ZeZ1xP2BTSrcIBaHV2b4xUQOdctrSNOpMqOZH1r2XzWTEhyfA==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.6.tgz", + "integrity": "sha512-8P//tA8DVPk+3XURk2rwcKgYwFvwGwmJH/wJqQiSKwXZtf/LiZK+hbUZmPj/9KzM+OVSwe4o85KTp5x9DUZTjw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/chunked-blob-reader": "^4.0.0", - "@smithy/chunked-blob-reader-native": "^3.0.1", - "@smithy/types": "^3.7.2", + "@smithy/chunked-blob-reader": "^5.2.0", + "@smithy/chunked-blob-reader-native": "^4.2.1", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/hash-node": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.11.tgz", - "integrity": "sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", + "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", + "@smithy/types": "^4.9.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/hash-stream-node": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.10.tgz", - "integrity": "sha512-olomK/jZQ93OMayW1zfTHwcbwBdhcZOHsyWyiZ9h9IXvc1mCD/VuvzbLb3Gy/qNJwI4MANPLctTp2BucV2oU/Q==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.5.tgz", + "integrity": "sha512-6+do24VnEyvWcGdHXomlpd0m8bfZePpUKBy7m311n+JuRwug8J4dCanJdTymx//8mi0nlkflZBvJe+dEO/O12Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", - "@smithy/util-utf8": "^3.0.0", + "@smithy/types": "^4.9.0", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/invalid-dependency": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz", - "integrity": "sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", + "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/md5-js": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.11.tgz", - "integrity": "sha512-3NM0L3i2Zm4bbgG6Ymi9NBcxXhryi3uE8fIfHJZIOfZVxOkGdjdgjR9A06SFIZCfnEIWKXZdm6Yq5/aPXFFhsQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.5.tgz", + "integrity": "sha512-Bt6jpSTMWfjCtC0s79gZ/WZ1w90grfmopVOWqkI2ovhjpD5Q2XRXuecIPB9689L2+cCySMbaXDhBPU56FKNDNg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", - "@smithy/util-utf8": "^3.0.0", + "@smithy/types": "^4.9.0", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/middleware-content-length": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz", - "integrity": "sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", + "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/middleware-endpoint": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz", - "integrity": "sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==", + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.12.tgz", + "integrity": "sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^2.5.5", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", - "@smithy/util-middleware": "^3.0.11", + "@smithy/core": "^3.18.5", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.30", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.30.tgz", - "integrity": "sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ==", + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.12.tgz", + "integrity": "sha512-S4kWNKFowYd0lID7/DBqWHOQxmxlsf0jBaos9chQZUWTVOjSW1Ogyh8/ib5tM+agFDJ/TCxuCTvrnlc+9cIBcQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/protocol-http": "^4.1.8", - "@smithy/service-error-classification": "^3.0.11", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", - "tslib": "^2.6.2", - "uuid": "^9.0.1" + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/service-error-classification": "^4.2.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-retry/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=18.0.0" } }, "node_modules/@smithy/middleware-serde": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz", - "integrity": "sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz", + "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/middleware-stack": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz", - "integrity": "sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz", + "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/node-config-provider": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz", - "integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz", + "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/node-http-handler": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz", - "integrity": "sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz", + "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^3.1.9", - "@smithy/protocol-http": "^4.1.8", - "@smithy/querystring-builder": "^3.0.11", - "@smithy/types": "^3.7.2", + "@smithy/abort-controller": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/property-provider": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz", - "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz", + "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/protocol-http": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz", - "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz", + "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/querystring-builder": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz", - "integrity": "sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz", + "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", - "@smithy/util-uri-escape": "^3.0.0", + "@smithy/types": "^4.9.0", + "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/querystring-parser": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz", - "integrity": "sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz", + "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/service-error-classification": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz", - "integrity": "sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz", + "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2" + "@smithy/types": "^4.9.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz", - "integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz", + "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/signature-v4": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.4.tgz", - "integrity": "sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz", + "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-uri-escape": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-uri-escape": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/smithy-client": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.5.0.tgz", - "integrity": "sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg==", + "version": "4.9.8", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.8.tgz", + "integrity": "sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^2.5.5", - "@smithy/middleware-endpoint": "^3.2.5", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-stream": "^3.3.2", + "@smithy/core": "^3.18.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/types": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", - "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz", + "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/url-parser": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.11.tgz", - "integrity": "sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz", + "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^3.0.11", - "@smithy/types": "^3.7.2", + "@smithy/querystring-parser": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/util-base64": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", - "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", + "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-body-length-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", - "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", + "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@smithy/util-body-length-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", - "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", + "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", + "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", + "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-config-provider": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", - "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", + "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.30", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.30.tgz", - "integrity": "sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg==", + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.11.tgz", + "integrity": "sha512-yHv+r6wSQXEXTPVCIQTNmXVWs7ekBTpMVErjqZoWkYN75HIFN5y9+/+sYOejfAuvxWGvgzgxbTHa/oz61YTbKw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^3.1.11", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", - "bowser": "^2.11.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">= 10.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.30", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.30.tgz", - "integrity": "sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow==", + "version": "4.2.14", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.14.tgz", + "integrity": "sha512-ljZN3iRvaJUgulfvobIuG97q1iUuCMrvXAlkZ4msY+ZuVHQHDIqn7FKZCEj+bx8omz6kF5yQXms/xhzjIO5XiA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^3.0.13", - "@smithy/credential-provider-imds": "^3.2.8", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/property-provider": "^3.1.11", - "@smithy/smithy-client": "^3.5.0", - "@smithy/types": "^3.7.2", + "@smithy/config-resolver": "^4.4.3", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">= 10.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-endpoints": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz", - "integrity": "sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz", + "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-hex-encoding": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", - "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", + "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-middleware": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz", - "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz", + "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-retry": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz", - "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz", + "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^3.0.11", - "@smithy/types": "^3.7.2", + "@smithy/service-error-classification": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-stream": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.2.tgz", - "integrity": "sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==", + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz", + "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/types": "^3.7.2", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-uri-escape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", - "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", + "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@smithy/util-waiter": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.2.0.tgz", - "integrity": "sha512-PpjSboaDUE6yl+1qlg3Si57++e84oXdWGbuFUSAciXsVfEZJJJupR2Nb0QuXHiunt2vGR+1PTizOMvnUPaG2Qg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.5.tgz", + "integrity": "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^3.1.9", - "@smithy/types": "^3.7.2", + "@smithy/abort-controller": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", + "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@types/babel__core": { @@ -4338,7 +4339,6 @@ "resolved": "https://registry.npmjs.org/@wix-pilot/core/-/core-3.4.2.tgz", "integrity": "sha512-O8V2NLfPEKI2IviJXG4g/vNbMfsBZNBhzAKFUOOaOR9TTDUJYlZUttqjhjP/fPnaDky0/hrfGES15sO0N7zEkw==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.0", "pngjs": "^7.0.0", @@ -4728,9 +4728,9 @@ } }, "node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.0.tgz", + "integrity": "sha512-yHAbSRuT6LTeKi6k2aS40csueHqgAsFEgmrOsfRyFpJnFv5O2hl9FYmWEUZ97gZ/dG17U4IQQcTx4YAFYPuWRQ==", "dev": true, "license": "MIT" }, @@ -4761,8 +4761,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true, - "license": "BSD-2-Clause" + "dev": true }, "node_modules/browserslist": { "version": "4.24.3", @@ -4843,7 +4842,6 @@ "resolved": "https://registry.npmjs.org/bunyamin/-/bunyamin-1.6.3.tgz", "integrity": "sha512-m1hAijFhu8pFiidsVc0XEDic46uxPK+mKNLqkb5mluNx0nTolNzx/DjwMqHChQWCgfOLMjKYJJ2uPTQLE6t4Ng==", "dev": true, - "license": "MIT", "dependencies": { "@flatten-js/interval-tree": "^1.1.2", "multi-sort-stream": "^1.0.4", @@ -4890,7 +4888,6 @@ "resolved": "https://registry.npmjs.org/bunyan-debug-stream/-/bunyan-debug-stream-3.1.1.tgz", "integrity": "sha512-LfMcz4yKM6s9BP5dfT63Prb5B2hAjReLAfQzLbNQF7qBHtn3P1v+/yn0SZ6UAr4PC3VZRX/QzK7HYkkY0ytokQ==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.2" }, @@ -5334,9 +5331,9 @@ } }, "node_modules/detox": { - "version": "20.46.3", - "resolved": "https://registry.npmjs.org/detox/-/detox-20.46.3.tgz", - "integrity": "sha512-9NlpWFu2/CHEMSkzdPcQ9XCGKAtRca2ZLIcVeQDjZvfqkcDOdBt7nj8SX2TNjB4oR6+5MsBg9m0ngQTm8RpNbQ==", + "version": "20.47.0", + "resolved": "https://registry.npmjs.org/detox/-/detox-20.47.0.tgz", + "integrity": "sha512-Jpk296Ct006MnemKQP25X1q4fQ3G6rwSX+f0BqC5Py7qKdJ9cRh4H39D1GIIV56UJ/nJEI5IAgg7jrSPjCT9sA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5592,7 +5589,6 @@ "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -5705,7 +5701,6 @@ "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", "dev": true, - "license": "Unlicense", "engines": { "node": ">=4.0.0" } @@ -5749,7 +5744,6 @@ "resolved": "https://registry.npmjs.org/exeunt/-/exeunt-1.1.0.tgz", "integrity": "sha512-dd++Yn/0Fp+gtJ04YHov7MeAii+LFivJc6KqnJNfplzLVUkUDrfKoQDTLlCgzcW15vY5hKlHasWeIsQJ8agHsw==", "dev": true, - "license": "MPL-2.0", "engines": { "node": ">=0.10" } @@ -5819,23 +5813,19 @@ "license": "BSD-3-Clause" }, "node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" @@ -6031,7 +6021,6 @@ "resolved": "https://registry.npmjs.org/funpermaproxy/-/funpermaproxy-1.1.0.tgz", "integrity": "sha512-2Sp1hWuO8m5fqeFDusyhKqYPT+7rGLw34N3qonDcdRP8+n7M7Gl/yKp/q7oCxnnJ6pWCectOmLFJpsMU/++KrQ==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=8.3.0" } @@ -6828,7 +6817,6 @@ "resolved": "https://registry.npmjs.org/jest-environment-emit/-/jest-environment-emit-1.2.0.tgz", "integrity": "sha512-dSFBrRuIiWbHK2LSUA6CutXpMcNGjjuhvxFLF+TVz5tYFAAH0eesrZgrQ3UtOptajDYNt/fIGRqtlHqGq/bLbA==", "dev": true, - "license": "MIT", "dependencies": { "bunyamin": "^1.5.2", "bunyan": "^2.0.5", @@ -6875,7 +6863,6 @@ "engines": [ "node >=0.10.0" ], - "license": "MIT", "dependencies": { "exeunt": "1.1.0" }, @@ -7426,7 +7413,6 @@ "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.6.0" } @@ -7436,7 +7422,6 @@ "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz", "integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==", "dev": true, - "license": "MIT", "dependencies": { "easy-stack": "^1.0.1" }, @@ -7618,8 +7603,7 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/logform": { "version": "2.7.0", @@ -7852,8 +7836,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/multi-sort-stream/-/multi-sort-stream-1.0.4.tgz", "integrity": "sha512-hAZ8JOEQFbgdLe8HWZbb7gdZg0/yAIHF00Qfo3kd0rXFv96nXe+/bPTrKHZ2QMHugGX4FiAyET1Lt+jiB+7Qlg==", - "dev": true, - "license": "bsd" + "dev": true }, "node_modules/multipipe": { "version": "4.0.0", @@ -7944,7 +7927,6 @@ "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz", "integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==", "dev": true, - "license": "MIT", "dependencies": { "event-pubsub": "4.3.0", "js-message": "1.0.7", @@ -9293,15 +9275,13 @@ "version": "2.2.5", "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", - "dev": true, - "license": "BSD-3-Clause" + "dev": true }, "node_modules/stream-json": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "stream-chain": "^2.2.5" } @@ -9399,10 +9379,16 @@ } }, "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "license": "MIT" }, "node_modules/supports-color": { @@ -9587,7 +9573,6 @@ "resolved": "https://registry.npmjs.org/trace-event-lib/-/trace-event-lib-1.4.1.tgz", "integrity": "sha512-TOgFolKG8JFY+9d5EohGWMvwvteRafcyfPWWNIqcuD1W/FUvxWcy2MSCZ/beYHM63oYPHYHCd3tkbgCctHVP7w==", "dev": true, - "license": "MIT", "dependencies": { "browser-process-hrtime": "^1.0.0" }, diff --git a/detox/package.json b/detox/package.json index fca83bea9..67f2dc1ab 100644 --- a/detox/package.json +++ b/detox/package.json @@ -4,8 +4,8 @@ "repository": "git@github.com:mattermost/mattermost-mobile.git", "author": "Mattermost, Inc.", "devDependencies": { - "@aws-sdk/client-s3": "3.712.0", - "@aws-sdk/lib-storage": "3.712.0", + "@aws-sdk/client-s3": "3.937.0", + "@aws-sdk/lib-storage": "3.937.0", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/plugin-transform-modules-commonjs": "7.26.3", "@babel/plugin-transform-runtime": "7.25.9", @@ -23,7 +23,7 @@ "babel-plugin-module-resolver": "5.0.2", "client-oauth2": "4.3.3", "deepmerge": "4.3.1", - "detox": "20.46.3", + "detox": "20.47.0", "dotenv": "17.2.1", "form-data": "4.0.1", "jest": "29.7.0", @@ -48,11 +48,11 @@ "e2e:android-inject-settings": "node inject-detox-settings.js", "e2e:android-create-emulator": "./create_android_emulator.sh", "e2e:android-build": "detox build -c android.emu.debug", - "e2e:android-test": "detox test -c android.emu.debug --reuse --record-logs failing --take-screenshots failing", + "e2e:android-test": "detox test -c android.emu.debug --record-logs failing --take-screenshots failing", "e2e:android-build-release": "detox build -c android.emu.release", "e2e:android-test-release": "detox test -c android.emu.release --record-logs failing --take-screenshots failing", "e2e:ios-build": "IOS=true detox build -c ios.sim.debug", - "e2e:ios-test": "IOS=true detox test -c ios.sim.debug --reuse --record-logs failing --take-screenshots failing", + "e2e:ios-test": "IOS=true detox test -c ios.sim.debug --record-logs failing --take-screenshots failing", "e2e:ios-build-release": "detox build -c ios.sim.release", "e2e:ios-test-release": "IOS=true detox test -c ios.sim.release --record-logs failing --take-screenshots failing", "e2e:ios-disable-autofill": "cd utils && node disable_ios_autofill.js",