You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

admin-settings.cy.ts 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /**
  2. * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com>
  3. *
  4. * @author John Molakvoæ <skjnldsv@protonmail.com>
  5. *
  6. * @license AGPL-3.0-or-later
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /* eslint-disable n/no-unpublished-import */
  23. import { User } from '@nextcloud/cypress'
  24. import { colord } from 'colord'
  25. import { pickRandomColor, validateBodyThemingCss, validateUserThemingDefaultCss } from './themingUtils'
  26. const admin = new User('admin', 'admin')
  27. const defaultPrimary = '#0082c9'
  28. const defaultBackground = 'kamil-porembinski-clouds.jpg'
  29. describe('Admin theming settings', function() {
  30. before(function() {
  31. // Just in case previous test failed
  32. cy.resetAdminTheming()
  33. cy.login(admin)
  34. })
  35. it('See the admin theming section', function() {
  36. cy.visit('/settings/admin/theming')
  37. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  38. })
  39. it('See the default settings', function() {
  40. cy.get('[data-admin-theming-setting-primary-color-picker]').should('contain.text', defaultPrimary)
  41. cy.get('[data-admin-theming-setting-primary-color-reset]').should('not.exist')
  42. cy.get('[data-admin-theming-setting-file-reset]').should('not.exist')
  43. cy.get('[data-admin-theming-setting-file-remove]').should('be.visible')
  44. })
  45. })
  46. describe('Change the primary colour and reset it', function() {
  47. let selectedColor = ''
  48. before(function() {
  49. // Just in case previous test failed
  50. cy.resetAdminTheming()
  51. cy.login(admin)
  52. })
  53. it('See the admin theming section', function() {
  54. cy.visit('/settings/admin/theming')
  55. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  56. })
  57. it('Change the primary colour', function() {
  58. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
  59. pickRandomColor('[data-admin-theming-setting-primary-color-picker]')
  60. .then(color => { selectedColor = color })
  61. cy.wait('@setColor')
  62. cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground))
  63. })
  64. it('Screenshot the login page', function() {
  65. cy.logout()
  66. cy.visit('/')
  67. cy.screenshot()
  68. })
  69. it('Undo theming settings', function() {
  70. cy.resetAdminTheming()
  71. })
  72. it('Screenshot the login page', function() {
  73. cy.visit('/')
  74. cy.waitUntil(validateBodyThemingCss)
  75. cy.screenshot()
  76. })
  77. })
  78. describe('Remove the default background and restore it', function() {
  79. before(function() {
  80. // Just in case previous test failed
  81. cy.resetAdminTheming()
  82. cy.login(admin)
  83. })
  84. it('See the admin theming section', function() {
  85. cy.visit('/settings/admin/theming')
  86. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  87. })
  88. it('Remove the default background', function() {
  89. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
  90. cy.get('[data-admin-theming-setting-file-remove]').click()
  91. cy.wait('@removeBackground')
  92. cy.waitUntil(() => cy.window().then((win) => {
  93. const currentBackgroundDefault = getComputedStyle(win.document.body).getPropertyValue('--image-background-default')
  94. const backgroundPlain = getComputedStyle(win.document.body).getPropertyValue('--image-background-plain')
  95. return !currentBackgroundDefault.includes(defaultBackground)
  96. && backgroundPlain !== ''
  97. }))
  98. })
  99. it('Screenshot the login page', function() {
  100. cy.logout()
  101. cy.visit('/')
  102. cy.screenshot()
  103. })
  104. it('Undo theming settings', function() {
  105. cy.resetAdminTheming()
  106. })
  107. it('Screenshot the login page', function() {
  108. cy.visit('/')
  109. cy.waitUntil(validateBodyThemingCss)
  110. cy.screenshot()
  111. })
  112. })
  113. describe.only('Remove the default background with a bright color', function() {
  114. before(function() {
  115. // Just in case previous test failed
  116. cy.resetAdminTheming()
  117. cy.resetUserTheming(admin)
  118. cy.login(admin)
  119. })
  120. it('See the admin theming section', function() {
  121. cy.visit('/settings/admin/theming')
  122. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  123. })
  124. it('Remove the default background', function() {
  125. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
  126. cy.get('[data-admin-theming-setting-file-remove]').click()
  127. cy.wait('@removeBackground')
  128. })
  129. it('Change the primary colour', function() {
  130. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
  131. // Pick one of the bright color preset
  132. cy.get('[data-admin-theming-setting-primary-color-picker]').click()
  133. cy.get('.color-picker__simple-color-circle:eq(4)').click()
  134. cy.wait('@setColor')
  135. cy.waitUntil(() => validateBodyThemingCss('#ddcb55', ''))
  136. })
  137. it('See the header being inverted', function() {
  138. cy.waitUntil(() => cy.window().then((win) => {
  139. const firstEntry = win.document.querySelector('.app-menu-main li')
  140. if (!firstEntry) {
  141. return false
  142. }
  143. return getComputedStyle(firstEntry).filter === 'invert(1)'
  144. }))
  145. })
  146. })
  147. describe('Change the login fields then reset them', function() {
  148. const name = 'ABCdef123'
  149. const url = 'https://example.com'
  150. const slogan = 'Testing is fun'
  151. before(function() {
  152. // Just in case previous test failed
  153. cy.resetAdminTheming()
  154. cy.login(admin)
  155. })
  156. it('See the admin theming section', function() {
  157. cy.visit('/settings/admin/theming')
  158. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  159. })
  160. it('Change the name field', function() {
  161. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('updateFields')
  162. // Name
  163. cy.get('[data-admin-theming-setting-field="name"] input[type="text"]')
  164. .scrollIntoView()
  165. .type('{selectall}')
  166. .type(name)
  167. .type('{enter}')
  168. cy.wait('@updateFields')
  169. // Url
  170. cy.get('[data-admin-theming-setting-field="url"] input[type="url"]')
  171. .scrollIntoView()
  172. .type('{selectall}')
  173. .type(url)
  174. .type('{enter}')
  175. cy.wait('@updateFields')
  176. // Slogan
  177. cy.get('[data-admin-theming-setting-field="slogan"] input[type="text"]')
  178. .scrollIntoView()
  179. .type('{selectall}')
  180. .type(slogan)
  181. .type('{enter}')
  182. cy.wait('@updateFields')
  183. })
  184. it('Ensure undo button presence', function() {
  185. cy.get('[data-admin-theming-setting-field="name"] .input-field__clear-button')
  186. .scrollIntoView().should('be.visible')
  187. cy.get('[data-admin-theming-setting-field="url"] .input-field__clear-button')
  188. .scrollIntoView().should('be.visible')
  189. cy.get('[data-admin-theming-setting-field="slogan"] .input-field__clear-button')
  190. .scrollIntoView().should('be.visible')
  191. })
  192. it('Check login screen changes', function() {
  193. cy.logout()
  194. cy.visit('/')
  195. cy.get('[data-login-form-headline]').should('contain.text', name)
  196. cy.get('footer p a').should('have.text', name)
  197. cy.get('footer p a').should('have.attr', 'href', url)
  198. cy.get('footer p').should('contain.text', `– ${slogan}`)
  199. })
  200. it('Undo theming settings', function() {
  201. cy.resetAdminTheming()
  202. })
  203. it('Check login screen changes', function() {
  204. cy.visit('/')
  205. cy.get('[data-login-form-headline]').should('not.contain.text', name)
  206. cy.get('footer p a').should('not.have.text', name)
  207. cy.get('footer p a').should('not.have.attr', 'href', url)
  208. cy.get('footer p').should('not.contain.text', `– ${slogan}`)
  209. })
  210. })
  211. describe('Disable user theming and enable it back', function() {
  212. before(function() {
  213. // Just in case previous test failed
  214. cy.resetAdminTheming()
  215. cy.login(admin)
  216. })
  217. it('See the admin theming section', function() {
  218. cy.visit('/settings/admin/theming')
  219. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  220. })
  221. it('Disable user theming', function() {
  222. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('disableUserTheming')
  223. cy.get('[data-admin-theming-setting-disable-user-theming]')
  224. .scrollIntoView().should('be.visible')
  225. cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').check({ force: true })
  226. cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').should('be.checked')
  227. cy.wait('@disableUserTheming')
  228. })
  229. it('Login as user', function() {
  230. cy.logout()
  231. cy.createRandomUser().then((user) => {
  232. cy.login(user)
  233. })
  234. })
  235. it('See the user disabled background settings', function() {
  236. cy.visit('/settings/user/theming')
  237. cy.get('[data-user-theming-background-disabled]').scrollIntoView().should('be.visible')
  238. })
  239. })
  240. describe('User default option matches admin theming', function() {
  241. let selectedColor = ''
  242. before(function() {
  243. // Just in case previous test failed
  244. cy.resetAdminTheming()
  245. cy.login(admin)
  246. })
  247. after(function() {
  248. cy.resetAdminTheming()
  249. })
  250. it('See the admin theming section', function() {
  251. cy.visit('/settings/admin/theming')
  252. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  253. })
  254. it('Change the primary colour', function() {
  255. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
  256. pickRandomColor('[data-admin-theming-setting-primary-color-picker]')
  257. .then(color => { selectedColor = color })
  258. cy.wait('@setColor')
  259. cy.waitUntil(() => cy.window().then((win) => {
  260. const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary-default')
  261. return colord(primary).isEqual(selectedColor)
  262. }))
  263. })
  264. it('Change the default background', function() {
  265. cy.intercept('*/apps/theming/ajax/uploadImage').as('setBackground')
  266. cy.fixture('image.jpg', null).as('background')
  267. cy.get('[data-admin-theming-setting-file="background"] input[type="file"]').selectFile('@background', { force: true })
  268. cy.wait('@setBackground')
  269. cy.waitUntil(() => cy.window().then((win) => {
  270. const currentBackgroundDefault = getComputedStyle(win.document.body).getPropertyValue('--image-background-default')
  271. return currentBackgroundDefault.includes('/apps/theming/image/background?v=')
  272. }))
  273. })
  274. it('Logout and check changes', function() {
  275. cy.logout()
  276. cy.visit('/')
  277. cy.waitUntil(() => validateBodyThemingCss(selectedColor, '/apps/theming/image/background?v='))
  278. })
  279. it('Login as user', function() {
  280. cy.createRandomUser().then((user) => {
  281. cy.login(user)
  282. })
  283. })
  284. it('See the user background settings', function() {
  285. cy.visit('/settings/user/theming')
  286. cy.get('[data-user-theming-background-settings]').scrollIntoView().should('be.visible')
  287. })
  288. it('See the default background option selected', function() {
  289. cy.get('[data-user-theming-background-default]').should('be.visible')
  290. cy.get('[data-user-theming-background-default]').should('have.class', 'background--active')
  291. cy.waitUntil(() => validateUserThemingDefaultCss(selectedColor, '/apps/theming/image/background?v='))
  292. })
  293. })