diff --git a/.drone.yml b/.drone.yml index a6c65c5705b..15392c0d94e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -262,6 +262,8 @@ matrix: DATABASEHOST: postgres-10 # Acceptance tests + - TESTS: acceptance + TESTS_ACCEPTANCE: call - TESTS: acceptance TESTS_ACCEPTANCE: chat - TESTS: acceptance diff --git a/tests/acceptance/config/behat.yml b/tests/acceptance/config/behat.yml index 64bac4cdd75..66b13ae9114 100644 --- a/tests/acceptance/config/behat.yml +++ b/tests/acceptance/config/behat.yml @@ -17,6 +17,7 @@ default: - LoginPageContext # Talk app contexts + - CallContext - ChatContext - ConversationInfoContext - ConversationListContext @@ -35,3 +36,39 @@ default: Jane: selenium2: wd_host: %selenium.server% + Kermit with microphone and camera: + selenium2: + wd_host: %selenium.server% + capabilities: + firefox: + profile: %paths.base%/firefox-profiles/granted-media-permissions-with-microphone-and-camera.zip + Karen with microphone: + selenium2: + wd_host: %selenium.server% + capabilities: + firefox: + profile: %paths.base%/firefox-profiles/granted-media-permissions-with-microphone.zip + James: + selenium2: + wd_host: %selenium.server% + capabilities: + firefox: + profile: %paths.base%/firefox-profiles/granted-media-permissions.zip + April with microphone and camera: + selenium2: + wd_host: %selenium.server% + capabilities: + firefox: + profile: %paths.base%/firefox-profiles/granted-media-permissions-with-microphone-and-camera.zip + Jarvis with microphone: + selenium2: + wd_host: %selenium.server% + capabilities: + firefox: + profile: %paths.base%/firefox-profiles/granted-media-permissions-with-microphone.zip + Lucius: + selenium2: + wd_host: %selenium.server% + capabilities: + firefox: + profile: %paths.base%/firefox-profiles/granted-media-permissions.zip diff --git a/tests/acceptance/config/firefox-profiles/granted-media-permissions-with-microphone-and-camera.zip b/tests/acceptance/config/firefox-profiles/granted-media-permissions-with-microphone-and-camera.zip new file mode 100644 index 00000000000..8699172d795 Binary files /dev/null and b/tests/acceptance/config/firefox-profiles/granted-media-permissions-with-microphone-and-camera.zip differ diff --git a/tests/acceptance/config/firefox-profiles/granted-media-permissions-with-microphone.zip b/tests/acceptance/config/firefox-profiles/granted-media-permissions-with-microphone.zip new file mode 100644 index 00000000000..2d6ad79fd35 Binary files /dev/null and b/tests/acceptance/config/firefox-profiles/granted-media-permissions-with-microphone.zip differ diff --git a/tests/acceptance/config/firefox-profiles/granted-media-permissions.zip b/tests/acceptance/config/firefox-profiles/granted-media-permissions.zip new file mode 100644 index 00000000000..c8bb6cc942b Binary files /dev/null and b/tests/acceptance/config/firefox-profiles/granted-media-permissions.zip differ diff --git a/tests/acceptance/features/bootstrap/CallContext.php b/tests/acceptance/features/bootstrap/CallContext.php new file mode 100644 index 00000000000..8a021423a55 --- /dev/null +++ b/tests/acceptance/features/bootstrap/CallContext.php @@ -0,0 +1,494 @@ +. + * + */ + +use Behat\Behat\Context\Context; + +class CallContext implements Context, ActorAwareInterface { + + use ActorAware; + + /** + * @return Locator + */ + public static function localContainer() { + return Locator::forThe()->css("#localVideoContainer")-> + descendantOf(TalkAppContext::mainView())-> + describedAs("Local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localVideo() { + return Locator::forThe()->css("video")-> + descendantOf(self::localContainer())-> + describedAs("Video in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localAvatar() { + return Locator::forThe()->css(".avatar-container")-> + descendantOf(self::localContainer())-> + describedAs("Avatar in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localAudioEnabledIndicator() { + return Locator::forThe()->css(".icon-audio:not(.audio-disabled):not(.no-audio-available)")-> + descendantOf(self::localContainer())-> + describedAs("Audio enabled indicator in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localAudioDisabledIndicator() { + return Locator::forThe()->css(".audio-disabled:not(.no-audio-available)")-> + descendantOf(self::localContainer())-> + describedAs("Audio disabled indicator in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localAudioNotAvailableIndicator() { + return Locator::forThe()->css(".no-audio-available")-> + descendantOf(self::localContainer())-> + describedAs("Audio not available indicator in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localVideoEnabledIndicator() { + return Locator::forThe()->css(".icon-video:not(.video-disabled):not(.no-video-available)")-> + descendantOf(self::localContainer())-> + describedAs("Video enabled indicator in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localVideoDisabledIndicator() { + return Locator::forThe()->css(".icon-video-off:not(.no-video-available)")-> + descendantOf(self::localContainer())-> + describedAs("Video disabled indicator in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function localVideoNotAvailableIndicator() { + return Locator::forThe()->css(".no-video-available")-> + descendantOf(self::localContainer())-> + describedAs("Video not available indicator in the local container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function containerFor($user) { + return Locator::forThe()->xpath("//div[contains(concat(' ', normalize-space(@class), ' '), ' videoContainer ') and not(contains(concat(' ', normalize-space(@class), ' '), ' promoted '))]//div[contains(concat(' ', normalize-space(@class), ' '), ' nameIndicator ') and normalize-space() = '$user']/..")-> + descendantOf(TalkAppContext::mainView())-> + describedAs("Container for $user of the call in the main view"); + } + + /** + * @return Locator + */ + public static function videoFor($user) { + return Locator::forThe()->css("video")-> + descendantOf(self::containerFor($user))-> + describedAs("Video in the container for $user of the call in the main view"); + } + + /** + * @return Locator + */ + public static function avatarFor($user) { + return Locator::forThe()->css(".avatar-container")-> + descendantOf(self::containerFor($user))-> + describedAs("Avatar in the container for $user of the call in the main view"); + } + + /** + * @return Locator + */ + public static function audioNotAvailableIndicatorFor($user) { + return Locator::forThe()->css(".audio-off")-> + descendantOf(self::containerFor($user))-> + describedAs("Audio not available indicator in the container for $user of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedContainer() { + return Locator::forThe()->css(".videoContainer.promoted")-> + descendantOf(TalkAppContext::mainView())-> + describedAs("Promoted container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedDummyContainer() { + // A dummy container is used to show the user name and the media + // permissions at the same place shown in the unpromoted container for + // the user (as the promoted container is centered and the unpromoted + // container can be anywhere in the bottom area). + return Locator::forThe()->css(".videoContainer-dummy")-> + descendantOf(TalkAppContext::mainView())-> + describedAs("Promoted dummy container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedVideo() { + return Locator::forThe()->css("video")-> + descendantOf(self::promotedContainer())-> + describedAs("Video in the promoted container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedAvatar() { + return Locator::forThe()->css(".avatar-container")-> + descendantOf(self::promotedContainer())-> + describedAs("Avatar in the promoted container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedUserName() { + return Locator::forThe()->css(".nameIndicator")-> + descendantOf(self::promotedDummyContainer())-> + describedAs("Name indicator in the promoted dummy container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedAudioEnabledIndicator() { + return Locator::forThe()->css(".audio-on")-> + descendantOf(self::promotedDummyContainer())-> + describedAs("Audio enabled indicator in the promoted dummy container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedAudioNotAvailableIndicator() { + return Locator::forThe()->css(".audio-off")-> + descendantOf(self::promotedDummyContainer())-> + describedAs("Audio not available indicator in the promoted dummy container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedVideoEnabledIndicator() { + return Locator::forThe()->css(".icon-video")-> + descendantOf(self::promotedDummyContainer())-> + describedAs("Video enabled indicator in the promoted dummy container of the call in the main view"); + } + + /** + * @return Locator + */ + public static function promotedVideoDisabledIndicator() { + return Locator::forThe()->css(".icon-video-off")-> + descendantOf(self::promotedDummyContainer())-> + describedAs("Video disabled indicator in the promoted dummy container of the call in the main view"); + } + + /** + * @When I enable the local audio + */ + public function iEnableTheLocalAudio() { + $this->actor->find(self::localAudioDisabledIndicator(), 10)->click(); + } + + /** + * @When I disable the local audio + */ + public function iDisableTheLocalAudio() { + $this->actor->find(self::localAudioEnabledIndicator(), 10)->click(); + } + + /** + * @When I enable the local video + */ + public function iEnableTheLocalVideo() { + $this->actor->find(self::localVideoDisabledIndicator(), 10)->click(); + } + + /** + * @When I disable the local video + */ + public function iDisableTheLocalVideo() { + $this->actor->find(self::localVideoEnabledIndicator(), 10)->click(); + } + + /** + * @When I enable the promoted video + */ + public function iEnableThePromotedVideo() { + $this->actor->find(self::promotedVideoDisabledIndicator(), 10)->click(); + } + + /** + * @When I disable the promoted video + */ + public function iDisableThePromotedVideo() { + $this->actor->find(self::promotedVideoEnabledIndicator(), 10)->click(); + } + + /** + * @Then I see that the local audio is enabled + */ + public function iSeeThatTheLocalAudioIsEnabled() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::localAudioEnabledIndicator(), 10)); + } + + /** + * @Then I see that the local audio is disabled + */ + public function iSeeThatTheLocalAudioIsDisabled() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::localAudioDisabledIndicator(), 10)); + } + + /** + * @Then I see that the local audio is not available + */ + public function iSeeThatTheLocalAudioIsNotAvailable() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::localAudioNotAvailableIndicator(), 10)); + } + + /** + * @Then I see that the local video is enabled + */ + public function iSeeThatTheLocalVideoIsEnabled() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::localVideoEnabledIndicator(), 10)); + } + + /** + * @Then I see that the local video is disabled + */ + public function iSeeThatTheLocalVideoIsDisabled() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::localVideoDisabledIndicator(), 10)); + } + + /** + * @Then I see that the local video is not available + */ + public function iSeeThatTheLocalVideoIsNotAvailable() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::localVideoNotAvailableIndicator(), 10)); + } + + /** + * @Then I see that the local video is shown + */ + public function iSeeThatTheLocalVideoIsShown() { + if (!WaitFor::elementToBeEventuallyShown( + $this->actor, + self::localVideo(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The local video was not shown yet after $timeout seconds"); + } + } + + /** + * @Then I see that the local video is not shown + */ + public function iSeeThatTheLocalVideoIsNotShown() { + if (!WaitFor::elementToBeEventuallyNotShown( + $this->actor, + self::localVideo(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The local video is still shown after $timeout seconds"); + } + } + + /** + * @Then I see that the local avatar is shown + */ + public function iSeeThatTheLocalAvatarIsShown() { + if (!WaitFor::elementToBeEventuallyShown( + $this->actor, + self::localAvatar(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The local avatar was not shown yet after $timeout seconds"); + } + } + + /** + * @Then I see that the local avatar is not shown + */ + public function iSeeThatTheLocalAvatarIsNotShown() { + if (!WaitFor::elementToBeEventuallyNotShown( + $this->actor, + self::localAvatar(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The local avatar is still shown after $timeout seconds"); + } + } + + /** + * @Then I see that the video for :user is not shown + */ + public function iSeeThatTheVideoForIsNotShown($user) { + if (!WaitFor::elementToBeEventuallyNotShown( + $this->actor, + self::videoFor($user), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The video for $user is still shown after $timeout seconds"); + } + } + + /** + * @Then I see that the avatar for :user is shown + */ + public function iSeeThatTheAvatarForIsShown($user) { + if (!WaitFor::elementToBeEventuallyShown( + $this->actor, + self::avatarFor($user), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The avatar for $user was not shown yet after $timeout seconds"); + } + } + + /** + * @Then I see that the audio for :user is not available + */ + public function iSeeThatTheAudioForIsNotAvailable($user) { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::audioNotAvailableIndicatorFor($user), 10)); + } + + /** + * @Then I see that the promoted video is shown + */ + public function iSeeThatThePromotedVideoIsShown() { + if (!WaitFor::elementToBeEventuallyShown( + $this->actor, + self::promotedVideo(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The promoted video was not shown yet after $timeout seconds"); + } + } + + /** + * @Then I see that the promoted video is not shown + */ + public function iSeeThatThePromotedVideoIsNotShown() { + if (!WaitFor::elementToBeEventuallyNotShown( + $this->actor, + self::promotedVideo(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The promoted video is still shown after $timeout seconds"); + } + } + + /** + * @Then I see that the promoted avatar is shown + */ + public function iSeeThatThePromotedAvatarIsShown() { + if (!WaitFor::elementToBeEventuallyShown( + $this->actor, + self::promotedAvatar(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The promoted avatar was not shown yet after $timeout seconds"); + } + } + + /** + * @Then I see that the promoted avatar is not shown + */ + public function iSeeThatThePromotedAvatarIsNotShown() { + if (!WaitFor::elementToBeEventuallyNotShown( + $this->actor, + self::promotedAvatar(), + $timeout = 10 * $this->actor->getFindTimeoutMultiplier())) { + PHPUnit_Framework_Assert::fail("The promoted avatar is still shown after $timeout seconds"); + } + } + + /** + * @Then I see that the promoted user is :userName + */ + public function iSeeThatThePromotedUserIs($userName) { + $promotedUserNameMatchedCallback = function() use($userName) { + try { + $foundUserName = $this->actor->find(self::promotedUserName())->getText(); + } catch (NoSuchElementException $exception) { + return false; + } + + if ($foundUserName == $userName) { + return true; + } + + return false; + }; + + if (!Utils::waitFor($promotedUserNameMatchedCallback, $timeout = 10 * $this->actor->getFindTimeoutMultiplier(), $timeoutStep = 1)) { + PHPUnit_Framework_Assert::fail("The promoted user name was not $userName yet after $timeout seconds"); + } + } + + /** + * @Then I see that the promoted audio is enabled + */ + public function iSeeThatThePromotedAudioIsEnabled() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::promotedAudioEnabledIndicator(), 10)); + } + + /** + * @Then I see that the promoted audio is not available + */ + public function iSeeThatThePromotedAudioIsNotAvailable() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::promotedAudioNotAvailableIndicator(), 10)); + } + + /** + * @Then I see that the promoted video is enabled + */ + public function iSeeThatThePromotedVideoIsEnabled() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::promotedVideoEnabledIndicator(), 10)); + } + + /** + * @Then I see that the promoted video is disabled + */ + public function iSeeThatThePromotedVideoIsDisabled() { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::promotedVideoDisabledIndicator(), 10)); + } + +} diff --git a/tests/acceptance/features/bootstrap/ChatContext.php b/tests/acceptance/features/bootstrap/ChatContext.php index c269cba18d6..adabfe207cd 100644 --- a/tests/acceptance/features/bootstrap/ChatContext.php +++ b/tests/acceptance/features/bootstrap/ChatContext.php @@ -215,7 +215,14 @@ public function iSendANewChatMessageWith($message) { * @Then I see that the chat is shown in the main view */ public function iSeeThatTheChatIsShownInTheMainView() { - PHPUnit_Framework_Assert::assertTrue($this->actor->find(self::chatView($this->chatAncestor), 10)->isVisible()); + PHPUnit_Framework_Assert::assertTrue($this->actor->find(self::chatView(TalkAppContext::mainView()), 10)->isVisible()); + } + + /** + * @Then I see that the chat is shown in the sidebar + */ + public function iSeeThatTheChatIsShownInTheSidebar() { + PHPUnit_Framework_Assert::assertTrue($this->actor->find(self::chatView(TalkAppContext::sidebar()), 10)->isVisible()); } /** diff --git a/tests/acceptance/features/bootstrap/ConversationInfoContext.php b/tests/acceptance/features/bootstrap/ConversationInfoContext.php index fe8b07ef9dd..60c2ec3d520 100644 --- a/tests/acceptance/features/bootstrap/ConversationInfoContext.php +++ b/tests/acceptance/features/bootstrap/ConversationInfoContext.php @@ -26,6 +26,7 @@ class ConversationInfoContext implements Context, ActorAwareInterface { use ActorAware; + use ChatAncestorSetter; /** * @return Locator @@ -72,6 +73,24 @@ public static function conversationNameTextInput() { describedAs("Conversation name text input in conversation info"); } + /** + * @return Locator + */ + public static function joinCallButton() { + return Locator::forThe()->css(".join-call")-> + descendantOf(self::conversationInfoContainer())-> + describedAs("Join call button in conversation info"); + } + + /** + * @return Locator + */ + public static function leaveCallButton() { + return Locator::forThe()->css(".leave-call")-> + descendantOf(self::conversationInfoContainer())-> + describedAs("Leave call button in conversation info"); + } + /** * @Given I rename the conversation to :newConversationName */ @@ -81,4 +100,22 @@ public function iRenameTheConversationTo($newConversationName) { $this->actor->find(self::conversationNameTextInput(), 2)->setValue($newConversationName . "\r"); } + /** + * @Given I join the call + */ + public function iJoinTheCall() { + $this->actor->find(self::joinCallButton(), 10)->click(); + + $this->setChatAncestorForActor(TalkAppContext::sidebar(), $this->actor); + } + + /** + * @Given I leave the call + */ + public function iLeaveTheCall() { + $this->actor->find(self::leaveCallButton(), 10)->click(); + + $this->setChatAncestorForActor(TalkAppContext::mainView(), $this->actor); + } + } diff --git a/tests/acceptance/features/call.feature b/tests/acceptance/features/call.feature new file mode 100644 index 00000000000..a0ebc7e4e5e --- /dev/null +++ b/tests/acceptance/features/call.feature @@ -0,0 +1,527 @@ +Feature: call + + Scenario: start a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + When I join the call + Then I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I see that the local audio is enabled + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + + Scenario: start a call without camera + Given I act as "Karen with microphone" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + When I join the call + Then I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I see that the local audio is enabled + And I see that the local avatar is shown + And I see that the local video is not available + And I see that the local video is not shown + + Scenario: start a call without camera nor microphone + Given I act as "James" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + When I join the call + Then I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I see that the local avatar is shown + And I see that the local audio is not available + And I see that the local video is not available + And I see that the local video is not shown + + Scenario: leave a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + When I leave the call + Then I see that the chat is shown in the main view + + Scenario: join a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + When I join the call + Then I see that the chat is shown in the sidebar + And I see that the local audio is enabled + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "user0" + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "admin" + + Scenario: join a call without camera + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "Karen with microphone" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + When I join the call + Then I see that the chat is shown in the sidebar + And I see that the local audio is enabled + And I see that the local avatar is shown + And I see that the local video is not available + And I see that the local video is not shown + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "user0" + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is enabled + And I see that the promoted avatar is shown + And I see that the promoted video is not shown + And I see that the promoted user is "admin" + + Scenario: join a call without camera nor microphone + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "James" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + When I join the call + Then I see that the chat is shown in the sidebar + And I see that the local avatar is shown + And I see that the local audio is not available + And I see that the local video is not available + And I see that the local video is not shown + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "user0" + And I act as "Kermit with microphone and camera" + And I see that the audio for "admin" is not available + And I see that the avatar for "admin" is shown + And I see that the video for "admin" is not shown + + Scenario: leave a call with another participant + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is shown + And I act as "Kermit with microphone and camera" + And I see that the promoted video is shown + When I leave the call + Then I see that the chat is shown in the main view + And I act as "April with microphone and camera" + And I see that the chat is shown in the sidebar + And I see that the "Waiting for user0 to join the call …" empty content message is shown in the main view + + Scenario: disable local video during a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is shown + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + When I disable the local video + Then I see that the local video is disabled + And I see that the local video is not shown + And I see that the local avatar is shown + And I see that the local audio is enabled + And I see that the promoted video is shown + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is enabled + And I see that the promoted avatar is shown + And I see that the promoted video is not shown + And I see that the promoted user is "admin" + + Scenario: disable local audio during a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is shown + And I see that the local audio is enabled + When I disable the local audio + Then I see that the local audio is disabled + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is not available + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "admin" + + Scenario: enable again local video during a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is shown + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + And I disable the local video + And I see that the local video is disabled + And I act as "Kermit with microphone and camera" + And I see that the promoted video is not shown + When I act as "April with microphone and camera" + And I enable the local video + Then I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + And I see that the local audio is enabled + And I see that the promoted video is shown + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "admin" + + Scenario: enable again local audio during a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is shown + And I see that the local audio is enabled + And I disable the local audio + And I see that the local audio is disabled + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is not available + When I act as "April with microphone and camera" + And I enable the local audio + Then I see that the local audio is enabled + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "admin" + + Scenario: join again a call after disabling local video + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is shown + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + And I disable the local video + And I see that the local video is disabled + When I leave the call + And I see that the chat is shown in the main view + And I join the call + Then I see that the chat is shown in the sidebar + And I see that the local audio is enabled + And I see that the local avatar is shown + And I see that the local video is disabled + And I see that the local video is not shown + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "user0" + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is enabled + And I see that the promoted avatar is shown + And I see that the promoted video is not shown + And I see that the promoted user is "admin" + + Scenario: join again a call after disabling local audio + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is shown + And I see that the local audio is enabled + And I disable the local audio + And I see that the local audio is disabled + When I leave the call + And I see that the chat is shown in the main view + And I join the call + Then I see that the chat is shown in the sidebar + And I see that the local audio is disabled + And I see that the local video is enabled + And I see that the local video is shown + And I see that the local avatar is not shown + And I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "user0" + And I act as "Kermit with microphone and camera" + And I see that the promoted audio is not available + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "admin" + + Scenario: disable remote video during a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + When I disable the promoted video + Then I see that the promoted audio is enabled + And I see that the promoted avatar is shown + And I see that the promoted video is disabled + And I see that the promoted video is not shown + And I see that the promoted user is "user0" + + Scenario: enable again remote video during a call + Given I act as "Kermit with microphone and camera" + And I am logged in + And I have opened the Talk app + And I create a one-to-one conversation with "admin" + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I see that the "Waiting for admin to join the call …" empty content message is shown in the main view + And I act as "April with microphone and camera" + And I am logged in as the admin + And I have opened the Talk app + And I open the "user0" conversation + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I disable the promoted video + And I see that the promoted avatar is shown + And I see that the promoted video is disabled + And I see that the promoted video is not shown + When I enable the promoted video + Then I see that the promoted audio is enabled + And I see that the promoted video is enabled + And I see that the promoted video is shown + And I see that the promoted avatar is not shown + And I see that the promoted user is "user0" + + Scenario: send messages during a call + Given I act as "Karen with microphone" + And I am logged in as the admin + And I have opened the Talk app + And I create a one-to-one conversation with "user0" + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I act as "Jarvis with microphone" + And I am logged in + And I have opened the Talk app + And I open the "admin" conversation + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + When I act as "Karen with microphone" + And I send a new chat message with the text "Hello" + And I act as "Jarvis with microphone" + And I see that the message 1 was sent by "admin" with the text "Hello" + And I send a new chat message with the text "Hi!" + Then I see that the message 1 was sent by "admin" with the text "Hello" + And I see that the message 2 was sent by "user0" with the text "Hi!" + And I act as "Karen with microphone" + And I see that the message 1 was sent by "admin" with the text "Hello" + And I see that the message 2 was sent by "user0" with the text "Hi!" + + Scenario: start and join a call after sending messages + Given I act as "Karen with microphone" + And I am logged in as the admin + And I have opened the Talk app + And I create a one-to-one conversation with "user0" + And I see that the "user0" conversation is active + And I see that the chat is shown in the main view + And I act as "Jarvis with microphone" + And I am logged in + And I have opened the Talk app + And I open the "admin" conversation + And I see that the "admin" conversation is active + And I see that the chat is shown in the main view + And I act as "Karen with microphone" + And I send a new chat message with the text "Hello" + And I act as "Jarvis with microphone" + And I see that the message 1 was sent by "admin" with the text "Hello" + And I send a new chat message with the text "Hi!" + When I join the call + And I see that the chat is shown in the sidebar + And I act as "Karen with microphone" + And I join the call + And I see that the chat is shown in the sidebar + Then I see that the message 1 was sent by "admin" with the text "Hello" + And I see that the message 2 was sent by "user0" with the text "Hi!" + And I act as "Jarvis with microphone" + And I see that the message 1 was sent by "admin" with the text "Hello" + And I see that the message 2 was sent by "user0" with the text "Hi!" + + Scenario: leave a call after sending messages + Given I act as "Karen with microphone" + And I am logged in as the admin + And I have opened the Talk app + And I create a one-to-one conversation with "user0" + And I see that the "user0" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I act as "Jarvis with microphone" + And I am logged in + And I have opened the Talk app + And I open the "admin" conversation + And I see that the "admin" conversation is active + And I join the call + And I see that the chat is shown in the sidebar + And I act as "Karen with microphone" + And I send a new chat message with the text "Hello" + And I act as "Jarvis with microphone" + And I see that the message 1 was sent by "admin" with the text "Hello" + And I send a new chat message with the text "Hi!" + When I leave the call + And I see that the chat is shown in the main view + And I act as "Karen with microphone" + And I leave the call + And I see that the chat is shown in the main view + Then I see that the message 1 was sent by "admin" with the text "Hello" + And I see that the message 2 was sent by "user0" with the text "Hi!" + And I act as "Jarvis with microphone" + And I see that the message 1 was sent by "admin" with the text "Hello" + And I see that the message 2 was sent by "user0" with the text "Hi!"