users_groups.cy.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /**
  2. * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
  3. * SPDX-License-Identifier: AGPL-3.0-or-later
  4. */
  5. import { User } from '@nextcloud/cypress'
  6. import { assertNotExistOrNotVisible, getUserListRow, handlePasswordConfirmation, toggleEditButton } from './usersUtils'
  7. // eslint-disable-next-line n/no-extraneous-import
  8. import randomString from 'crypto-random-string'
  9. const admin = new User('admin', 'admin')
  10. describe('Settings: Create groups', () => {
  11. before(() => {
  12. cy.login(admin)
  13. cy.visit('/settings/users')
  14. })
  15. it('Can create a group', () => {
  16. const groupName = randomString(7)
  17. // open the Create group menu
  18. cy.get('button[aria-label="Create group"]').click()
  19. cy.get('li[data-cy-users-settings-new-group-name]').within(() => {
  20. // see that the group name is ""
  21. cy.get('input').should('exist').and('have.value', '')
  22. // set the group name to foo
  23. cy.get('input').type(groupName)
  24. // see that the group name is foo
  25. cy.get('input').should('have.value', groupName)
  26. // submit the group name
  27. cy.get('input ~ button').click()
  28. })
  29. // Make sure no confirmation modal is shown
  30. handlePasswordConfirmation(admin.password)
  31. // see that the created group is in the list
  32. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  33. // see that the list of groups contains the group foo
  34. cy.contains(groupName).should('exist')
  35. })
  36. })
  37. })
  38. describe('Settings: Assign user to a group', { testIsolation: false }, () => {
  39. const groupName = randomString(7)
  40. let testUser: User
  41. after(() => cy.deleteUser(testUser))
  42. before(() => {
  43. cy.createRandomUser().then((user) => {
  44. testUser = user
  45. })
  46. cy.runOccCommand(`group:add '${groupName}'`)
  47. cy.login(admin)
  48. cy.visit('/settings/users')
  49. })
  50. it('see that the group is in the list', () => {
  51. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').contains('li', groupName).should('exist')
  52. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').contains('li', groupName).within(() => {
  53. cy.get('.counter-bubble__counter')
  54. .should('not.exist') // is hidden when 0
  55. })
  56. })
  57. it('see that the user is in the list', () => {
  58. getUserListRow(testUser.userId)
  59. .contains(testUser.userId)
  60. .should('exist')
  61. .scrollIntoView()
  62. })
  63. it('switch into user edit mode', () => {
  64. toggleEditButton(testUser)
  65. getUserListRow(testUser.userId)
  66. .find('[data-cy-user-list-input-groups]')
  67. .should('exist')
  68. })
  69. it('assign the group', () => {
  70. // focus inside the input
  71. getUserListRow(testUser.userId)
  72. .find('[data-cy-user-list-input-groups] input')
  73. .click({ force: true })
  74. // enter the group name
  75. getUserListRow(testUser.userId)
  76. .find('[data-cy-user-list-input-groups] input')
  77. .type(`${groupName.slice(0, 5)}`) // only type part as otherwise we would create a new one with the same name
  78. cy.contains('li.vs__dropdown-option', groupName)
  79. .click({ force: true })
  80. handlePasswordConfirmation(admin.password)
  81. })
  82. it('leave the user edit mode', () => {
  83. toggleEditButton(testUser, false)
  84. })
  85. it('see the group was successfully assigned', () => {
  86. // see a new memeber
  87. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]')
  88. .contains('li', groupName)
  89. .find('.counter-bubble__counter')
  90. .should('contain', '1')
  91. })
  92. it('validate the user was added on backend', () => {
  93. cy.runOccCommand(`user:info --output=json '${testUser.userId}'`).then((output) => {
  94. cy.wrap(output.code).should('eq', 0)
  95. cy.wrap(JSON.parse(output.stdout)?.groups).should('include', groupName)
  96. })
  97. })
  98. })
  99. describe('Settings: Delete an empty group', { testIsolation: false }, () => {
  100. const groupName = randomString(7)
  101. before(() => {
  102. cy.runOccCommand(`group:add '${groupName}'`)
  103. cy.login(admin)
  104. cy.visit('/settings/users')
  105. })
  106. it('see that the group is in the list', () => {
  107. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  108. // see that the list of groups contains the group foo
  109. cy.contains(groupName).should('exist').scrollIntoView()
  110. // open the actions menu for the group
  111. cy.contains('li', groupName).within(() => {
  112. cy.get('button.action-item__menutoggle').click({ force: true })
  113. })
  114. })
  115. })
  116. it('can delete the group', () => {
  117. // The "Remove group" action in the actions menu is shown and clicked
  118. cy.get('.action-item__popper button').contains('Remove group').should('exist').click({ force: true })
  119. // And confirmation dialog accepted
  120. cy.get('.modal-container button').contains('Confirm').click({ force: true })
  121. // Make sure no confirmation modal is shown
  122. handlePasswordConfirmation(admin.password)
  123. })
  124. it('deleted group is not shown anymore', () => {
  125. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  126. // see that the list of groups does not contain the group
  127. cy.contains(groupName).should('not.exist')
  128. })
  129. // and also not in database
  130. cy.runOccCommand('group:list --output=json').then(($response) => {
  131. const groups: string[] = Object.keys(JSON.parse($response.stdout))
  132. expect(groups).to.not.include(groupName)
  133. })
  134. })
  135. })
  136. describe('Settings: Delete a non empty group', () => {
  137. let testUser: User
  138. const groupName = randomString(7)
  139. before(() => {
  140. cy.runOccCommand(`group:add '${groupName}'`)
  141. cy.createRandomUser().then(($user) => {
  142. testUser = $user
  143. cy.runOccCommand(`group:addUser '${groupName}' '${$user.userId}'`)
  144. })
  145. cy.login(admin)
  146. cy.visit('/settings/users')
  147. })
  148. after(() => cy.deleteUser(testUser))
  149. it('see that the group is in the list', () => {
  150. // see that the list of groups contains the group
  151. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').contains('li', groupName).should('exist').scrollIntoView()
  152. })
  153. it('can delete the group', () => {
  154. // open the menu
  155. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]')
  156. .contains('li', groupName)
  157. .find('button.action-item__menutoggle')
  158. .click({ force: true })
  159. // The "Remove group" action in the actions menu is shown and clicked
  160. cy.get('.action-item__popper button').contains('Remove group').should('exist').click({ force: true })
  161. // And confirmation dialog accepted
  162. cy.get('.modal-container button').contains('Confirm').click({ force: true })
  163. // Make sure no confirmation modal is shown
  164. handlePasswordConfirmation(admin.password)
  165. })
  166. it('deleted group is not shown anymore', () => {
  167. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  168. // see that the list of groups does not contain the group foo
  169. cy.contains(groupName).should('not.exist')
  170. })
  171. // and also not in database
  172. cy.runOccCommand('group:list --output=json').then(($response) => {
  173. const groups: string[] = Object.keys(JSON.parse($response.stdout))
  174. expect(groups).to.not.include(groupName)
  175. })
  176. })
  177. })
  178. describe.only('Settings: Sort groups in the UI', () => {
  179. before(() => {
  180. // Clear state
  181. cy.runOccCommand('group:list --output json').then((output) => {
  182. const groups = Object.keys(JSON.parse(output.stdout)).filter((group) => group !== 'admin')
  183. groups.forEach((group) => {
  184. cy.runOccCommand(`group:delete '${group}'`)
  185. })
  186. })
  187. // Add two groups and add one user to group B
  188. cy.runOccCommand('group:add A')
  189. cy.runOccCommand('group:add B')
  190. cy.createRandomUser().then((user) => {
  191. cy.runOccCommand(`group:adduser B '${user.userId}'`)
  192. })
  193. // Visit the settings as admin
  194. cy.login(admin)
  195. cy.visit('/settings/users')
  196. })
  197. it('Can set sort by member count', () => {
  198. // open the settings dialog
  199. cy.contains('button', 'Account management settings').click()
  200. cy.contains('.modal-container', 'Account management settings').within(() => {
  201. cy.get('[data-test="sortGroupsByMemberCount"] input[type="radio"]').scrollIntoView()
  202. cy.get('[data-test="sortGroupsByMemberCount"] input[type="radio"]').check({ force: true })
  203. // close the settings dialog
  204. cy.get('button.modal-container__close').click()
  205. })
  206. cy.waitUntil(() => cy.get('.modal-container').should(el => assertNotExistOrNotVisible(el)))
  207. })
  208. it('See that the groups are sorted by the member count', () => {
  209. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  210. cy.get('li').eq(0).should('contain', 'B') // 1 member
  211. cy.get('li').eq(1).should('contain', 'A') // 0 members
  212. })
  213. })
  214. it('See that the order is preserved after a reload', () => {
  215. cy.reload()
  216. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  217. cy.get('li').eq(0).should('contain', 'B') // 1 member
  218. cy.get('li').eq(1).should('contain', 'A') // 0 members
  219. })
  220. })
  221. it('Can set sort by group name', () => {
  222. // open the settings dialog
  223. cy.contains('button', 'Account management settings').click()
  224. cy.contains('.modal-container', 'Account management settings').within(() => {
  225. cy.get('[data-test="sortGroupsByName"] input[type="radio"]').scrollIntoView()
  226. cy.get('[data-test="sortGroupsByName"] input[type="radio"]').check({ force: true })
  227. // close the settings dialog
  228. cy.get('button.modal-container__close').click()
  229. })
  230. cy.waitUntil(() => cy.get('.modal-container').should(el => assertNotExistOrNotVisible(el)))
  231. })
  232. it('See that the groups are sorted by the user count', () => {
  233. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  234. cy.get('li').eq(0).should('contain', 'A')
  235. cy.get('li').eq(1).should('contain', 'B')
  236. })
  237. })
  238. it('See that the order is preserved after a reload', () => {
  239. cy.reload()
  240. cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
  241. cy.get('li').eq(0).should('contain', 'A')
  242. cy.get('li').eq(1).should('contain', 'B')
  243. })
  244. })
  245. })