Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement reviewal of contact requests from contact profile #19119

Merged
merged 10 commits into from
Mar 11, 2024

Conversation

seanstrom
Copy link
Member

@seanstrom seanstrom commented Mar 6, 2024

fixes #18968
fixes #18969

Summary

  • This PR attempts to implement the contact-request reviewing functionality.
  • Additionally, this PR modifies the quo/locked-input
    • It changes quo/locked-input to have a minimum height instead of a fixed-height.
      • This is useful allowing locked-inputs to grow in height with a multiline message.
    • It changes quo/locked-input to only render a label when provided the label text.
      • This is useful for avoiding unnecessary whitespace from an empty label view.

Testing Notes

These changes to the quo/locked-input may require manual-qa, though it may not since the quo/locked-input component does not seem to be used yet. It seems that it has been defined in the design system, but this may be the first use of the component (?), meaning that changes to it may not affect anything.

Platforms

  • Android
  • iOS

Areas that maybe impacted

Functional
  • Feature Flagged Contact Profiles
  • Locked-Input Components

Steps to test

  • Open the Status mobile and desktop app
  • Enable the profile new-contact-ui feature flag on mobile
  • Send a contact request from desktop user to mobile user
  • Press the "Review contact request" button
  • Accept contact request via the mobile app
  • Press the "Send message" button to navigate to contact's chat

Before and after screenshots comparison

Before

Screenshot 2024-03-06 at 13 28 06

After changes

Screen.Recording.2024-03-07.at.18.48.12.mov

status: ready

@seanstrom seanstrom self-assigned this Mar 6, 2024
@status-github-bot status-github-bot bot added this to REVIEW in Pipeline for QA Mar 6, 2024
@seanstrom seanstrom force-pushed the seanstrom/contact-profile-contact-request-received branch from 87e2571 to 356b0f4 Compare March 6, 2024 13:27
@status-im-auto
Copy link
Member

status-im-auto commented Mar 6, 2024

Jenkins Builds

Click to see older builds (18)
Commit #️⃣ Finished (UTC) Duration Platform Result
356b0f4 #2 2024-03-06 13:29:55 ~2 min tests 📄log
✔️ 356b0f4 #2 2024-03-06 13:36:15 ~8 min android 🤖apk 📲
✔️ 356b0f4 #2 2024-03-06 13:36:24 ~8 min android-e2e 🤖apk 📲
✔️ 356b0f4 #2 2024-03-06 13:36:48 ~8 min ios 📱ipa 📲
✔️ b4ccbf3 #3 2024-03-06 16:22:48 ~6 min android-e2e 🤖apk 📲
✔️ b4ccbf3 #3 2024-03-06 16:22:52 ~6 min tests 📄log
✔️ b4ccbf3 #3 2024-03-06 16:23:37 ~7 min android 🤖apk 📲
✔️ b4ccbf3 #3 2024-03-06 16:23:47 ~7 min ios 📱ipa 📲
eacc328 #4 2024-03-07 10:20:30 ~1 min tests 📄log
✔️ eacc328 #4 2024-03-07 10:26:55 ~7 min ios 📱ipa 📲
✔️ eacc328 #4 2024-03-07 10:27:00 ~8 min android-e2e 🤖apk 📲
✔️ eacc328 #4 2024-03-07 10:27:25 ~8 min android 🤖apk 📲
5889937 #5 2024-03-07 16:48:46 ~1 min tests 📄log
✔️ 5889937 #5 2024-03-07 16:55:04 ~7 min android-e2e 🤖apk 📲
✔️ 5889937 #5 2024-03-07 16:55:34 ~8 min ios 📱ipa 📲
✔️ 5889937 #5 2024-03-07 16:55:56 ~8 min android 🤖apk 📲
b94b19e #7 2024-03-07 18:28:16 ~1 min tests 📄log
✔️ cf73b2a #8 2024-03-07 18:38:02 ~5 min tests 📄log
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ c4cb8c2 #9 2024-03-07 18:44:43 ~6 min tests 📄log
✔️ c4cb8c2 #9 2024-03-07 18:45:59 ~7 min ios 📱ipa 📲
✔️ c4cb8c2 #9 2024-03-07 18:46:46 ~8 min android-e2e 🤖apk 📲
✔️ c4cb8c2 #9 2024-03-07 18:46:53 ~8 min android 🤖apk 📲
✔️ c625ee3 #10 2024-03-11 09:32:57 ~5 min tests 📄log
✔️ c625ee3 #10 2024-03-11 09:34:43 ~7 min android-e2e 🤖apk 📲
✔️ c625ee3 #10 2024-03-11 09:34:55 ~7 min android 🤖apk 📲
✔️ c625ee3 #10 2024-03-11 09:34:57 ~7 min ios 📱ipa 📲

