@@ -21,6 +21,7 @@
2121
2222from __future__ import absolute_import
2323
24+from unity8 import shell
2425from unity8.process_helpers import unlock_unity
2526from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
2627
@@ -64,7 +65,8 @@ class NotificationsBase(UnityTestCase):
6465 if os.path.abspath(__file__).startswith('/usr/'):
6566 return '/usr/share/unity8/graphics/' + icon_name
6667 else:
67− return os.path.dirname(__file__) + "/../../../../../qml/graphics/" + icon_name
68+ return os.path.dirname(__file__) + (
69+ "/../../../../../qml/graphics/" + icon_name)
6870
6971 def _get_notifications_list(self):
7072 return self.main_window.select_single(
@@ -196,7 +198,7 @@ class InteractiveNotificationBase(NotificationsBase):
196198 get_notification = lambda: notify_list.wait_select_single(
197199 'Notification', objectName='notification1')
198200 notification = get_notification()
199− self._assert_notification(notification, None, None, True, True, 1.0)
201+ self._assert_notification(notification, summary, body, True, True, 1.0)
200202 initial_height = notification.height
201203 self.touch.tap_object(notification.select_single(objectName="button1"))
202204 self.assertThat(
@@ -209,6 +211,89 @@ class InteractiveNotificationBase(NotificationsBase):
209211 self.touch.tap_object(notification.select_single(objectName="button4"))
210212 self.assert_notification_action_id_was_called("action_decline_4")
211213
214+ def test_modal_sd_without_greeter (self):
215+ """A snap-decision on a phone should block input to shell beneath it when there's no greeter."""
216+ unity_proxy = self.launch_unity()
217+ unlock_unity(unity_proxy)
218+
219+ summary = "Incoming file"
220+ body = "Frank would like to send you the file: essay.pdf"
221+ icon_path = "sync-idle"
222+ hints = [
223+ ("x-canonical-snap-decisions", "true"),
224+ ("x-canonical-non-shaped-icon", "true"),
225+ ]
226+
227+ actions = [
228+ ('action_accept', 'Accept'),
229+ ('action_decline_1', 'Decline'),
230+ ]
231+
232+ self._create_interactive_notification(
233+ summary,
234+ body,
235+ icon_path,
236+ "NORMAL",
237+ actions,
238+ hints
239+ )
240+
241+ # verify that we cannot reveal the launcher (no longer interact with the shell)
242+ time.sleep(1)
243+ self.main_window.show_dash_swiping()
244+ launcher = self.main_window.get_launcher()
245+ self.assertThat(launcher.shown, Eventually(Equals(False)))
246+
247+ # verify and interact with the triggered snap-decision notification
248+ notify_list = self._get_notifications_list()
249+ get_notification = lambda: notify_list.wait_select_single(
250+ 'Notification', objectName='notification1')
251+ notification = get_notification()
252+ self._assert_notification(notification, summary, body, True, False, 1.0)
253+ self.touch.tap_object(notification.select_single(objectName="button0"))
254+ self.assert_notification_action_id_was_called("action_accept")
255+
256+ def test_modal_sd_with_greeter (self):
257+ """A snap-decision on a phone should not block input to the greeter beneath it."""
258+ unity_proxy = self.launch_unity()
259+
260+ summary = "Incoming file"
261+ body = "Frank would like to send you the file: essay.pdf"
262+ icon_path = "sync-idle"
263+ hints = [
264+ ("x-canonical-snap-decisions", "true"),
265+ ("x-canonical-non-shaped-icon", "true"),
266+ ]
267+
268+ actions = [
269+ ('action_accept', 'Accept'),
270+ ('action_decline_1', 'Decline'),
271+ ]
272+
273+ self._create_interactive_notification(
274+ summary,
275+ body,
276+ icon_path,
277+ "NORMAL",
278+ actions,
279+ hints
280+ )
281+
282+ # verify that we can swipe away the greeter (interact with the "shell")
283+ time.sleep(1)
284+ self.main_window.show_dash_swiping()
285+ greeter = self.main_window.get_greeter()
286+ self.assertThat(greeter.shown, Eventually(Equals(False)))
287+
288+ # verify and interact with the triggered snap-decision notification
289+ notify_list = self._get_notifications_list()
290+ get_notification = lambda: notify_list.wait_select_single(
291+ 'Notification', objectName='notification1')
292+ notification = get_notification()
293+ self._assert_notification(notification, summary, body, True, False, 1.0)
294+ self.touch.tap_object(notification.select_single(objectName="button0"))
295+ self.assert_notification_action_id_was_called("action_accept")
296+
212297 def _create_interactive_notification(
213298 self,
214299 summary="",
@@ -354,7 +439,7 @@ class EphemeralNotificationsTests(NotificationsBase):
354439 )
355440 ]
356441
357− notification = self._create_ephemeral_notification(
442+ notification = shell.create_ephemeral_notification(
358443 summary,
359444 body,
360445 icon_path,
@@ -391,7 +476,7 @@ class EphemeralNotificationsTests(NotificationsBase):
391476 )
392477 ]
393478
394− notification = self._create_ephemeral_notification(
479+ notification = shell.create_ephemeral_notification(
395480 summary,
396481 None,
397482 None,
@@ -403,7 +488,6 @@ class EphemeralNotificationsTests(NotificationsBase):
403488
404489 notification = lambda: notify_list.wait_select_single(
405490 'Notification', objectName='notification1')
406−
407491 self._assert_notification(
408492 notification(),
409493 summary,
@@ -434,7 +518,7 @@ class EphemeralNotificationsTests(NotificationsBase):
434518 body_critical = 'Dude, this is so urgent you have no idea :)'
435519 icon_path_critical = self._get_icon_path('avatars/anna_olsson.png')
436520
437− notification_normal = self._create_ephemeral_notification(
521+ notification_normal = shell.create_ephemeral_notification(
438522 summary_normal,
439523 body_normal,
440524 icon_path_normal,
@@ -442,7 +526,7 @@ class EphemeralNotificationsTests(NotificationsBase):
442526 )
443527 notification_normal.show()
444528
445− notification_low = self._create_ephemeral_notification(
529+ notification_low = shell.create_ephemeral_notification(
446530 summary_low,
447531 body_low,
448532 icon_path_low,
@@ -450,7 +534,7 @@ class EphemeralNotificationsTests(NotificationsBase):
450534 )
451535 notification_low.show()
452536
453− notification_critical = self._create_ephemeral_notification(
537+ notification_critical = shell.create_ephemeral_notification(
454538 summary_critical,
455539 body_critical,
456540 icon_path_critical,
@@ -511,7 +595,7 @@ class EphemeralNotificationsTests(NotificationsBase):
511595 summary = 'Summary-Body'
512596 body = 'This is a superfluous notification'
513597
514− notification = self._create_ephemeral_notification(summary, body)
598+ notification = shell.create_ephemeral_notification(summary, body)
515599 notification.show()
516600
517601 notification = notify_list.wait_select_single(
@@ -535,7 +619,7 @@ class EphemeralNotificationsTests(NotificationsBase):
535619
536620 summary = 'Summary-Only'
537621
538− notification = self._create_ephemeral_notification(summary)
622+ notification = shell.create_ephemeral_notification(summary)
539623 notification.show()
540624
541625 notification = notify_list.wait_select_single(
@@ -555,7 +639,7 @@ class EphemeralNotificationsTests(NotificationsBase):
555639 body = 'This is the original content of this notification-bubble.'
556640 icon_path = self._get_icon_path('avatars/funky.png')
557641
558− notification = self._create_ephemeral_notification(
642+ notification = shell.create_ephemeral_notification(
559643 summary,
560644 body,
561645 icon_path
@@ -579,7 +663,7 @@ class EphemeralNotificationsTests(NotificationsBase):
579663 icon_path = self._get_icon_path('avatars/amanda.png')
580664 notification.update(summary, body, icon_path)
581665 notification.show()
582− self._assert_notification(get_notification(), summary, body)
666+ self._assert_notification(get_notification(), summary, body, True, False, 1.0)
583667
584668 def test_update_notification_layout_change(self):
585669 """Notification must allow updating its contents and layout while
@@ -595,7 +679,7 @@ class EphemeralNotificationsTests(NotificationsBase):
595679 icon_path = self._get_icon_path('avatars/anna_olsson.png')
596680 hint_icon = self._get_icon_path('applicationIcons/phone-app.png')
597681
598− notification = self._create_ephemeral_notification(
682+ notification = shell.create_ephemeral_notification(
599683 summary,
600684 body,
601685 icon_path
@@ -626,7 +710,7 @@ class EphemeralNotificationsTests(NotificationsBase):
626710 notification.show()
627711
628712 self.assertThat(get_notification, Eventually(NotEquals(None)))
629− self._assert_notification(get_notification(), summary, body, False)
713+ self._assert_notification(get_notification(), summary, body, False, False, 1.0)
630714
631715 def test_append_hint(self):
632716 """Notification has to accumulate body-text using append-hint."""
@@ -639,7 +723,7 @@ class EphemeralNotificationsTests(NotificationsBase):
639723 body = 'Hey Bro Coly!'
640724 icon_path = self._get_icon_path('avatars/amanda.png')
641725 body_sum = body
642− notification = self._create_ephemeral_notification(
726+ notification = shell.create_ephemeral_notification(
643727 summary,
644728 body,
645729 icon_path,
@@ -675,7 +759,7 @@ class EphemeralNotificationsTests(NotificationsBase):
675759 for new_body in bodies:
676760 body = new_body
677761 body_sum += '\n' + body
678− notification = self._create_ephemeral_notification(
762+ notification = shell.create_ephemeral_notification(
679763 summary,
680764 body,
681765 icon_path,
@@ -696,48 +780,3 @@ class EphemeralNotificationsTests(NotificationsBase):
696780 False,
697781 1.0
698782 )
699−
700− def _create_ephemeral_notification(
701− self,
702− summary="",
703− body="",
704− icon=None,
705− hints=[],
706− urgency="NORMAL"
707− ):
708− """Create an ephemeral (non-interactive) notification
709−
710− :param summary: Summary text for the notification
711− :param body: Body text to display in the notification
712− :param icon: Path string to the icon to use
713− :param hint_strings: List of tuples containing the 'name' and value
714− for setting the hint strings for the notification
715− :param urgency: Urgency string for the noticiation, either: 'LOW',
716− 'NORMAL', 'CRITICAL'
717−
718− """
719− logger.info(
720− "Creating ephemeral: summary(%s), body(%s), urgency(%r) "
721− "and Icon(%s)",
722− summary,
723− body,
724− urgency,
725− icon
726− )
727−
728− n = Notify.Notification.new(summary, body, icon)
729−
730− for hint in hints:
731− key, value = hint
732− n.set_hint_string(key, value)
733− logger.info("Adding hint to notification: (%s, %s)", key, value)
734− n.set_urgency(self._get_urgency(urgency))
735−
736− return n
737−
738− def _get_urgency(self, urgency):
739− """Translates urgency string to enum."""
740− _urgency_enums = {'LOW': Notify.Urgency.LOW,
741− 'NORMAL': Notify.Urgency.NORMAL,
742− 'CRITICAL': Notify.Urgency.CRITICAL}
743− return _urgency_enums.get(urgency.upper())