on xenial help sign in
Add a test for the session chooser icon in the greeter's sessions list
446b941Josh Arenson
qml/Greeter/LoginList.qml−2
@@ -36,12 +36,10 @@ StyledItem {
36 readonly property int cellHeight: units.gu(5)
36 readonly property int cellHeight: units.gu(5)
37 readonly property int highlightedHeight: units.gu(15)
37 readonly property int highlightedHeight: units.gu(15)
38 readonly property int moveDuration: UbuntuAnimation.FastDuration
38 readonly property int moveDuration: UbuntuAnimation.FastDuration
39− property string selectedSession
40 property string currentSession
39 property string currentSession
41 readonly property string currentUser: userList.currentItem.username
40 readonly property string currentUser: userList.currentItem.username
42 property bool wasPrompted: false
41 property bool wasPrompted: false
43
42
44− signal loginListSessionChanged(string session)
45 signal responded(string response)
43 signal responded(string response)
46 signal selected(int index)
44 signal selected(int index)
47 signal sessionChooserButtonClicked()
45 signal sessionChooserButtonClicked()
qml/Greeter/WideView.qml+1−4
@@ -125,8 +125,6 @@ FocusScope {
125 id: loginList
125 id: loginList
126 objectName: "loginList"
126 objectName: "loginList"
127
127
128− property int selectedUserIndex: 0
129−
130 width: units.gu(40)
128 width: units.gu(40)
131 anchors {
129 anchors {
132 left: parent.left
130 left: parent.left
@@ -141,11 +139,10 @@ FocusScope {
141 Behavior on boxVerticalOffset { UbuntuNumberAnimation {} }
139 Behavior on boxVerticalOffset { UbuntuNumberAnimation {} }
142
140
143 model: root.userModel
141 model: root.userModel
144− currentSession: LightDMService.users.data(selectedUserIndex, LightDMService.userRoles.SessionRole);
145 onResponded: root.responded(response)
142 onResponded: root.responded(response)
146 onSelected: {
143 onSelected: {
147 root.selected(index)
144 root.selected(index)
148− loginList.selectedUserIndex = index;
145+ currentSession = LightDMService.users.data(index, LightDMService.userRoles.SessionRole);
149 }
146 }
150 onSessionChooserButtonClicked: parent.state = "SessionsList"
147 onSessionChooserButtonClicked: parent.state = "SessionsList"
151
148
tests/mocks/liblightdm/MockController.cpp+24
@@ -85,6 +85,30 @@ void MockController::setUserMode(const QString &userMode)
85 }
85 }
86}
86}
87
87
88+QString MockController::sessionName() const
89+{
90+ return QString("INVALID - Please read directly from the UserModel");
91+}
92+
93+void MockController::setSessionName(const QString &sessionName)
94+{
95+ // Let the user model deal with this
96+ Q_EMIT sessionNameChanged(sessionName, m_currentUsername);
97+}
98+
99+QString MockController::currentUsername() const
100+{
101+ return m_currentUsername;
102+}
103+
104+void MockController::setCurrentUsername(const QString &username)
105+{
106+ if (m_currentUsername != username) {
107+ m_currentUsername = username;
108+ Q_EMIT currentUsernameChanged();
109+ }
110+}
111+
88QString MockController::sessionMode() const
112QString MockController::sessionMode() const
89{
113{
90 return m_sessionMode;
114 return m_sessionMode;
tests/mocks/liblightdm/MockController.h+15
@@ -34,6 +34,11 @@ class Q_DECL_EXPORT MockController : public QObject
34 // single, none, full
34 // single, none, full
35 Q_PROPERTY(QString sessionMode READ sessionMode WRITE setSessionMode NOTIFY sessionModeChanged)
35 Q_PROPERTY(QString sessionMode READ sessionMode WRITE setSessionMode NOTIFY sessionModeChanged)
36
36
37+ // This would be best as a Q_INVOKABLE, but using a property allows for
38+ // keeping the mock cleaner
39+ Q_PROPERTY(QString sessionName READ sessionName WRITE setSessionName NOTIFY sessionNameChanged)
40+ Q_PROPERTY(QString currentUsername READ currentUsername WRITE setCurrentUsername NOTIFY currentUsernameChanged)
41+
37 Q_PROPERTY(int numAvailableSessions READ numFullSessions CONSTANT)
42 Q_PROPERTY(int numAvailableSessions READ numFullSessions CONSTANT)
38 Q_PROPERTY(int numSessions READ numSessions WRITE setNumSessions NOTIFY numSessionsChanged)
43 Q_PROPERTY(int numSessions READ numSessions WRITE setNumSessions NOTIFY numSessionsChanged)
39
44
@@ -50,6 +55,12 @@ public:
50 QString sessionMode() const;
55 QString sessionMode() const;
51 void setSessionMode(const QString &sessionMode);
56 void setSessionMode(const QString &sessionMode);
52
57
58+ QString sessionName() const;
59+ void setSessionName(const QString &userIndex);
60+
61+ QString currentUsername() const;
62+ void setCurrentUsername(const QString &username);
63+
53 class SessionItem
64 class SessionItem
54 {
65 {
55 public:
66 public:
@@ -63,14 +74,18 @@ public:
63 void setNumSessions(int numSessions);
74 void setNumSessions(int numSessions);
64
75
65Q_SIGNALS:
76Q_SIGNALS:
77+ void currentUsernameChanged();
66 void selectUserHintChanged();
78 void selectUserHintChanged();
67 void userModeChanged();
79 void userModeChanged();
68 void sessionModeChanged();
80 void sessionModeChanged();
69 void numSessionsChanged();
81 void numSessionsChanged();
82+ void sessionNameChanged(const QString &sessionName, const QString &username);
70
83
71private:
84private:
72 explicit MockController(QObject* parent=0);
85 explicit MockController(QObject* parent=0);
73
86
87+ QString m_currentUsername;
88+ QString m_sessionName;
74 QString m_selectUserHint;
89 QString m_selectUserHint;
75 QString m_userMode;
90 QString m_userMode;
76 QString m_sessionMode;
91 QString m_sessionMode;
tests/mocks/liblightdm/MockUsersModel.cpp+37−14
@@ -67,6 +67,8 @@ UsersModel::UsersModel(QObject *parent)
67
67
68 connect(MockController::instance(), &MockController::userModeChanged,
68 connect(MockController::instance(), &MockController::userModeChanged,
69 this, &UsersModel::resetEntries);
69 this, &UsersModel::resetEntries);
70+ connect(MockController::instance(), &MockController::sessionNameChanged,
71+ this, &UsersModel::setCurrentSessionName);
70 resetEntries();
72 resetEntries();
71}
73}
72
74
@@ -75,6 +77,22 @@ UsersModel::~UsersModel()
75 delete d_ptr;
77 delete d_ptr;
76}
78}
77
79
80+void UsersModel::setCurrentSessionName(const QString &sessionName, const QString &username)
81+{
82+ Q_D(UsersModel);
83+
84+ int usersIndex = 0;
85+ for (auto &entry : d->entries) {
86+ if (username == entry.username) {
87+ entry.session = sessionName;
88+ break;
89+ }
90+ usersIndex++;
91+ }
92+
93+ dataChanged(index(usersIndex, 0), index(usersIndex, 0), QVector<int>(SessionRole));
94+}
95+
78int UsersModel::rowCount(const QModelIndex &parent) const
96int UsersModel::rowCount(const QModelIndex &parent) const
79{
97{
80 Q_D(const UsersModel);
98 Q_D(const UsersModel);
@@ -138,28 +156,33 @@ void UsersModel::resetEntries()
138 } else if (userMode == "single-pin") {
156 } else if (userMode == "single-pin") {
139 d->entries = {{"has-pin", "Has PIN", "", 0, false, false, "ubuntu", 0}};
157 d->entries = {{"has-pin", "Has PIN", "", 0, false, false, "ubuntu", 0}};
140 } else if (userMode == "full") {
158 } else if (userMode == "full") {
159+ /*
160+ * Since the real model sorts these entries alphabetically, the model indices
161+ * don't line up correctly. The easiest way to fix this is to ensure that this
162+ * list of entries REMAINS IN ALPHABETICAL ORDER at all times.
163+ */
141 d->entries = {
164 d->entries = {
165+ { "active", "Active Account", 0, 0, true, false, "ubuntu", 0 },
166+ { "auth-error", "Auth Error", 0, 0, false, false, "ubuntu", 0 },
167+ { "black-background", "Black Background", "#000000", 0, false, false, "ubuntu", 0 },
168+ { "color-background", "Color Background", "#E95420", 0, false, false, "ubuntu", 0 },
169+ { "different-prompt", "Different Prompt", 0, 0, false, false, "ubuntu", 0 },
170+ { "empty-name", "", 0, 0, false, false, "ubuntu", 0 },
142 { "has-password", "Has Password", 0, 0, false, false, "ubuntu", 0 },
171 { "has-password", "Has Password", 0, 0, false, false, "ubuntu", 0 },
143 { "has-pin", "Has PIN", 0, 0, false, false, "ubuntu", 0 },
172 { "has-pin", "Has PIN", 0, 0, false, false, "ubuntu", 0 },
144− { "different-prompt", "Different Prompt", 0, 0, false, false, "ubuntu", 0 },
145− { "no-password", "No Password", 0, 0, false, false, "ubuntu", 0 },
146− { "auth-error", "Auth Error", 0, 0, false, false, "ubuntu", 0 },
147− { "two-factor", "Two Factor", 0, 0, false, false, "ubuntu", 0 },
148− { "info-prompt", "Info Prompt", 0, 0, false, false, "ubuntu", 0 },
149 { "html-info-prompt", "HTML Info Prompt", 0, 0, false, false, "ubuntu", 0 },
173 { "html-info-prompt", "HTML Info Prompt", 0, 0, false, false, "ubuntu", 0 },
174+ { "info-prompt", "Info Prompt", 0, 0, false, false, "ubuntu", 0 },
150 { "long-info-prompt", "Long Info Prompt", 0, 0, false, false, "ubuntu", 0 },
175 { "long-info-prompt", "Long Info Prompt", 0, 0, false, false, "ubuntu", 0 },
151− { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, "ubuntu", 0 },
152− { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, "ubuntu", 0 },
153 { "long-name", "Long name (far far too long to fit, seriously this would never fit on the screen, you will never see this part of the name)", 0, 0, false, false, "ubuntu", 0 },
176 { "long-name", "Long name (far far too long to fit, seriously this would never fit on the screen, you will never see this part of the name)", 0, 0, false, false, "ubuntu", 0 },
154− { "color-background", "Color Background", "#E95420", 0, false, false, "ubuntu", 0 },
177+ { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, "ubuntu", 0 },
155− // white and black are a bit redundant, but useful for manually testing if UI is still readable
156− { "white-background", "White Background", "#ffffff", 0, false, false, "ubuntu", 0 },
157− { "black-background", "Black Background", "#000000", 0, false, false, "ubuntu", 0 },
158 { "no-background", "No Background", "", 0, false, false, "ubuntu", 0 },
178 { "no-background", "No Background", "", 0, false, false, "ubuntu", 0 },
159− { "unicode", "가나다라마", 0, 0, false, false, "ubuntu", 0 },
179+ { "no-password", "No Password", 0, 0, false, false, "ubuntu", 0 },
160 { "no-response", "No Response", 0, 0, false, false, "ubuntu", 0 },
180 { "no-response", "No Response", 0, 0, false, false, "ubuntu", 0 },
161− { "empty-name", "", 0, 0, false, false, "ubuntu", 0 },
181+ { "two-factor", "Two Factor", 0, 0, false, false, "ubuntu", 0 },
162− { "active", "Active Account", 0, 0, true, false, "ubuntu", 0 },
182+ { "unicode", "가나다라마", 0, 0, false, false, "ubuntu", 0 },
183+ // white and black are a bit redundant, but useful for manually testing if UI is still readable
184+ { "white-background", "White Background", "#ffffff", 0, false, false, "ubuntu", 0 },
185+ { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, "ubuntu", 0 }
163 };
186 };
164 }
187 }
165
188
tests/mocks/liblightdm/MockUsersModel.h+2
@@ -48,6 +48,8 @@ public:
48 int rowCount(const QModelIndex &parent) const override;
48 int rowCount(const QModelIndex &parent) const override;
49 QVariant data(const QModelIndex &index, int role) const override;
49 QVariant data(const QModelIndex &index, int role) const override;
50
50
51+ void setCurrentSessionName(const QString &sessionName, const QString &username);
52+
51private Q_SLOTS:
53private Q_SLOTS:
52 void resetEntries();
54 void resetEntries();
53
55
tests/qmltests/Greeter/tst_WideView.qml+31
@@ -411,6 +411,37 @@ StyledItem {
411 waitForRendering(view);
411 waitForRendering(view);
412 }
412 }
413
413
414+ function test_changingSessionSticksToUser() {
415+ LightDMController.sessionMode = "full";
416+
417+ var loginList = findChild(view, "loginList");
418+ var fakeSession1 = "ASessionWillNeverBeCalledThis";
419+ var fakeSession2 = "ASessionWillAlsoNeverBeCalledThis";
420+
421+ // For this test to work, a user has to be selected and the
422+ // mock must be made aware of that user
423+ selectUser("has-password")
424+ LightDMController.currentUsername = "has-password"
425+ compare(LightDM.Sessions.count > 1, true);
426+ compare(loginList.currentSession != fakeSession1, true);
427+ LightDMController.sessionName = fakeSession1;
428+
429+ selectUser("has-pin")
430+ LightDMController.currentUsername = "has-pin"
431+ compare(loginList.currentSession != fakeSession2, true);
432+ LightDMController.sessionName = fakeSession2;
433+
434+ selectUser("has-password")
435+ tryCompare(loginList, "currentSession", fakeSession1);
436+
437+ selectUser("has-pin")
438+ tryCompare(loginList, "currentSession", fakeSession2);
439+
440+ // Force a model reset
441+ LightDMController.userMode = "single";
442+ LightDMController.userMode = "full";
443+ }
444+
414 function test_tease_data() {
445 function test_tease_data() {
415 return [
446 return [
416 {tag: "locked", x: 0, offset: 0, count: 0, locked: true},
447 {tag: "locked", x: 0, offset: 0, count: 0, locked: true},