@seanstrom seanstrom marked this pull request as ready for review March 6, 2024 13:33
Copy link
Member Author

@seanstrom seanstrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self Review / Comments

@@ -44,3 +44,4 @@
:button-one-props {:disabled? (string/blank? message)
:on-press on-message-submit}
:button-one-label (i18n/label :t/send-contact-request)}]]))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 End of file whitespace is being added by formatter

Comment on lines 9 to 24
(defn view
[]
(let [{:keys [public-key customization-color]
:as profile} (rf/sub [:contacts/current-contact])
{contact-request-id :id
:as contact-request} (rf/sub [:activity-center/contact-request-from-contact-id public-key])
;; TODO: remove :blue when #18733 merged.
customization-color (or customization-color :blue)
full-name (profile.utils/displayed-name profile)
profile-picture (profile.utils/photo profile)
on-contact-accept (rn/use-callback (fn []
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:activity-center.contact-requests/accept
contact-request-id]))
[contact-request-id])
on-contact-ignore (rn/use-callback (fn []
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm using the activity-center subscription and events for accessing the contact-request data. It may be useful to refactor this to access contact-requests from a separate event/sub namespace that manages all contact requests directly. But I'm not sure if that's necessary since activity-center seems to be doing that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any strong opinion about it but maybe @ilmotta any thought?

Copy link
Contributor

@ilmotta ilmotta Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be a little bit careful with this piece of data.

Pending contact requests are actually fetched from notifications. Back when I wrote that part I added a long docstring explaining why that works and why it's not the ideal solution. See

(rf/defn notifications-fetch-pending-contact-requests
"Unread contact requests are, in practical terms, the same as pending contact
requests in the Activity Center, because pending contact requests are always
marked as unread in status-go, and once the user declines/accepts the request,
they are marked as read.
If this relationship ever changes, we will probably need to change the backend
to explicitly support fetching notifications for 'pending' contact requests."

So just be aware that grabbing a specific contact request from what's stored in the app-db has limitations, but should be fine for now (unless the user has "lots" of pending contact request notifications, i.e. more than we paginate).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for providing this context 🙌

I think this PR assumes the subscribed contact-request is pending, but I can try naming the subscription something like pending-contact-request-from-contact-id so the reader knows this limitation, thoughts?

Also do you think I should create a separate issue for possibly rewiring the way contact requests are stored? For example, maybe we can store them in a map that's indexed by contact-id? I suppose that would assume we can only have one contact-request from a person at a time though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something I'm just noticing is that when we try to supporting dismissing a notification, we'll need to support retrieving dismissed contact-requests. But I think from what you mention, that currently is not possible because the contact request will be marked as read when dismissed, and then removed from the activity-center.

Am I understanding this correctly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seanstrom, one thing that could clarify things a bit is that we intentionally descoped managing pending contact requests (see the feature in Figma https://www.figma.com/file/7KIYbhoqNGAIFonE0w9TDz/Messages-for-Mobile?type=design&node-id=2010-507764&mode=design&t=to5BwBfcY6wkr3s1-0).

I remember back then I thought a good excuse to improve the client/server code would be if I worked on that feature because it would help me understand the ideal solution. But this doesn't seem to be a priority yet (you could double-check, that was a long time ago). Notifications of type contact request and contact requests themselves are different entities in the backend db, so ideally our code should improve on this area.

Also do you think I should create a separate issue for possibly rewiring the way contact requests are stored?

Sure! 👍🏼

Copy link
Contributor

@mohsen-ghafouri mohsen-ghafouri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🔥

@seanstrom seanstrom force-pushed the seanstrom/contact-profile-contact-request-received branch from b4ccbf3 to eacc328 Compare March 7, 2024 10:18
@seanstrom seanstrom force-pushed the seanstrom/contact-profile-contact-request-received branch from eacc328 to 5889937 Compare March 7, 2024 16:46
@seanstrom seanstrom moved this from REVIEW to E2E Tests in Pipeline for QA Mar 7, 2024
@seanstrom seanstrom force-pushed the seanstrom/contact-profile-contact-request-received branch 4 times, most recently from cf73b2a to c4cb8c2 Compare March 7, 2024 18:38
@seanstrom seanstrom moved this from E2E Tests to REVIEW in Pipeline for QA Mar 8, 2024
@seanstrom seanstrom moved this from REVIEW to E2E Tests in Pipeline for QA Mar 8, 2024
@status-im-auto
Copy link
Member

73% of end-end tests have passed

Total executed tests: 48
Failed tests: 12
Expected to fail tests: 1
Passed tests: 35
IDs of failed tests: 702782,702733,702777,702813,702851,702745,702850,702869,702855,703391,702731,702730 
IDs of expected to fail tests: 703503 

Failed tests (12)

Click to expand
  • Rerun failed tests

  • Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_emoji_send_reply_and_open_link, id: 702782
    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    2. test_1_1_chat_text_message_delete_push_disappear, id: 702733

    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    3. test_1_1_chat_push_emoji, id: 702813

    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    4. test_1_1_chat_non_latin_messages_stack_update_profile_photo, id: 702745

    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    5. test_1_1_chat_edit_message, id: 702855

    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    6. test_1_1_chat_send_image_save_and_share, id: 703391

    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    7. test_1_1_chat_pin_messages, id: 702731

    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    8. test_1_1_chat_message_reaction, id: 702730

    Test setup failed: critical/chats/test_1_1_public_chats.py:20: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    Class TestActivityCenterContactRequestMultipleDevicePR:

    1. test_add_contact_field_validation, id: 702777

    Test setup failed: activity_center/test_activity_center.py:18: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    2. test_activity_center_contact_request_accept_swipe_mark_all_as_read, id: 702851

    Test setup failed: activity_center/test_activity_center.py:18: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    3. test_activity_center_contact_request_decline, id: 702850

    Test setup failed: activity_center/test_activity_center.py:18: in prepare_devices
        self.drivers, self.loop = create_shared_drivers(2)
    base_test_case.py:309: in create_shared_drivers
        drivers = loop.run_until_complete(start_threads(test_suite_data.current_test.name,
    /usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
        return future.result()
    __init__.py:26: in start_threads
        returns[k] = await returns[k]
    /usr/lib/python3.10/concurrent/futures/thread.py:58: in run
        result = self.fn(*self.args, **self.kwargs)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:257: in __init__
        super().__init__(
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:206: in __init__
        self.start_session(capabilities)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/webdriver.py:346: in start_session
        response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:193: in check_response
        raise exception_class(value)
     <html><body><h1>502 Bad Gateway</h1>
    E   The server returned an invalid or incomplete response.
    E   </body></html>
    



    Class TestCommunityOneDeviceMerged:

    1. test_community_undo_delete_message, id: 702869

    Device 1: Tap on found: Button
    Device 1: Find Button by xpath: //*[@text="Undo"]

    critical/chats/test_public_chat_browsing.py:112: in test_community_undo_delete_message
        self.channel.element_by_text("Undo").click()
    ../views/base_element.py:92: in click
        element.click()
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py:94: in click
        self._execute(Command.CLICK_ELEMENT)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py:395: in _execute
        return self._parent.execute(command, params)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/errorhandler.py:122: in check_response
        raise exception_class(msg=message, stacktrace=format_stacktrace(stacktrace))
     The element 'By.xpath: //*[@text="Undo"]' does not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#stale-element-reference-exception
    E   Stacktrace:
    E   io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: The element 'By.xpath: //*[@text="Undo"]' does not exist in DOM anymore
    E   	at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:117)
    E   	at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:153)
    E   	at io.appium.uiautomator2.handler.Click.safeHandle(Click.java:36)
    E   	at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59)
    E   	at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:277)
    E   	at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:271)
    E   	at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:68)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
    E   	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
    E   	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
    E   	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
    E   	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)
    E   	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
    E   	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
    E   	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
    E   	at java.lang.Thread.run(Thread.java:1012)
    
    During handling of the above exception, another exception occurred:
    critical/chats/test_public_chat_browsing.py:114: in test_community_undo_delete_message
        pytest.fail("Can't press Undo button, not enough time")
    E   Failed: Can't press Undo button, not enough time
    



    Device sessions

    Expected to fail tests (1)

    Click to expand

    Class TestCommunityOneDeviceMerged:

    1. test_community_discovery, id: 703503

    Test is not run, e2e blocker  
    

    [[reason: [NOTRUN] Curated communities not loading, https://github.com//issues/17852]]

    Passed tests (35)

    Click to expand

    Class TestDeepLinksOneDevice:

    1. test_links_open_universal_links_from_chat, id: 704613
    Device sessions

    2. test_links_deep_links, id: 702775
    Device sessions

    Class TestOneToOneChatMultipleSharedDevicesNewUiTwo:

    1. test_1_1_chat_delete_via_long_press_relogin, id: 702784
    Device sessions

    2. test_1_1_chat_is_shown_message_sent_delivered_from_offline, id: 702783
    Device sessions

    3. test_1_1_chat_mute_chat, id: 703496
    Device sessions

    Class TestCommunityMultipleDeviceMergedTwo:

    1. test_community_markdown_support, id: 702809
    Device sessions

    2. test_community_hashtag_links_to_community_channels, id: 702948
    Device sessions

    3. test_community_mentions_push_notification, id: 702786
    Device sessions

    4. test_community_leave, id: 702845
    Device sessions

    5. test_community_join_when_node_owner_offline, id: 703629
    Device sessions

    Class TestActivityMultipleDevicePR:

    1. test_navigation_jump_to, id: 702936
    Device sessions

    2. test_activity_center_reply_read_unread_delete_filter_swipe, id: 702947
    Device sessions

    Class TestActivityMultipleDevicePRTwo:

    1. test_activity_center_mentions, id: 702957
    Device sessions

    2. test_activity_center_admin_notification_accept_swipe, id: 702958
    Device sessions

    Class TestCommunityOneDeviceMerged:

    1. test_restore_multiaccount_with_waku_backup_remove_switch, id: 703133
    Device sessions

    2. test_community_copy_and_paste_message_in_chat_input, id: 702742
    Device sessions

    3. test_community_navigate_to_channel_when_relaunch, id: 702846
    Device sessions

    4. test_community_mute_community_and_channel, id: 703382
    Device sessions

    Class TestGroupChatMultipleDeviceMergedNewUI:

    1. test_group_chat_pin_messages, id: 702732
    Device sessions

    2. test_group_chat_mute_chat, id: 703495
    Device sessions

    3. test_group_chat_send_image_save_and_share, id: 703297
    Device sessions

    4. test_group_chat_reactions, id: 703202
    Device sessions

    5. test_group_chat_join_send_text_messages_push, id: 702807
    Device sessions

    6. test_group_chat_offline_pn, id: 702808
    Device sessions

    Class TestCommunityMultipleDeviceMerged:

    1. test_community_several_images_send_reply, id: 703194
    Device sessions

    2. test_community_one_image_send_reply, id: 702859
    Device sessions

    3. test_community_emoji_send_copy_paste_reply, id: 702840
    Device sessions

    4. test_community_mark_all_messages_as_read, id: 703086
    Device sessions

    5. test_community_contact_block_unblock_offline, id: 702894
    Device sessions

    6. test_community_edit_delete_message_when_offline, id: 704615
    Device sessions

    7. test_community_message_delete, id: 702839
    Device sessions

    8. test_community_message_send_check_timestamps_sender_username, id: 702838
    Device sessions

    9. test_community_links_with_previews_github_youtube_twitter_gif_send_enable, id: 702844
    Device sessions

    10. test_community_message_edit, id: 702843
    Device sessions

    11. test_community_unread_messages_badge, id: 702841
    Device sessions

    @seanstrom
    Copy link
    Member Author

    @status-im/mobile-qa Can you please review the results of the E2E? 🙏

    @VolodLytvynenko VolodLytvynenko moved this from E2E Tests to REVIEW in Pipeline for QA Mar 8, 2024
    @VolodLytvynenko VolodLytvynenko moved this from REVIEW to E2E Tests in Pipeline for QA Mar 8, 2024
    @VolodLytvynenko
    Copy link
    Contributor

    @status-im/mobile-qa Can you please review the results of the E2E? 🙏

    Hi @seanstrom all fails are not PR related. I have rerun them one more time

    @status-im-auto
    Copy link
    Member

    92% of end-end tests have passed

    Total executed tests: 48
    Failed tests: 3
    Expected to fail tests: 1
    Passed tests: 44
    
    IDs of failed tests: 702809,702851,702731 
    
    IDs of expected to fail tests: 703503 
    

    Failed tests (3)

    Click to expand
  • Rerun failed tests

  • Class TestCommunityMultipleDeviceMergedTwo:

    1. test_community_markdown_support, id: 702809

    Device 1: Looking for a message by text: quote reply (one row)
    Device 2: Looking for a message by text: quote reply (one row)

    critical/chats/test_public_chat_browsing.py:980: in test_community_markdown_support
        self.errors.verify_no_errors()
    base_test_case.py:191: in verify_no_errors
        pytest.fail('\n '.join([self.errors.pop(0) for _ in range(len(self.errors))]))
     italic text in asteric is not displayed with markdown in community channel for the recipient (device 1)
    



    Device sessions

    Class TestActivityCenterContactRequestMultipleDevicePR:

    1. test_activity_center_contact_request_accept_swipe_mark_all_as_read, id: 702851

    Device 1: Tap on found: Button
    # STEP: Device1 check that contact appeared in contact list mutually

    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/connectionpool.py:703: in urlopen
        httplib_response = self._make_request(
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/connectionpool.py:449: in _make_request
        six.raise_from(e, None)
    <string>:3: in raise_from
        ???
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/connectionpool.py:444: in _make_request
        httplib_response = conn.getresponse()
    /usr/lib/python3.10/http/client.py:1375: in getresponse
        response.begin()
    /usr/lib/python3.10/http/client.py:318: in begin
        version, status, reason = self._read_status()
    /usr/lib/python3.10/http/client.py:287: in _read_status
        raise RemoteDisconnected("Remote end closed connection without"
    E   http.client.RemoteDisconnected: Remote end closed connection without response
    
    During handling of the above exception, another exception occurred:
    activity_center/test_activity_center.py:134: in test_activity_center_contact_request_accept_swipe_mark_all_as_read
        self.device_2.just_fyi('Device1 check that contact appeared in contact list mutually')
    ../views/base_view.py:395: in just_fyi
        self.driver.execute_script("sauce:context=STEP: %s" % some_str)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:405: in execute_script
        return self.execute(command, {"script": script, "args": converted_args})["value"]
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:343: in execute
        response = self.command_executor.execute(driver_command, params)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/remote_connection.py:291: in execute
        return self._request(command_info[0], url, body=data)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/remote_connection.py:312: in _request
        response = self._conn.request(method, url, body=body, headers=headers)
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/request.py:78: in request
        return self.request_encode_body(
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/request.py:170: in request_encode_body
        return self.urlopen(method, url, **extra_kw)
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/poolmanager.py:376: in urlopen
        response = conn.urlopen(method, u.request_uri, **kw)
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/connectionpool.py:787: in urlopen
        retries = retries.increment(
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/util/retry.py:550: in increment
        raise six.reraise(type(error), error, _stacktrace)
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/packages/six.py:769: in reraise
        raise value.with_traceback(tb)
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/connectionpool.py:703: in urlopen
        httplib_response = self._make_request(
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/connectionpool.py:449: in _make_request
        six.raise_from(e, None)
    <string>:3: in raise_from
        ???
    /home/jenkins/.local/lib/python3.10/site-packages/urllib3/connectionpool.py:444: in _make_request
        httplib_response = conn.getresponse()
    /usr/lib/python3.10/http/client.py:1375: in getresponse
        response.begin()
    /usr/lib/python3.10/http/client.py:318: in begin
        version, status, reason = self._read_status()
    /usr/lib/python3.10/http/client.py:287: in _read_status
        raise RemoteDisconnected("Remote end closed connection without"
     ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
    



    Device sessions

    Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_pin_messages, id: 702731

    Device 1: Find Button by xpath: //*[@content-desc='pins-count']//android.widget.TextView
    Device 2: Find Button by xpath: //*[@content-desc='pins-count']//android.widget.TextView

    critical/chats/test_1_1_public_chats.py:267: in test_1_1_chat_pin_messages
        self.errors.verify_no_errors()
    base_test_case.py:191: in verify_no_errors
        pytest.fail('\n '.join([self.errors.pop(0) for _ in range(len(self.errors))]))
     Pinned messages count is 3 but should be 2 after unpinning the last pinned message for user 2
    



    Device sessions

    Expected to fail tests (1)

    Click to expand

    Class TestCommunityOneDeviceMerged:

    1. test_community_discovery, id: 703503

    Test is not run, e2e blocker  
    

    [[reason: [NOTRUN] Curated communities not loading, https://github.com//issues/17852]]

    Passed tests (44)

    Click to expand

    Class TestActivityMultipleDevicePR:

    1. test_navigation_jump_to, id: 702936
    Device sessions

    2. test_activity_center_reply_read_unread_delete_filter_swipe, id: 702947
    Device sessions

    Class TestOneToOneChatMultipleSharedDevicesNewUiTwo:

    1. test_1_1_chat_delete_via_long_press_relogin, id: 702784
    Device sessions

    2. test_1_1_chat_is_shown_message_sent_delivered_from_offline, id: 702783
    Device sessions

    3. test_1_1_chat_mute_chat, id: 703496
    Device sessions

    Class TestCommunityMultipleDeviceMerged:

    1. test_community_several_images_send_reply, id: 703194
    Device sessions

    2. test_community_one_image_send_reply, id: 702859
    Device sessions

    3. test_community_emoji_send_copy_paste_reply, id: 702840
    Device sessions

    4. test_community_mark_all_messages_as_read, id: 703086
    Device sessions

    5. test_community_contact_block_unblock_offline, id: 702894
    Device sessions

    6. test_community_edit_delete_message_when_offline, id: 704615
    Device sessions

    7. test_community_message_delete, id: 702839
    Device sessions

    8. test_community_message_send_check_timestamps_sender_username, id: 702838
    Device sessions

    9. test_community_links_with_previews_github_youtube_twitter_gif_send_enable, id: 702844
    Device sessions

    10. test_community_message_edit, id: 702843
    Device sessions

    11. test_community_unread_messages_badge, id: 702841
    Device sessions

    Class TestActivityMultipleDevicePRTwo:

    1. test_activity_center_mentions, id: 702957
    Device sessions

    2. test_activity_center_admin_notification_accept_swipe, id: 702958
    Device sessions

    Class TestCommunityMultipleDeviceMergedTwo:

    1. test_community_hashtag_links_to_community_channels, id: 702948
    Device sessions

    2. test_community_mentions_push_notification, id: 702786
    Device sessions

    3. test_community_leave, id: 702845
    Device sessions

    4. test_community_join_when_node_owner_offline, id: 703629
    Device sessions

    Class TestActivityCenterContactRequestMultipleDevicePR:

    1. test_add_contact_field_validation, id: 702777
    Device sessions

    2. test_activity_center_contact_request_decline, id: 702850
    Device sessions

    Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_emoji_send_reply_and_open_link, id: 702782
    Device sessions

    2. test_1_1_chat_text_message_delete_push_disappear, id: 702733
    Device sessions

    3. test_1_1_chat_push_emoji, id: 702813
    Device sessions

    4. test_1_1_chat_non_latin_messages_stack_update_profile_photo, id: 702745
    Device sessions

    5. test_1_1_chat_edit_message, id: 702855
    Device sessions

    6. test_1_1_chat_send_image_save_and_share, id: 703391
    Device sessions

    7. test_1_1_chat_message_reaction, id: 702730
    Device sessions

    Class TestGroupChatMultipleDeviceMergedNewUI:

    1. test_group_chat_pin_messages, id: 702732
    Device sessions

    2. test_group_chat_mute_chat, id: 703495
    Device sessions

    3. test_group_chat_send_image_save_and_share, id: 703297
    Device sessions

    4. test_group_chat_reactions, id: 703202
    Device sessions

    5. test_group_chat_join_send_text_messages_push, id: 702807
    Device sessions

    6. test_group_chat_offline_pn, id: 702808
    Device sessions

    Class TestDeepLinksOneDevice:

    1. test_links_open_universal_links_from_chat, id: 704613
    Device sessions

    2. test_links_deep_links, id: 702775
    Device sessions

    Class TestCommunityOneDeviceMerged:

    1. test_restore_multiaccount_with_waku_backup_remove_switch, id: 703133
    Device sessions

    2. test_community_copy_and_paste_message_in_chat_input, id: 702742
    Device sessions

    3. test_community_undo_delete_message, id: 702869
    Device sessions

    4. test_community_navigate_to_channel_when_relaunch, id: 702846
    Device sessions

    5. test_community_mute_community_and_channel, id: 703382
    Device sessions

    @pavloburykh
    Copy link
    Contributor

    @status-im/mobile-qa Can you please review the results of the E2E? 🙏

    @seanstrom E2E are okay. If PR does not require manual QA - it is ready for merge.

    @pavloburykh
    Copy link
    Contributor

    pavloburykh commented Mar 11, 2024

    though it may not since the quo/locked-input component does not seem to be used yet

    @seanstrom If the component is not yet in use in app - we can skip manual qa. Since e2e are okay PR is ready for merge.

    @pavloburykh pavloburykh moved this from E2E Tests to MERGE in Pipeline for QA Mar 11, 2024
    @seanstrom seanstrom force-pushed the seanstrom/contact-profile-contact-request-received branch from c4cb8c2 to c625ee3 Compare March 11, 2024 09:27
    @seanstrom
    Copy link
    Member Author

    @pavloburykh Awesome! Thanks for the help 🙌

    @seanstrom seanstrom merged commit ca9346a into develop Mar 11, 2024
    6 checks passed
    Pipeline for QA automation moved this from MERGE to DONE Mar 11, 2024
    @seanstrom seanstrom deleted the seanstrom/contact-profile-contact-request-received branch March 11, 2024 09:43
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    Archived in project
    6 participants