diff options
author | Charles Kerr <charles.kerr@canonical.com> | 2016-01-05 13:12:58 -0600 |
---|---|---|
committer | Charles Kerr <charles.kerr@canonical.com> | 2016-01-05 13:12:58 -0600 |
commit | cbca1818ef142938022511abded7e39d671866ac (patch) | |
tree | b655eb961c3265d3ffb987cf3e9740f6fbc2da73 /tests/integration/test-indicator.cpp | |
parent | c0c4180561fba3e1ebe3f22381a4b5609e22f17b (diff) | |
parent | 58e4e5dd08444a193a52ae103f6bd432772dacc7 (diff) | |
download | ayatana-indicator-sound-cbca1818ef142938022511abded7e39d671866ac.tar.gz ayatana-indicator-sound-cbca1818ef142938022511abded7e39d671866ac.tar.bz2 ayatana-indicator-sound-cbca1818ef142938022511abded7e39d671866ac.zip |
adding lp:~xavi-garcia-mena/indicator-sound/restore-osd-notifications
Diffstat (limited to 'tests/integration/test-indicator.cpp')
-rw-r--r-- | tests/integration/test-indicator.cpp | 981 |
1 files changed, 981 insertions, 0 deletions
diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp new file mode 100644 index 0000000..33e62b5 --- /dev/null +++ b/tests/integration/test-indicator.cpp @@ -0,0 +1,981 @@ +/* + * Copyright (C) 2015 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Xavi Garcia <xavi.garcia.mena@canonical.com> + */ + +#include <indicator-sound-test-base.h> + +#include <QDebug> +#include <QTestEventLoop> +#include <QSignalSpy> + +using namespace std; +using namespace testing; +namespace mh = unity::gmenuharness; +namespace +{ + +class TestIndicator: public IndicatorSoundTestBase +{ +}; + +TEST_F(TestIndicator, PhoneChangeRoleVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setStreamRestoreVolume("multimedia", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // Generate a random volume + QTime now = QTime::currentTime(); + qsrand(now.msec()); + int randInt = qrand() % 100; + double randomVolume = randInt / 100.0; + + QSignalSpy &userAccountsSpy = *signal_spy_volume_changed_; + // set an initial volume to the alert role + userAccountsSpy.clear(); + EXPECT_TRUE(setVolumeUntilAccountsIsConnected(1.0)); + userAccountsSpy.clear(); + // play a test sound, it should change the role in the indicator + EXPECT_TRUE(startTestSound("multimedia")); + + // this time we only expect 1 signal as it's only the indicator + // updating the value + WAIT_FOR_SIGNALS(userAccountsSpy, 1); + //EXPECT_TRUE(waitVolumeChangedInIndicator()); + + userAccountsSpy.clear(); + // set the random volume to the multimedia role + setActionValue("volume", QVariant::fromValue(randomVolume)); + if (randomVolume != INITIAL_VOLUME) + { + WAIT_FOR_SIGNALS(userAccountsSpy, 1); + } + + // check the indicator + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(randomVolume, "Volume")) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); + + // initialize the signal spy + EXPECT_TRUE(initializeMenuChangedSignal()); + userAccountsSpy.clear(); + // stop the test sound, the role should change again to alert + stopTestSound(); + if (randomVolume != 1.0) + { + // wait for the menu change + EXPECT_TRUE(waitMenuChange()); + } + + // check the initial volume for the alert role + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(1.0, "Volume")) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); +} + +TEST_F(TestIndicator, PhoneBasicInitialVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); +} + +TEST_F(TestIndicator, PhoneAddMprisPlayer) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); + + // initialize the signal spy + EXPECT_TRUE(initializeMenuChangedSignal()); + + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + + // wait for the menu change + EXPECT_TRUE(waitMenuChange()); + + // finally verify that the player is added + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); +} + +TEST_F(TestIndicator, DesktopBasicInitialVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulseDesktop()); + + // initialize volumes in pulseaudio + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); +} + +TEST_F(TestIndicator, DesktopAddMprisPlayer) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulseDesktop()); + + // initialize volumes in pulseaudio + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // check that the player is added + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); +} + +TEST_F(TestIndicator, DesktopMprisPlayerButtonsState) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulseDesktop()); + + // initialize volumes in pulseaudio + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // check that the player is added + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); + + // change the state of CanGoNext + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoNext", false)); + + // verify that the action changes + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .attribute_not_set("x-canonical-next-action") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); + + + // change the state of CanGoPrevious + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoPrevious", false)); + + // verify that the action changes + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .attribute_not_set("x-canonical-previous-action") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .attribute_not_set("x-canonical-next-action") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); + + // set back both to true + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoNext", true)); + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoPrevious", true)); + + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); +} + +TEST_F(TestIndicator, DesktopChangeRoleVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulseDesktop()); + + // initialize volumes in pulseaudio + // expect false for stream restore, because the module + // is not loaded in the desktop pulseaudio instance + EXPECT_FALSE(setStreamRestoreVolume("mutimedia", INITIAL_VOLUME)); + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // Generate a random volume + QTime now = QTime::currentTime(); + qsrand(now.msec()); + int randInt = qrand() % 100; + double randomVolume = randInt / 100.0; + + // play a test sound, it should NOT change the role in the indicator + EXPECT_TRUE(startTestSound("multimedia")); + EXPECT_FALSE(waitVolumeChangedInIndicator()); + + // set the random volume + EXPECT_TRUE(setSinkVolume(randomVolume)); + if (randomVolume != INITIAL_VOLUME) + { + EXPECT_TRUE(waitVolumeChangedInIndicator()); + } + + // check the indicator + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(randomVolume, "Volume")) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); + + // stop the test sound, the role should change again to alert + stopTestSound(); + + // although we were playing something in the multimedia role + // the server does not have the streamrestore module, so + // the volume does not change (the role does not change) + EXPECT_FALSE(waitVolumeChangedInIndicator()); + + // check the initial volume for the alert role + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(randomVolume, "Volume")) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); +} + +TEST_F(TestIndicator, PhoneNotificationVolume) +{ + double INITIAL_VOLUME = 0.0; + + QSignalSpy notificationsSpy(¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &))); + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // check the initial state + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME, "Volume")) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); + + // change volume to 1.0 + setActionValue("volume", QVariant::fromValue(1.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 3); + + // the first time we also have the calls to + // GetServerInformation and GetCapabilities + checkNotificationWithNoArgs("GetServerInformation", notificationsSpy.at(0)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(1)); + checkVolumeNotification(1.0, "Speakers", false, notificationsSpy.at(2)); + + notificationsSpy.clear(); + setActionValue("volume", QVariant::fromValue(0.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 2) + + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkVolumeNotification(0.0, "Speakers", false, notificationsSpy.at(1)); + + notificationsSpy.clear(); + setActionValue("volume", QVariant::fromValue(0.5)); + + WAIT_FOR_SIGNALS(notificationsSpy, 2) + + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkVolumeNotification(0.5, "Speakers", false, notificationsSpy.at(1)); +} + +TEST_F(TestIndicator, PhoneNotificationWarningVolume) +{ + double INITIAL_VOLUME = 0.0; + + QSignalSpy notificationsSpy(¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &))); + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setStreamRestoreVolume("multimedia", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // activate the headphones + EXPECT_TRUE(activateHeadphones(true)); + + // set an initial volume to the alert role + setStreamRestoreVolume("alert", 1.0); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + // play a test sound, it should change the role in the indicator + EXPECT_TRUE(startTestSound("multimedia")); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + WAIT_FOR_SIGNALS(notificationsSpy, 3); + // the first time we also have the calls to + // GetServerInformation and GetCapabilities + checkNotificationWithNoArgs("GetServerInformation", notificationsSpy.at(0)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(1)); + checkVolumeNotification(0.0, "Headphones", false, notificationsSpy.at(2)); + notificationsSpy.clear(); + + // change volume to 0.3... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.3)); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + WAIT_FOR_SIGNALS(notificationsSpy, 2); + + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkVolumeNotification(0.3, "Headphones", false, notificationsSpy.at(1)); + notificationsSpy.clear(); + + // change volume to 0.5... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.5)); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + WAIT_FOR_SIGNALS(notificationsSpy, 2); + + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkVolumeNotification(0.5, "Headphones", false, notificationsSpy.at(1)); + notificationsSpy.clear(); + + // change volume to 1.0... warning should be emitted + setActionValue("volume", QVariant::fromValue(1.0)); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + WAIT_FOR_SIGNALS(notificationsSpy, 8); + + // the notification is sent twice (TODO check why) + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkCloseNotification(1, notificationsSpy.at(1)); + checkHighVolumeNotification(notificationsSpy.at(2)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(3)); + checkCloseNotification(1, notificationsSpy.at(4)); + checkHighVolumeNotification(notificationsSpy.at(5)); + + // get the last notification ID + int idNotification = getNotificationID(notificationsSpy.at(5)); + ASSERT_NE(-1, idNotification); + + qWarning() << "XGM: id Notification: " << idNotification; + + // cancel the dialog + pressNotificationButton(idNotification, "cancel"); + + // check that the volume was clamped + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(0.74, "Volume (Headphones)")) + ) + ).match()); + + // try again... + notificationsSpy.clear(); + + qWarning() << "-----------------------------------------------------------"; + // change volume to 1.0... warning should be emitted + setActionValue("volume", QVariant::fromValue(1.0)); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + WAIT_FOR_SIGNALS(notificationsSpy, 6); + + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkHighVolumeNotification(notificationsSpy.at(1)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(2)); + checkHighVolumeNotification(notificationsSpy.at(3)); + + // get the last notification ID + idNotification = getNotificationID(notificationsSpy.at(1)); + ASSERT_NE(-1, idNotification); + + // this time we approve + pressNotificationButton(idNotification, "ok"); + + // check that the volume was applied + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(1.0, "Volume (Headphones)")) + .item(mh::MenuItemMatcher() + .action("indicator.high-volume-warning-item") + .label("High volume can damage your hearing.") + ) + ) + ).match()); + + // after the warning was approved we should be able to modify the volume + // and don't get the warning + notificationsSpy.clear(); + + // change volume to 0.5... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.5)); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + WAIT_FOR_SIGNALS(notificationsSpy, 6); + + // check the notification TODO check why the sound indicator sends it twice + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkCloseNotification(idNotification, notificationsSpy.at(1)); + checkVolumeNotification(0.5, "Headphones", false, notificationsSpy.at(2)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(3)); + checkCloseNotification(idNotification, notificationsSpy.at(4)); + checkVolumeNotification(0.5, "Headphones", false, notificationsSpy.at(5)); + + // check that the volume was applied + // and that we don't have the warning item + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(0.5, "Volume (Headphones)")) + ) + ).match()); + + // now set high volume again, we should not get the warning dialog + // as we already approved it + notificationsSpy.clear(); + + setActionValue("volume", QVariant::fromValue(1.0)); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + WAIT_FOR_SIGNALS(notificationsSpy, 4); + + // check the notification TODO check why the sound indicator sends it twice + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkVolumeNotification(1.0, "Headphones", true, notificationsSpy.at(1)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(2)); + checkVolumeNotification(1.0, "Headphones", true, notificationsSpy.at(3)); +} + + +TEST_F(TestIndicator, PhoneNotificationWarningVolumeAlertMode) +{ + double INITIAL_VOLUME = 0.0; + + QSignalSpy notificationsSpy(¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &))); + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setStreamRestoreVolume("multimedia", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // activate the headphones + EXPECT_TRUE(activateHeadphones(true)); + + // set an initial volume to the alert role + setStreamRestoreVolume("alert", 1.0); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + // change volume to 0.0... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 5); + + // the first time we also have the calls to + // GetServerInformation and GetCapabilities + checkNotificationWithNoArgs("GetServerInformation", notificationsSpy.at(0)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(1)); + checkVolumeNotification(0.0, "Headphones", false, notificationsSpy.at(2)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(3)); + checkVolumeNotification(0.0, "Headphones", false, notificationsSpy.at(4)); + notificationsSpy.clear(); + + // change volume to 0.5... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.5)); + + WAIT_FOR_SIGNALS(notificationsSpy, 2); + + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkVolumeNotification(0.5, "Headphones", false, notificationsSpy.at(1)); + notificationsSpy.clear(); + + // change volume to 1.0... no warning should be emitted, we are in alert mode + setActionValue("volume", QVariant::fromValue(1.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 2); + + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(0)); + checkVolumeNotification(1.0, "Headphones", false, notificationsSpy.at(1)); + notificationsSpy.clear(); +} + +TEST_F(TestIndicator, PhoneNotificationHeadphoneSpeakerWiredLabels) +{ + checkPortDevicesLabels(WIRED, WIRED); +} + +TEST_F(TestIndicator, PhoneNotificationHeadphoneSpeakerBluetoothLabels) +{ + checkPortDevicesLabels(BLUETOOTH, BLUETOOTH); +} + +TEST_F(TestIndicator, PhoneNotificationHeadphoneSpeakerUSBLabels) +{ + checkPortDevicesLabels(USB, USB); +} + +TEST_F(TestIndicator, PhoneNotificationHeadphoneSpeakerHDMILabels) +{ + checkPortDevicesLabels(HDMI, HDMI); +} + +} // namespace |