Merge lp:~jonas-drange/ubuntu-system-settings/wifi-connect-is-not-dialog-fix-1366006 into lp:ubuntu-system-settings

Proposed by Jonas G. Drange
Status: Merged
Approved by: Ken VanDine
Approved revision: 1054
Merged at revision: 1083
Proposed branch: lp:~jonas-drange/ubuntu-system-settings/wifi-connect-is-not-dialog-fix-1366006
Merge into: lp:ubuntu-system-settings
Diff against target: 1278 lines (+857/-174)
11 files modified
plugins/wifi/CMakeLists.txt (+1/-0)
plugins/wifi/Common.qml (+99/-0)
plugins/wifi/NetworkDetailsBrief.qml (+1/-1)
plugins/wifi/OtherNetwork.qml (+349/-125)
plugins/wifi/PageComponent.qml (+15/-4)
plugins/wifi/nm_manager_proxy.h (+1/-1)
plugins/wifi/wifidbushelper.cpp (+46/-36)
plugins/wifi/wifidbushelper.h (+5/-1)
tests/autopilot/ubuntu_system_settings/__init__.py (+163/-1)
tests/autopilot/ubuntu_system_settings/tests/__init__.py (+42/-5)
tests/autopilot/ubuntu_system_settings/tests/test_wifi.py (+135/-0)
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-system-settings/wifi-connect-is-not-dialog-fix-1366006
Reviewer Review Type Date Requested Status
Ken VanDine Approve
PS Jenkins bot continuous-integration Approve
Sebastien Bacher (community) Needs Fixing
Review via email: mp+234842@code.launchpad.net

Commit message

[wifi] connect to hidden network is now a dialog

Description of the change

Changes the "Connect to hidden network" item to act as a Dialog instead of a page.

It also adds behaviour on failure, which the old page did not have.

QA/translators: POT file will be updated in separate branch.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1038. By Jonas G. Drange

fix code fails

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1039. By Jonas G. Drange

refactoring, cleaning up

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1040. By Jonas G. Drange

proper tests

1041. By Jonas G. Drange

some tweaks and workarounds

1042. By Jonas G. Drange

update pot file

1043. By Jonas G. Drange

readme entry note to self

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1044. By Jonas G. Drange

merge trunk

1045. By Jonas G. Drange

waiting longer may let tests pass?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1046. By Jonas G. Drange

make testing more robust

Revision history for this message
Ken VanDine (ken-vandine) wrote :

Please add a comment to Common.qml including information on where the reason codes come from. The mapping to strings is probably the best we can do, but that mapping will need to be maintained as reason codes get added or changed.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1047. By Jonas G. Drange

fixing pep errors and docs in Common.qml

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

The item for connecting to the hidden network now opens a dialog, so shouldn't show progression and the title should include the "..."

I'm still find the interaction with the OSK annoying, but I don't know what we can do about it.

review: Needs Fixing
1048. By Jonas G. Drange

bar

1049. By Jonas G. Drange

merge trunk

1050. By Jonas G. Drange

update pot

1051. By Jonas G. Drange

adding ellipsis

1052. By Jonas G. Drange

resolve divergence

Revision history for this message
Jonas G. Drange (jonas-drange) wrote :

> The item for connecting to the hidden network now opens a dialog, so shouldn't
> show progression and the title should include the "..."

Right, fixed.

> I'm still find the interaction with the OSK annoying, but I don't know what we
> can do about it.

What are you referring to? If these[1][2] bugs were fixed, that would make the dialog pretty small, i.e. letting anchorToKeyboard property do its thing and keep the OSK from hiding essential things.

[1] https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1337556
[2] https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1185337

Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, it looks fine for an easy read but somebody should do a real review. One comment, can you take the README update to another merge request? It has nothing to do with the changeset/commit message there. The pot update could also be done in a different commit to avoid conflicts with other changes in the same landing

review: Needs Fixing
1053. By Jonas G. Drange

reverting readme, and pot change

Revision history for this message
Jonas G. Drange (jonas-drange) wrote :

> Thanks, it looks fine for an easy read but somebody should do a real review.
> One comment, can you take the README update to another merge request? It has
> nothing to do with the changeset/commit message there. The pot update could
> also be done in a different commit to avoid conflicts with other changes in
> the same landing
Thanks Seb. I've reverted changes to both failes.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1054. By Jonas G. Drange

skip flaky tests

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/wifi/CMakeLists.txt'
2--- plugins/wifi/CMakeLists.txt 2014-08-28 15:08:55 +0000
3+++ plugins/wifi/CMakeLists.txt 2014-09-25 13:39:43 +0000
4@@ -1,6 +1,7 @@
5 set(QML_SOURCES
6 AccessPoint.qml
7 BaseMenuItem.qml
8+Common.qml
9 DivMenuItem.qml
10 FramedMenuItem.qml
11 HLine.qml
12
13=== added file 'plugins/wifi/Common.qml'
14--- plugins/wifi/Common.qml 1970-01-01 00:00:00 +0000
15+++ plugins/wifi/Common.qml 2014-09-25 13:39:43 +0000
16@@ -0,0 +1,99 @@
17+/*
18+ * Copyright (C) 2014 Canonical Ltd
19+ *
20+ * This program is free software: you can redistribute it and/or modify
21+ * it under the terms of the GNU General Public License version 3 as
22+ * published by the Free Software Foundation.
23+ *
24+ * This program is distributed in the hope that it will be useful,
25+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27+ * GNU General Public License for more details.
28+ *
29+ * You should have received a copy of the GNU General Public License
30+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
31+ *
32+ * Authors:
33+ * Jonas G. Drange <jonas.drange@canonical.com>
34+ *
35+*/
36+import QtQuick 2.0
37+
38+Item {
39+
40+
41+ /*
42+ The mapping of code to string is taken from
43+ http://bazaar.launchpad.net/~vcs-imports/
44+ network-manager/trunk/view/head:/cli/src/common.c
45+
46+ NetworkManager documentation: https://developer.gnome.org/
47+ NetworkManager/0.9/spec.html#type-NM_DEVICE_STATE_REASON
48+ */
49+ function reasonToString (reason) {
50+ switch (reason) {
51+ case 0:
52+ return i18n.tr("Unknown error");
53+ case 1:
54+ return i18n.tr("No reason given");
55+ case 2:
56+ return i18n.tr("Device is now managed");
57+ case 3:
58+ return i18n.tr("Device is now unmanaged");
59+ case 4:
60+ return i18n.tr("The device could not be readied for configuration");
61+ case 5:
62+ return i18n.tr("IP configuration could not be reserved (no available address, timeout, etc.)");
63+ case 6:
64+ return i18n.tr("The IP configuration is no longer valid");
65+ case 7:
66+ return i18n.tr("Your authentication details were incorrect");
67+ case 8:
68+ return i18n.tr("802.1X supplicant disconnected");
69+ case 9:
70+ return i18n.tr("802.1X supplicant configuration failed");
71+ case 10:
72+ return i18n.tr("802.1X supplicant failed");
73+ case 11:
74+ return i18n.tr("802.1X supplicant took too long to authenticate");
75+ case 15:
76+ return i18n.tr("DHCP client failed to start");
77+ case 16:
78+ return i18n.tr("DHCP client error");
79+ case 17:
80+ return i18n.tr("DHCP client failed");
81+ case 18:
82+ return i18n.tr("Shared connection service failed to start");
83+ case 19:
84+ return i18n.tr("Shared connection service failed");
85+ case 35:
86+ return i18n.tr("Necessary firmware for the device may be missing");
87+ case 36:
88+ return i18n.tr("The device was removed");
89+ case 37:
90+ return i18n.tr("NetworkManager went to sleep");
91+ case 38:
92+ return i18n.tr("The device's active connection disappeared");
93+ case 39:
94+ return i18n.tr("Device disconnected by user or client");
95+ case 41:
96+ return i18n.tr("The device's existing connection was assumed");
97+ case 42:
98+ return i18n.tr("The supplicant is now available");
99+ case 43:
100+ return i18n.tr("The modem could not be found");
101+ case 44:
102+ return i18n.tr("The Bluetooth connection failed or timed out");
103+ case 50:
104+ return i18n.tr("A dependency of the connection failed");
105+ case 52:
106+ return i18n.tr("ModemManager is unavailable");
107+ case 53:
108+ return i18n.tr("The Wi-Fi network could not be found");
109+ case 54:
110+ return i18n.tr("A secondary connection of the base connection failed");
111+ default:
112+ return i18n.tr("Unknown");
113+ }
114+ }
115+}
116
117=== modified file 'plugins/wifi/NetworkDetailsBrief.qml'
118--- plugins/wifi/NetworkDetailsBrief.qml 2014-08-29 18:12:33 +0000
119+++ plugins/wifi/NetworkDetailsBrief.qml 2014-09-25 13:39:43 +0000
120@@ -46,7 +46,7 @@
121 margins: units.gu(2)
122 }
123 onClicked: {
124- if (DbusHelper.deactivateConnection()) {
125+ if (DbusHelper.disconnectDevice()) {
126 accessPoint.checked = false;
127 accessPoint.checkedChanged(false)
128 }
129
130=== modified file 'plugins/wifi/OtherNetwork.qml'
131--- plugins/wifi/OtherNetwork.qml 2014-09-13 02:44:36 +0000
132+++ plugins/wifi/OtherNetwork.qml 2014-09-25 13:39:43 +0000
133@@ -19,141 +19,365 @@
134 import SystemSettings 1.0
135 import Ubuntu.Components 0.1
136 import Ubuntu.Components.ListItems 0.1 as ListItem
137+import Ubuntu.Components.Popups 0.1
138 import Ubuntu.SystemSettings.Wifi 1.0
139 import QMenuModel 0.1
140
141-ItemPage {
142- id: othernetwork
143- title: i18n.tr("Connect to hidden network")
144-
145- function settingsValid() {
146- if(networkname.length == 0) {
147- return false;
148- }
149- if(securityList.selectedIndex == 0) {
150- return true
151- }
152- if(securityList.selectedIndex == 1) {
153- return password.length >= 8
154- }
155- // WEP
156- return password.length === 5 ||
157- password.length === 10 ||
158- password.length === 13 ||
159- password.length === 26;
160- }
161-
162- Component.onCompleted: {
163- flickable: otherNetworkFlickable
164- }
165-
166- Flickable {
167- id: otherNetworkFlickable
168- contentWidth: parent.width
169- contentHeight: otherview.height + units.gu(8)
170- anchors.fill: parent
171-
172- Column {
173- id : otherview
174+Component {
175+
176+ Dialog {
177+
178+ id: otherNetworkDialog
179+ objectName: "otherNetworkDialog"
180+ anchorToKeyboard: true
181+
182+ /* The following is a (bad) workaround for bugs
183+ #1337556
184+ #1337555
185+
186+ If the Dialog does not shrink after a user chooses e.g. WPA,
187+ the anchorToKeyboard setting of OrientationHelper have no effect,
188+ since the dialog never shrinks in size.
189+
190+ This workaround resizes the Dialog.
191+ */
192+
193+ property int dialogVisualsHeight
194+ function getVisibleChildren () {
195+ var children = [feedback, networknameLabel, networkname,
196+ securityListLabel, securityList, passwordListLabel,
197+ password, passwordVisiblityRow, buttonRow];
198+ var ret = [];
199+ children.forEach(function (child) {
200+ if (child.visible) {
201+ ret.push(child);
202+ }
203+ });
204+ return ret;
205+ }
206+
207+ function getVisibleChildrenHeight () {
208+ var h = 0;
209+ getVisibleChildren().forEach(function (child) {
210+ h = h + child.height;
211+ });
212+ return h;
213+ }
214+
215+ Component.onCompleted: {
216+ dialogVisualsHeight =
217+ __foreground.height - getVisibleChildrenHeight();
218+ }
219+
220+ Binding {
221+ target: __foreground
222+ property: "height"
223+ value: dialogVisualsHeight + getVisibleChildrenHeight()
224+ when: dialogVisualsHeight
225+ }
226+
227+ function settingsValid() {
228+ if(networkname.length == 0) {
229+ return false;
230+ }
231+ if(securityList.selectedIndex == 0) {
232+ return true
233+ }
234+ if(securityList.selectedIndex == 1) {
235+ return password.length >= 8
236+ }
237+ // WEP
238+ return password.length === 5 ||
239+ password.length === 10 ||
240+ password.length === 13 ||
241+ password.length === 26;
242+ }
243+
244+ title: i18n.tr("Connect to Hidden Network")
245+ text: feedback.enabled ? feedback.text : "";
246+
247+ Common {
248+ id: common
249+ }
250+
251+ states: [
252+ State {
253+ name: "CONNECTING"
254+ PropertyChanges {
255+ target: connectAction
256+ enabled: false
257+ }
258+ PropertyChanges {
259+ target: connectButtonIndicator
260+ running: true
261+ }
262+ PropertyChanges {
263+ target: passwordVisibleSwitch
264+ enabled: false
265+ }
266+ PropertyChanges {
267+ target: passwordVisibleLabel
268+ opacity: 0.5
269+ }
270+ PropertyChanges {
271+ target: password
272+ enabled: false
273+ }
274+ PropertyChanges {
275+ target: passwordListLabel
276+ opacity: 0.5
277+ }
278+ PropertyChanges {
279+ target: securityList
280+ enabled: false
281+ opacity: 0.5
282+ }
283+ PropertyChanges {
284+ target: securityListLabel
285+ opacity: 0.5
286+ }
287+ PropertyChanges {
288+ target: networkname
289+ enabled: false
290+ }
291+ PropertyChanges {
292+ target: networknameLabel
293+ opacity: 0.5
294+ }
295+ PropertyChanges {
296+ target: feedback
297+ enabled: true
298+ }
299+ },
300+ State {
301+ name: "FAILED"
302+ PropertyChanges {
303+ target: feedback
304+ enabled: true
305+ }
306+ },
307+ State {
308+ name: "SUCCEEDED"
309+ PropertyChanges {
310+ target: successIndicator
311+ running: true
312+ }
313+ PropertyChanges {
314+ target: cancelButton
315+ enabled: false
316+ }
317+ PropertyChanges {
318+ target: connectAction
319+ enabled: false
320+ }
321+ }
322+ ]
323+
324+ Label {
325+ property bool enabled: false
326+ id: feedback
327+ horizontalAlignment: Text.AlignHCenter
328+ height: contentHeight
329+ wrapMode: Text.Wrap
330+ visible: false
331+ }
332+
333+ Label {
334+ id: networknameLabel
335+ text : i18n.tr("Network name")
336+ objectName: "networknameLabel"
337+ fontSize: "medium"
338+ font.bold: true
339+ color: Theme.palette.selected.backgroundText
340+ elide: Text.ElideRight
341+ }
342+
343+ TextField {
344+ id : networkname
345+ objectName: "networkname"
346+ inputMethodHints: Qt.ImhNoPredictiveText
347+ }
348+
349+ Label {
350+ id: securityListLabel
351+ text : i18n.tr("Security")
352+ objectName: "securityListLabel"
353+ fontSize: "medium"
354+ font.bold: true
355+ color: Theme.palette.selected.backgroundText
356+ elide: Text.ElideRight
357+ }
358+
359+ ListItem.ItemSelector {
360+ id: securityList
361+ objectName: "securityList"
362+ model: [i18n.tr("None"), // index: 0
363+ i18n.tr("WPA & WPA2 Personal"), // index: 1
364+ i18n.tr("WEP"), // index: 2
365+ ]
366+ }
367+
368+ Label {
369+ id: passwordListLabel
370+ text : i18n.tr("Password")
371+ objectName: "passwordListLabel"
372+ fontSize: "medium"
373+ font.bold: true
374+ color: Theme.palette.selected.backgroundText
375+ elide: Text.ElideRight
376+ visible: securityList.selectedIndex !== 0
377+ }
378+
379+ TextField {
380+ id : password
381+ objectName: "password"
382+ visible: securityList.selectedIndex !== 0
383+ echoMode: passwordVisibleSwitch.checked ?
384+ TextInput.Normal : TextInput.Password
385+ inputMethodHints: passwordVisibleSwitch.checked ?
386+ Qt.ImhHiddenText : Qt.ImhNoPredictiveText;
387+ onAccepted: {
388+ connectAction.trigger();
389+ }
390+ }
391+
392+ Row {
393+ id: passwordVisiblityRow
394+ layoutDirection: Qt.LeftToRight
395+ spacing: units.gu(2)
396+ visible: securityList.selectedIndex !== 0
397+
398+ CheckBox {
399+ id: passwordVisibleSwitch
400+ }
401+
402+ Label {
403+ id: passwordVisibleLabel
404+ text : i18n.tr("Show password")
405+ objectName: "passwordVisibleLabel"
406+ fontSize: "medium"
407+ color: Theme.palette.selected.backgroundText
408+ elide: Text.ElideRight
409+ height: passwordVisibleSwitch.height
410+ verticalAlignment: Text.AlignVCenter
411+ MouseArea {
412+ anchors {
413+ fill: parent
414+ }
415+ onClicked: {
416+ passwordVisibleSwitch.checked =
417+ !passwordVisibleSwitch.checked
418+ }
419+ }
420+ }
421+ }
422+
423+ RowLayout {
424+ id: buttonRow
425 anchors {
426- top: parent.top
427 left: parent.left
428 right: parent.right
429 }
430-
431- ListItem.Standard {
432- text : i18n.tr("Network name")
433- showDivider: false
434- }
435-
436- TextField {
437- id : networkname
438- width: parent.width - units.gu(4)
439- anchors.horizontalCenter: parent.horizontalCenter
440- inputMethodHints: Qt.ImhNoPredictiveText
441- }
442-
443- ListItem.ItemSelector {
444- id: securityList
445- text: i18n.tr("Security")
446- model: [i18n.tr("None"), // index: 0
447- i18n.tr("WPA & WPA2 Personal"), // index: 1
448- i18n.tr("WEP"), // index: 2
449- ]
450- }
451-
452- ListItem.Standard {
453- id: passwordList
454- visible: securityList.selectedIndex !== 0
455- text: i18n.tr("Password")
456- control : TextInput {
457- }
458- showDivider: false
459- }
460-
461- TextField {
462- id : password
463- visible: securityList.selectedIndex !== 0
464- width: parent.width - units.gu(4)
465- anchors.horizontalCenter: parent.horizontalCenter
466- echoMode: passwordVisibleSwitch.checked ? TextInput.Normal : TextInput.Password
467- onActiveFocusChanged: {
468- parent.parent.contentY = 1000
469- }
470- }
471-
472- ListItem.Standard {
473- text: i18n.tr("Password visible")
474- visible: securityList.selectedIndex !== 0
475- id: passwordVisible
476- control: Switch {
477- id: passwordVisibleSwitch
478- }
479- }
480-
481- Rectangle {
482- id: buttons
483- color: Theme.palette.normal.background
484- anchors {
485- left: parent.left
486- right: parent.right
487- }
488- height: buttonRow.height + units.gu(4)
489-
490- RowLayout {
491- id: buttonRow
492- anchors {
493- margins: units.gu(2)
494- verticalCenter: parent.verticalCenter
495- left: parent.left
496- right: parent.right
497- }
498- spacing: units.gu(2)
499- height: cancelButton.height
500-
501- Button {
502- id: cancelButton
503- Layout.fillWidth: true
504- text: i18n.tr("Cancel")
505- onClicked: {
506- pageStack.pop()
507- }
508- }
509-
510- Button {
511- id: connectButton
512- Layout.fillWidth: true
513- text: i18n.tr("Connect")
514- enabled: settingsValid()
515- onClicked: {
516- DbusHelper.connect(networkname.text,
517- securityList.selectedIndex,
518- password.text)
519- pageStack.pop()
520- }
521+ spacing: units.gu(2)
522+ height: cancelButton.height
523+
524+ Button {
525+ id: cancelButton
526+ objectName: "cancel"
527+ Layout.fillWidth: true
528+ text: i18n.tr("Cancel")
529+ onClicked: {
530+ PopupUtils.close(otherNetworkDialog);
531+
532+ // If this dialog created the connection,
533+ // disconnect the device
534+ if (otherNetworkDialog.state === "CONNECTING") {
535+ DbusHelper.disconnectDevice();
536+ }
537+ }
538+ }
539+
540+ Button {
541+ id: connectButton
542+ objectName: "connect"
543+ Layout.fillWidth: true
544+ text: i18n.tr("Connect")
545+ enabled: connectAction.enabled
546+ action: connectAction
547+ Icon {
548+ height: parent.height - units.gu(1.5)
549+ width: parent.height - units.gu(1.5)
550+ anchors {
551+ centerIn: parent
552+ }
553+ name: "tick"
554+ color: "green"
555+ visible: successIndicator.running
556+ }
557+ ActivityIndicator {
558+ id: connectButtonIndicator
559+ running: false
560+ visible: running
561+ height: parent.height - units.gu(1.5)
562+ anchors {
563+ centerIn: parent
564+ }
565+ }
566+ }
567+ }
568+
569+ Action {
570+ id: connectAction
571+ enabled: settingsValid()
572+ onTriggered: {
573+ DbusHelper.connect(
574+ networkname.text,
575+ securityList.selectedIndex,
576+ password.text);
577+ otherNetworkDialog.state = "CONNECTING";
578+ }
579+ }
580+
581+ /* Timer that shows a tick in the connect button once we have
582+ successfully connected. */
583+ Timer {
584+ id: successIndicator
585+ interval: 2000
586+ running: false
587+ repeat: false
588+ onTriggered: PopupUtils.close(otherNetworkDialog)
589+ }
590+
591+ Connections {
592+ target: DbusHelper
593+ onDeviceStateChanged: {
594+ if (otherNetworkDialog.state === "FAILED") {
595+ /* Disconnect the device if it tries to reconnect after a
596+ connection failure */
597+ if (newState === 40) { // 40 = NM_DEVICE_STATE_PREPARE
598+ DbusHelper.disconnectDevice();
599+ }
600+ }
601+
602+ /* We will only consider these cases if we are in
603+ the CONNECTING state. This means that this Dialog will not
604+ react to what other NetworkManager consumers do.
605+ */
606+ if (otherNetworkDialog.state === "CONNECTING") {
607+ switch (newState) {
608+ case 120:
609+ feedback.text = common.reasonToString(reason);
610+ otherNetworkDialog.state = "FAILED";
611+ break;
612+ case 100:
613+ /* connection succeeded only if it was us that
614+ created it */
615+ otherNetworkDialog.state = "SUCCEEDED";
616+ break;
617 }
618 }
619 }
620 }
621 }
622 }
623+
624
625=== modified file 'plugins/wifi/PageComponent.qml'
626--- plugins/wifi/PageComponent.qml 2014-09-13 02:44:36 +0000
627+++ plugins/wifi/PageComponent.qml 2014-09-25 13:39:43 +0000
628@@ -18,11 +18,13 @@
629 import SystemSettings 1.0
630 import Ubuntu.Components 0.1
631 import Ubuntu.Components.ListItems 0.1 as ListItem
632+import Ubuntu.Components.Popups 0.1
633 import Ubuntu.SystemSettings.Wifi 1.0
634 import QMenuModel 0.1
635
636 ItemPage {
637 id: wifibase
638+ objectName: "wifiPage"
639 title: i18n.tr("Wi-Fi")
640
641 UnityMenuModel {
642@@ -105,7 +107,7 @@
643
644 if (item.hasOwnProperty("menuActivated")) {
645 item.menuActivated = Qt.binding(function() {
646- return ListView.isCurrentItem;
647+ return ListView.isCurrentItem;
648 });
649 item.selectMenu.connect(function() {
650 ListView.view.currentIndex = index;
651@@ -132,10 +134,18 @@
652 }
653
654 ListItem.SingleValue {
655- text: i18n.tr("Connect to hidden network")
656+ objectName: "connectToHiddenNetwork"
657+ text: i18n.tr("Connect to hidden network…")
658 progression: true
659- onClicked: pageStack.push(Qt.resolvedUrl("OtherNetwork.qml"))
660- visible : (actionGroup.actionObject.valid ? actionGroup.actionObject.state : false)
661+ onClicked: {
662+ otherNetworLoader.source = "OtherNetwork.qml";
663+ PopupUtils.open(otherNetworLoader.item);
664+ }
665+ }
666+
667+ Loader {
668+ id: otherNetworLoader
669+ asynchronous: false
670 }
671 }
672
673@@ -144,4 +154,5 @@
674 Flickable.DragAndOvershootBounds :
675 Flickable.StopAtBounds
676 }
677+
678 }
679
680=== modified file 'plugins/wifi/nm_manager_proxy.h'
681--- plugins/wifi/nm_manager_proxy.h 2014-06-18 14:16:53 +0000
682+++ plugins/wifi/nm_manager_proxy.h 2014-09-25 13:39:43 +0000
683@@ -108,7 +108,7 @@
684 {
685 QList<QVariant> argumentList;
686 argumentList << QVariant::fromValue(connection) << QVariant::fromValue(device) << QVariant::fromValue(specific_object);
687- return asyncCallWithArgumentList(QLatin1String("AddAndActivateConnection"), argumentList);
688+ return callWithArgumentList(QDBus::Block, QLatin1String("AddAndActivateConnection"), argumentList);
689 }
690 inline QDBusReply<QDBusObjectPath> AddAndActivateConnection(const QMap<QString, QVariantMap> &connection, const QDBusObjectPath &device, const QDBusObjectPath &specific_object, QDBusObjectPath &active_connection)
691 {
692
693=== modified file 'plugins/wifi/wifidbushelper.cpp'
694--- plugins/wifi/wifidbushelper.cpp 2014-09-04 00:58:34 +0000
695+++ plugins/wifi/wifidbushelper.cpp 2014-09-25 13:39:43 +0000
696@@ -31,6 +31,7 @@
697
698 #define NM_SERVICE "org.freedesktop.NetworkManager"
699 #define NM_PATH "/org/freedesktop/NetworkManager"
700+#define NM_DEVICE_IFACE "org.freedesktop.NetworkManager.Device"
701
702 typedef QMap<QString,QVariantMap> ConfigurationData;
703 Q_DECLARE_METATYPE(ConfigurationData)
704@@ -96,9 +97,9 @@
705
706 QDBusObjectPath dev;
707 for (const auto &d : devices) {
708- QDBusInterface iface("org.freedesktop.NetworkManager",
709+ QDBusInterface iface(NM_SERVICE,
710 d.path(),
711- "org.freedesktop.NetworkManager.Device",
712+ NM_DEVICE_IFACE,
713 QDBusConnection::systemBus());
714
715 auto type_v = iface.property("DeviceType");
716@@ -110,14 +111,42 @@
717
718 if (dev.path().isEmpty()) {
719 // didn't find a wifi device
720+ qWarning() << "Could not find wifi device.";
721 return;
722 }
723
724+ mgr.connection().disconnect(
725+ mgr.service(),
726+ dev.path(),
727+ NM_DEVICE_IFACE,
728+ "StateChanged",
729+ this,
730+ SLOT(nmDeviceStateChanged(uint, uint, uint)));
731+
732+ mgr.connection().connect(
733+ mgr.service(),
734+ dev.path(),
735+ NM_DEVICE_IFACE,
736+ "StateChanged",
737+ this,
738+ SLOT(nmDeviceStateChanged(uint, uint, uint)));
739+
740 QDBusObjectPath tmp;
741 auto reply2 = mgr.AddAndActivateConnection(configuration,
742 dev,
743 QDBusObjectPath("/"),
744 tmp);
745+ if(!reply2.isValid()) {
746+ qWarning() << "Could not connect: " << reply2.error().message() << "\n";
747+ }
748+}
749+
750+void WifiDbusHelper::nmDeviceStateChanged(uint newState,
751+ uint oldState,
752+ uint reason)
753+{
754+ Q_UNUSED (oldState);
755+ Q_EMIT (deviceStateChanged(newState, reason));
756 }
757
758 QString WifiDbusHelper::getWifiIpAddress()
759@@ -138,11 +167,7 @@
760
761 QDBusObjectPath dev;
762 for (const auto &d : devices) {
763- QDBusInterface iface("org.freedesktop.NetworkManager",
764- d.path(),
765- "org.freedesktop.NetworkManager.Device",
766- m_systemBusConnection);
767-
768+ QDBusInterface iface(NM_SERVICE, d.path(), NM_DEVICE_IFACE, m_systemBusConnection);
769 auto type_v = iface.property("DeviceType");
770 if (type_v.toUInt() == 2 /* NM_DEVICE_TYPE_WIFI */) {
771 ip4addr = iface.property("Ip4Address").toInt();
772@@ -323,7 +348,7 @@
773 QList<QStringList> networks;
774
775 OrgFreedesktopNetworkManagerSettingsInterface foo
776- ("org.freedesktop.NetworkManager",
777+ (NM_SERVICE,
778 "/org/freedesktop/NetworkManager/Settings",
779 QDBusConnection::systemBus());
780 auto reply = foo.ListConnections();
781@@ -359,7 +384,7 @@
782
783 void WifiDbusHelper::forgetConnection(const QString dbus_path) {
784 OrgFreedesktopNetworkManagerSettingsConnectionInterface bar
785- ("org.freedesktop.NetworkManager",
786+ (NM_SERVICE,
787 dbus_path,
788 QDBusConnection::systemBus());
789 auto reply = bar.Delete();
790@@ -369,7 +394,7 @@
791 }
792 }
793
794-bool WifiDbusHelper::deactivateConnection() {
795+bool WifiDbusHelper::disconnectDevice() {
796 OrgFreedesktopNetworkManagerInterface mgr(NM_SERVICE,
797 NM_PATH,
798 m_systemBusConnection);
799@@ -377,42 +402,27 @@
800 auto reply1 = mgr.GetDevices();
801 reply1.waitForFinished();
802 if(!reply1.isValid()) {
803- qWarning() << "deactivateConnection: Could not get network device: " << reply1.error().message() << "\n";
804+ qWarning() << "disconnectDevice: Could not get network device: " << reply1.error().message() << "\n";
805 return false;
806 }
807 auto devices = reply1.value();
808
809- QDBusObjectPath activeConnection;
810 QDBusObjectPath dev;
811 for (const auto &d : devices) {
812- QDBusInterface iface(NM_SERVICE,
813- d.path(),
814- "org.freedesktop.NetworkManager.Device",
815- m_systemBusConnection);
816+ QDBusInterface iface(NM_SERVICE, d.path(), NM_DEVICE_IFACE, m_systemBusConnection);
817
818 auto type_v = iface.property("DeviceType");
819 if (type_v.toUInt() == 2 /* NM_DEVICE_TYPE_WIFI */) {
820- activeConnection = qvariant_cast<QDBusObjectPath>(iface.property("ActiveConnection"));
821- dev = d;
822+ if (d.path().isEmpty()) {
823+ // didn't find a wifi device
824+ qWarning() << "disconnectDevice: Could not find wifi device\n";
825+ return false;
826+ } else {
827+ iface.call("Disconnect");
828+ return true;
829+ }
830 break;
831 }
832 }
833-
834- if (dev.path().isEmpty()) {
835- // didn't find a wifi device
836- return false;
837- }
838-
839- if (activeConnection.path().isEmpty()) {
840- // no active connection
841- return false;
842- }
843-
844- auto reply = mgr.DeactivateConnection(activeConnection);
845- reply.waitForFinished();
846- if(!reply.isValid()) {
847- qWarning() << "Error deactivating connection: " << reply.error().message() << "\n";
848- return false;
849- }
850- return true;
851+ return false;
852 }
853
854=== modified file 'plugins/wifi/wifidbushelper.h'
855--- plugins/wifi/wifidbushelper.h 2014-09-04 00:58:34 +0000
856+++ plugins/wifi/wifidbushelper.h 2014-09-25 13:39:43 +0000
857@@ -40,10 +40,14 @@
858 Q_INVOKABLE void connect(QString ssid, int security, QString password);
859 Q_INVOKABLE QList<QStringList> getPreviouslyConnectedWifiNetworks();
860 Q_INVOKABLE void forgetConnection(const QString dbus_path);
861- Q_INVOKABLE bool deactivateConnection();
862+ Q_INVOKABLE bool disconnectDevice();
863+
864+public Q_SLOTS:
865+ void nmDeviceStateChanged(uint, uint, uint);
866
867 Q_SIGNALS:
868 void wifiIp4AddressChanged(QString wifiIp4Address);
869+ void deviceStateChanged(uint newState, uint reason);
870
871 private:
872 QDBusConnection m_systemBusConnection;
873
874=== modified file 'tests/autopilot/ubuntu_system_settings/__init__.py'
875--- tests/autopilot/ubuntu_system_settings/__init__.py 2014-09-11 18:34:30 +0000
876+++ tests/autopilot/ubuntu_system_settings/__init__.py 2014-09-25 13:39:43 +0000
877@@ -27,7 +27,7 @@
878 import autopilot.logging
879 import ubuntuuitoolkit
880 from autopilot import introspection, platform
881-
882+from ubuntu_system_settings.utils.i18n import ugettext as _
883
884 logger = logging.getLogger(__name__)
885
886@@ -110,6 +110,10 @@
887 def go_to_language_page(self):
888 return self._go_to_page('entryComponent-language', 'languagePage')
889
890+ @autopilot.logging.log_action(logger.debug)
891+ def go_to_wifi_page(self):
892+ return self._go_to_page('entryComponent-wifi', 'wifiPage')
893+
894 def _go_to_page(self, item_object_name, page_object_name):
895 self.click_item(item_object_name)
896 page = self.wait_select_single(objectName=page_object_name)
897@@ -181,6 +185,11 @@
898 return self.select_single(objectName='aboutPage')
899
900 @property
901+ def wifi_page(self):
902+ """ Return 'Wifi' page """
903+ return self.select_single(objectName='wifiPage')
904+
905+ @property
906 def _orientation_lock_switch(self):
907 return self.wait_select_single(
908 ubuntuuitoolkit.CheckBox,
909@@ -655,3 +664,156 @@
910 def _click_revert(self):
911 button = self.select_single('Button', objectName='revert')
912 self.pointing_device.click_object(button)
913+
914+
915+class WifiPage(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
916+
917+ """Autopilot helper for the Sound page."""
918+
919+ @classmethod
920+ def validate_dbus_object(cls, path, state):
921+ name = introspection.get_classname_from_path(path)
922+ if name == b'ItemPage':
923+ if state['objectName'][1] == 'wifiPage':
924+ return True
925+ return False
926+
927+ """Connects to hidden network
928+
929+ :param name: Network name string (SSID)
930+ :kwarg security: A string that is either "none", "wpa" or "wep
931+ :kwarg password: A string/hex secret
932+ :kwarg cancel: A boolean deciding whether we press cancel or not
933+
934+ :returns: If we are connecting, it returns the dialog,
935+ if we cancel, it returns itself
936+
937+ """
938+ @autopilot.logging.log_action(logger.debug)
939+ def connect_to_hidden_network(self, name, security="none", password=None,
940+ cancel=False, scroll_to_and_click=None):
941+ dialog = self._click_connect_to_hidden_network(scroll_to_and_click)
942+ dialog.enter_name(name)
943+ if security:
944+ dialog.set_security(security)
945+ if password:
946+ dialog.enter_password(password)
947+
948+ if cancel:
949+ dialog.cancel()
950+ return self
951+ else:
952+ dialog.connect()
953+ return dialog
954+
955+ @autopilot.logging.log_action(logger.debug)
956+ def _click_connect_to_hidden_network(self, scroll_to_and_click):
957+
958+ # we can't mock the qunitymenu items, so we
959+ # have to wait for them to be built
960+ sleep(1)
961+
962+ button = self.select_single('*',
963+ objectName='connectToHiddenNetwork')
964+ if (scroll_to_and_click):
965+ scroll_to_and_click(button)
966+ else:
967+ self.pointing_device.click_object(button)
968+ return self.get_root_instance().wait_select_single(
969+ objectName='otherNetworkDialog')
970+
971+
972+class OtherNetwork(
973+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
974+
975+ """Autopilot helper for the Connect to Hidden Network dialog."""
976+
977+ @classmethod
978+ def validate_dbus_object(cls, path, state):
979+ name = introspection.get_classname_from_path(path)
980+ if name == b'Dialog':
981+ if state['objectName'][1] == 'otherNetworkDialog':
982+ return True
983+ return False
984+
985+ @autopilot.logging.log_action(logger.debug)
986+ def enter_name(self, name):
987+ self._enter_name(name)
988+
989+ @autopilot.logging.log_action(logger.debug)
990+ def _enter_name(self, name):
991+ namefield = self.select_single('TextField',
992+ objectName='networkname')
993+ namefield.write(name)
994+
995+ @autopilot.logging.log_action(logger.debug)
996+ def set_security(self, security):
997+ """Sets the hidden network's security
998+
999+ :param security: Either "none", "wpa" or "wep
1000+
1001+ :returns: None
1002+
1003+ """
1004+ self._set_security(security)
1005+
1006+ @autopilot.logging.log_action(logger.debug)
1007+ def _expand_security_list(self):
1008+ sec_list = self.select_single(
1009+ '*', objectName='securityList')
1010+ active_child = sec_list.select_single(
1011+ '*', objectName='listContainer')
1012+ self.pointing_device.click_object(active_child)
1013+ # wait for it to expand
1014+ sleep(0.5)
1015+ return sec_list
1016+
1017+ @autopilot.logging.log_action(logger.debug)
1018+ def _set_security(self, security):
1019+ if security == 'none':
1020+ sec_list = self._expand_security_list()
1021+ item = sec_list.wait_select_single('*',
1022+ text=_('None'))
1023+ self.pointing_device.click_object(item)
1024+ elif security == 'wpa':
1025+ sec_list = self._expand_security_list()
1026+ item = sec_list.wait_select_single('*',
1027+ text=_('WPA & WPA2 Personal'))
1028+ self.pointing_device.click_object(item)
1029+ elif security == 'wep':
1030+ sec_list = self._expand_security_list()
1031+ item = sec_list.wait_select_single('*',
1032+ text=_('WEP'))
1033+ self.pointing_device.click_object(item)
1034+ elif security is not None:
1035+ raise ValueError('security type %s is not valid' % security)
1036+ # wait for ui to change
1037+ sleep(0.5)
1038+
1039+ @autopilot.logging.log_action(logger.debug)
1040+ def enter_password(self, password):
1041+ self._enter_password(password)
1042+
1043+ @autopilot.logging.log_action(logger.debug)
1044+ def _enter_password(self, password):
1045+ pwdfield = self.select_single('TextField',
1046+ objectName='password')
1047+ pwdfield.write(password)
1048+
1049+ @autopilot.logging.log_action(logger.debug)
1050+ def cancel(self):
1051+ self._click_cancel()
1052+
1053+ @autopilot.logging.log_action(logger.debug)
1054+ def _click_cancel(self):
1055+ button = self.select_single('Button', objectName='cancel')
1056+ self.pointing_device.click_object(button)
1057+
1058+ @autopilot.logging.log_action(logger.debug)
1059+ def connect(self):
1060+ self._click_connect()
1061+
1062+ @autopilot.logging.log_action(logger.debug)
1063+ def _click_connect(self):
1064+ button = self.select_single('Button', objectName='connect')
1065+ self.pointing_device.click_object(button)
1066
1067=== modified file 'tests/autopilot/ubuntu_system_settings/tests/__init__.py'
1068--- tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-09-11 18:34:30 +0000
1069+++ tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-09-25 13:39:43 +0000
1070@@ -13,15 +13,14 @@
1071 import dbusmock
1072 import os
1073 import subprocess
1074-from time import sleep
1075-
1076 import ubuntuuitoolkit
1077+
1078 from autopilot.matchers import Eventually
1079+from dbusmock.templates.networkmanager import DEVICE_IFACE
1080+from datetime import datetime
1081 from fixtures import EnvironmentVariable
1082 from testtools.matchers import Equals, NotEquals, GreaterThan
1083-
1084-from datetime import datetime
1085-
1086+from time import sleep
1087 from ubuntu_system_settings import SystemSettings
1088
1089 ACCOUNTS_IFACE = 'org.freedesktop.Accounts'
1090@@ -41,6 +40,9 @@
1091 LM_SERVICE = 'org.freedesktop.login1'
1092 LM_PATH = '/org/freedesktop/login1'
1093 LM_IFACE = 'org.freedesktop.login1.Manager'
1094+NM_SERVICE = 'org.freedesktop.NetworkManager'
1095+NM_PATH = '/org/freedesktop/NetworkManager'
1096+NM_IFACE = 'org.freedesktop.NetworkManager'
1097
1098
1099 class UbuntuSystemSettingsTestCase(
1100@@ -737,3 +739,38 @@
1101 self.mock_server.terminate()
1102 self.mock_server.wait()
1103 super(LanguageBaseTestCase, self).tearDown()
1104+
1105+
1106+class WifiBaseTestCase(UbuntuSystemSettingsTestCase,
1107+ dbusmock.DBusTestCase):
1108+ """ Base class for wifi settings tests"""
1109+
1110+ @classmethod
1111+ def setUpClass(cls):
1112+ cls.start_system_bus()
1113+ cls.dbus_con = cls.get_dbus(True)
1114+ # Add a mock NetworkManager environment so we get consistent results
1115+ (cls.p_mock, cls.obj_nm) = cls.spawn_server_template(
1116+ 'networkmanager', stdout=subprocess.PIPE)
1117+ cls.dbusmock = dbus.Interface(cls.obj_nm, dbusmock.MOCK_IFACE)
1118+
1119+ def setUp(self, panel=None):
1120+ self.obj_nm.Reset()
1121+ device_path = self.obj_nm.AddWiFiDevice('test0', 'Barbaz', 1)
1122+ self.device_mock = dbus.Interface(self.dbus_con.get_object(
1123+ 'org.freedesktop.NetworkManager', device_path),
1124+ dbusmock.MOCK_IFACE)
1125+
1126+ """A device should not just implement Device.Wireless/Device.Wired
1127+ interfaces, but also the Device interface. Since we want to test
1128+ the Disconnect method, we add it."""
1129+
1130+ try:
1131+ self.device_mock.AddMethod(DEVICE_IFACE, 'Disconnect', '', '', '')
1132+ except:
1133+ # it was already added
1134+ pass
1135+
1136+ super(WifiBaseTestCase, self).setUp()
1137+ self.wifi_page = self.system_settings.\
1138+ main_view.go_to_wifi_page()
1139
1140=== added file 'tests/autopilot/ubuntu_system_settings/tests/test_wifi.py'
1141--- tests/autopilot/ubuntu_system_settings/tests/test_wifi.py 1970-01-01 00:00:00 +0000
1142+++ tests/autopilot/ubuntu_system_settings/tests/test_wifi.py 2014-09-25 13:39:43 +0000
1143@@ -0,0 +1,135 @@
1144+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1145+# Copyright 2014 Canonical
1146+#
1147+# This program is free software: you can redistribute it and/or modify it
1148+# under the terms of the GNU General Public License version 3, as published
1149+# by the Free Software Foundation.
1150+
1151+from __future__ import absolute_import
1152+from autopilot.matchers import Eventually
1153+from dbusmock.templates.networkmanager import DEVICE_IFACE
1154+from testtools.matchers import Equals
1155+from time import sleep
1156+from ubuntu_system_settings.tests import WifiBaseTestCase
1157+from ubuntu_system_settings.utils.i18n import ugettext as _
1158+from unittest import skip
1159+
1160+
1161+class WifiTestCase(WifiBaseTestCase):
1162+ """Tests for Language Page"""
1163+
1164+ def test_wifi_page_title_is_correct(self):
1165+ """Checks whether Wifi page is available"""
1166+ self.assertThat(
1167+ self.wifi_page.title,
1168+ Equals(_('Wi-Fi')))
1169+
1170+ def test_connect_to_hidden_network(self):
1171+ dialog = self.wifi_page.connect_to_hidden_network(
1172+ 'yeah',
1173+ scroll_to_and_click=self.system_settings.main_view
1174+ .scroll_to_and_click)
1175+
1176+ # allow backend to set up listeners
1177+ sleep(0.3)
1178+
1179+ """Mock a StateChanged signal on the Device, using a likely
1180+ scenario of a not found SSID:
1181+ newState = 120 # NM_DEVICE_STATE_FAILED
1182+ oldState = 0 # does not matter
1183+ reason = 53 # NM_DEVICE_STATE_REASON_SSID_NOT_FOUND
1184+ """
1185+
1186+ self.device_mock.EmitSignal(
1187+ DEVICE_IFACE, 'StateChanged', 'uuu', [100, 0, 0])
1188+
1189+ if dialog:
1190+ dialog.wait_until_destroyed()
1191+
1192+ def test_connect_to_nonexistant_hidden_network(self):
1193+
1194+ dialog = self.wifi_page.connect_to_hidden_network(
1195+ 'yeah',
1196+ scroll_to_and_click=self.system_settings.main_view
1197+ .scroll_to_and_click)
1198+
1199+ # allow backend to set up listeners
1200+ sleep(0.3)
1201+
1202+ """Mock a StateChanged signal on the Device, using a likely
1203+ scenario of a not found SSID:
1204+ newState = 120 # NM_DEVICE_STATE_FAILED
1205+ oldState = 0 # does not matter
1206+ reason = 53 # NM_DEVICE_STATE_REASON_SSID_NOT_FOUND
1207+ """
1208+
1209+ self.device_mock.EmitSignal(
1210+ DEVICE_IFACE, 'StateChanged', 'uuu', [120, 0, 53])
1211+
1212+ self.assertThat(
1213+ dialog.text, Eventually(Equals(
1214+ _('The Wi-Fi network could not be found'))))
1215+
1216+ @skip('skipped due to bug 1337556')
1217+ def test_connect_to_hidden_network_using_secrets(self):
1218+ dialog = self.wifi_page.connect_to_hidden_network(
1219+ 'yeah', security='wpa', password='abcdefgh',
1220+ scroll_to_and_click=self.system_settings.main_view
1221+ .scroll_to_and_click)
1222+
1223+ # allow backend to set up listeners
1224+ sleep(0.3)
1225+
1226+ """Mock a StateChanged signal on the Device, which
1227+ lets the backend know it was the wrong secret:
1228+ newState = 100 # NM_DEVICE_STATE_ACTIVATED
1229+ oldState = 0 # does not matter
1230+ reason = 0 # does not matter
1231+ """
1232+
1233+ self.device_mock.EmitSignal(
1234+ DEVICE_IFACE, 'StateChanged', 'uuu', [100, 0, 0])
1235+
1236+ if dialog:
1237+ dialog.wait_until_destroyed()
1238+
1239+ @skip('skipped due to bug 1337556')
1240+ def test_connect_to_hidden_network_using_incorrect_secrets(self):
1241+ dialog = self.wifi_page.connect_to_hidden_network(
1242+ 'yeah', security='wpa', password='abcdefgh',
1243+ scroll_to_and_click=self.system_settings.main_view
1244+ .scroll_to_and_click)
1245+ # allow backend to set up listeners
1246+ sleep(0.3)
1247+
1248+ """Mock a StateChanged signal on the Device, which
1249+ lets the backend know it was the wrong secret:
1250+ newState = 120 # NM_DEVICE_STATE_FAILED
1251+ oldState = 0 # does not matter
1252+ reason = 7 # NM_DEVICE_STATE_REASON_NO_SECRETS
1253+ """
1254+
1255+ self.device_mock.EmitSignal(
1256+ DEVICE_IFACE, 'StateChanged', 'uuu', [120, 0, 7])
1257+
1258+ self.assertThat(
1259+ dialog.text, Eventually(Equals(
1260+ _('Your authentication details were incorrect'))))
1261+
1262+ def test_connect_to_hidden_network_then_cancel(self):
1263+
1264+ dialog = self.wifi_page.connect_to_hidden_network(
1265+ 'foo',
1266+ scroll_to_and_click=self.system_settings.main_view
1267+ .scroll_to_and_click)
1268+
1269+ # allow backend to set up listeners
1270+ sleep(0.3)
1271+
1272+ dialog.cancel()
1273+
1274+ # check that Disconnect was called once
1275+ self.assertThat(
1276+ lambda:
1277+ len(self.device_mock.GetMethodCalls('Disconnect')),
1278+ Eventually(Equals(1)))

Subscribers

People subscribed via source and target branches