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 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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 { defaultPrimary, defaultBackground, pickRandomColor, validateBodyThemingCss, validateUserThemingDefaultCss } from './themingUtils'
  26. const admin = new User('admin', 'admin')
  27. describe('Admin theming settings visibility check', function() {
  28. before(function() {
  29. // Just in case previous test failed
  30. cy.resetAdminTheming()
  31. cy.login(admin)
  32. })
  33. it('See the admin theming section', function() {
  34. cy.visit('/settings/admin/theming')
  35. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  36. })
  37. it('See the default settings', function() {
  38. cy.get('[data-admin-theming-setting-primary-color-picker]').should('contain.text', defaultPrimary)
  39. cy.get('[data-admin-theming-setting-primary-color-reset]').should('not.exist')
  40. cy.get('[data-admin-theming-setting-file-reset]').should('not.exist')
  41. cy.get('[data-admin-theming-setting-file-remove]').should('be.visible')
  42. })
  43. })
  44. describe('Change the primary color and reset it', function() {
  45. let selectedColor = ''
  46. before(function() {
  47. // Just in case previous test failed
  48. cy.resetAdminTheming()
  49. cy.login(admin)
  50. })
  51. it('See the admin theming section', function() {
  52. cy.visit('/settings/admin/theming')
  53. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  54. })
  55. it('Change the primary color', function() {
  56. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
  57. pickRandomColor('[data-admin-theming-setting-primary-color-picker]')
  58. .then(color => { selectedColor = color })
  59. cy.wait('@setColor')
  60. cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground))
  61. })
  62. it('Screenshot the login page and validate login page', function() {
  63. cy.logout()
  64. cy.visit('/')
  65. cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground))
  66. cy.screenshot()
  67. })
  68. it('Undo theming settings and validate login page again', function() {
  69. cy.resetAdminTheming()
  70. cy.visit('/')
  71. cy.waitUntil(validateBodyThemingCss)
  72. cy.screenshot()
  73. })
  74. })
  75. describe('Remove the default background and restore it', function() {
  76. before(function() {
  77. // Just in case previous test failed
  78. cy.resetAdminTheming()
  79. cy.login(admin)
  80. })
  81. it('See the admin theming section', function() {
  82. cy.visit('/settings/admin/theming')
  83. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  84. })
  85. it('Remove the default background', function() {
  86. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
  87. cy.get('[data-admin-theming-setting-file-remove]').click()
  88. cy.wait('@removeBackground')
  89. cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, null))
  90. cy.waitUntil(() => cy.window().then((win) => {
  91. const backgroundPlain = getComputedStyle(win.document.body).getPropertyValue('--image-background-plain')
  92. return backgroundPlain !== ''
  93. }))
  94. })
  95. it('Screenshot the login page and validate login page', function() {
  96. cy.logout()
  97. cy.visit('/')
  98. cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, null))
  99. cy.screenshot()
  100. })
  101. it('Undo theming settings and validate login page again', function() {
  102. cy.resetAdminTheming()
  103. cy.visit('/')
  104. cy.waitUntil(validateBodyThemingCss)
  105. cy.screenshot()
  106. })
  107. })
  108. describe('Remove the default background with a custom primary color', function() {
  109. let selectedColor = ''
  110. before(function() {
  111. // Just in case previous test failed
  112. cy.resetAdminTheming()
  113. cy.login(admin)
  114. })
  115. it('See the admin theming section', function() {
  116. cy.visit('/settings/admin/theming')
  117. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  118. })
  119. it('Change the primary color', function() {
  120. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
  121. pickRandomColor('[data-admin-theming-setting-primary-color-picker]')
  122. .then(color => selectedColor = color)
  123. cy.wait('@setColor')
  124. cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground))
  125. })
  126. it('Remove the default background', function() {
  127. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
  128. cy.get('[data-admin-theming-setting-file-remove]').click()
  129. cy.wait('@removeBackground')
  130. })
  131. it('Screenshot the login page and validate login page', function() {
  132. cy.logout()
  133. cy.visit('/')
  134. cy.waitUntil(() => validateBodyThemingCss(selectedColor, null))
  135. cy.screenshot()
  136. })
  137. it('Undo theming settings and validate login page again', function() {
  138. cy.resetAdminTheming()
  139. cy.visit('/')
  140. cy.waitUntil(validateBodyThemingCss)
  141. cy.screenshot()
  142. })
  143. })
  144. describe('Remove the default background with a bright color', function() {
  145. before(function() {
  146. // Just in case previous test failed
  147. cy.resetAdminTheming()
  148. cy.resetUserTheming(admin)
  149. cy.login(admin)
  150. })
  151. it('See the admin theming section', function() {
  152. cy.visit('/settings/admin/theming')
  153. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  154. })
  155. it('Remove the default background', function() {
  156. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
  157. cy.get('[data-admin-theming-setting-file-remove]').click()
  158. cy.wait('@removeBackground')
  159. })
  160. it('Change the primary color', function() {
  161. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
  162. // Pick one of the bright color preset
  163. cy.get('[data-admin-theming-setting-primary-color-picker]').click()
  164. cy.get('.color-picker__simple-color-circle:eq(4)').click()
  165. cy.wait('@setColor')
  166. cy.waitUntil(() => validateBodyThemingCss('#ddcb55', null))
  167. })
  168. it('See the header being inverted', function() {
  169. cy.waitUntil(() => cy.window().then((win) => {
  170. const firstEntry = win.document.querySelector('.app-menu-main li img')
  171. if (!firstEntry) {
  172. return false
  173. }
  174. return getComputedStyle(firstEntry).filter === 'invert(1)'
  175. }))
  176. })
  177. })
  178. describe('Change the login fields then reset them', function() {
  179. const name = 'ABCdef123'
  180. const url = 'https://example.com'
  181. const slogan = 'Testing is fun'
  182. before(function() {
  183. // Just in case previous test failed
  184. cy.resetAdminTheming()
  185. cy.login(admin)
  186. })
  187. it('See the admin theming section', function() {
  188. cy.visit('/settings/admin/theming')
  189. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  190. })
  191. it('Change the name field', function() {
  192. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('updateFields')
  193. // Name
  194. cy.get('[data-admin-theming-setting-field="name"] input[type="text"]')
  195. .scrollIntoView()
  196. .type('{selectall}')
  197. .type(name)
  198. .type('{enter}')
  199. cy.wait('@updateFields')
  200. // Url
  201. cy.get('[data-admin-theming-setting-field="url"] input[type="url"]')
  202. .scrollIntoView()
  203. .type('{selectall}')
  204. .type(url)
  205. .type('{enter}')
  206. cy.wait('@updateFields')
  207. // Slogan
  208. cy.get('[data-admin-theming-setting-field="slogan"] input[type="text"]')
  209. .scrollIntoView()
  210. .type('{selectall}')
  211. .type(slogan)
  212. .type('{enter}')
  213. cy.wait('@updateFields')
  214. })
  215. it('Ensure undo button presence', function() {
  216. cy.get('[data-admin-theming-setting-field="name"] .input-field__clear-button')
  217. .scrollIntoView().should('be.visible')
  218. cy.get('[data-admin-theming-setting-field="url"] .input-field__clear-button')
  219. .scrollIntoView().should('be.visible')
  220. cy.get('[data-admin-theming-setting-field="slogan"] .input-field__clear-button')
  221. .scrollIntoView().should('be.visible')
  222. })
  223. it('Validate login screen changes', function() {
  224. cy.logout()
  225. cy.visit('/')
  226. cy.get('[data-login-form-headline]').should('contain.text', name)
  227. cy.get('footer p a').should('have.text', name)
  228. cy.get('footer p a').should('have.attr', 'href', url)
  229. cy.get('footer p').should('contain.text', `– ${slogan}`)
  230. })
  231. it('Undo theming settings', function() {
  232. cy.resetAdminTheming()
  233. })
  234. it('Validate login screen changes again', function() {
  235. cy.visit('/')
  236. cy.get('[data-login-form-headline]').should('not.contain.text', name)
  237. cy.get('footer p a').should('not.have.text', name)
  238. cy.get('footer p a').should('not.have.attr', 'href', url)
  239. cy.get('footer p').should('not.contain.text', `– ${slogan}`)
  240. })
  241. })
  242. describe('Disable user theming and enable it back', function() {
  243. before(function() {
  244. // Just in case previous test failed
  245. cy.resetAdminTheming()
  246. cy.login(admin)
  247. })
  248. it('See the admin theming section', function() {
  249. cy.visit('/settings/admin/theming')
  250. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  251. })
  252. it('Disable user background theming', function() {
  253. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('disableUserTheming')
  254. cy.get('[data-admin-theming-setting-disable-user-theming]')
  255. .scrollIntoView().should('be.visible')
  256. cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').check({ force: true })
  257. cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').should('be.checked')
  258. cy.wait('@disableUserTheming')
  259. })
  260. it('Login as user', function() {
  261. cy.logout()
  262. cy.createRandomUser().then((user) => {
  263. cy.login(user)
  264. })
  265. })
  266. it('User cannot not change background settings', function() {
  267. cy.visit('/settings/user/theming')
  268. cy.get('[data-user-theming-background-disabled]').scrollIntoView().should('be.visible')
  269. })
  270. })
  271. describe('The user default background settings reflect the admin theming settings', function() {
  272. let selectedColor = ''
  273. before(function() {
  274. // Just in case previous test failed
  275. cy.resetAdminTheming()
  276. cy.login(admin)
  277. })
  278. after(function() {
  279. cy.resetAdminTheming()
  280. })
  281. it('See the admin theming section', function() {
  282. cy.visit('/settings/admin/theming')
  283. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  284. })
  285. it('Change the primary color', function() {
  286. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
  287. pickRandomColor('[data-admin-theming-setting-primary-color-picker]')
  288. .then(color => { selectedColor = color })
  289. cy.wait('@setColor')
  290. cy.waitUntil(() => cy.window().then((win) => {
  291. const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary-default')
  292. return colord(primary).isEqual(selectedColor)
  293. }))
  294. })
  295. it('Change the default background', function() {
  296. cy.intercept('*/apps/theming/ajax/uploadImage').as('setBackground')
  297. cy.fixture('image.jpg', null).as('background')
  298. cy.get('[data-admin-theming-setting-file="background"] input[type="file"]').selectFile('@background', { force: true })
  299. cy.wait('@setBackground')
  300. cy.waitUntil(() => cy.window().then((win) => {
  301. const currentBackgroundDefault = getComputedStyle(win.document.body).getPropertyValue('--image-background-default')
  302. return currentBackgroundDefault.includes('/apps/theming/image/background?v=')
  303. }))
  304. })
  305. it('Login page should match admin theming settings', function() {
  306. cy.logout()
  307. cy.visit('/')
  308. cy.waitUntil(() => validateBodyThemingCss(selectedColor, '/apps/theming/image/background?v='))
  309. })
  310. it('Login as user', function() {
  311. cy.createRandomUser().then((user) => {
  312. cy.login(user)
  313. })
  314. })
  315. it('See the user background settings', function() {
  316. cy.visit('/settings/user/theming')
  317. cy.get('[data-user-theming-background-settings]').scrollIntoView().should('be.visible')
  318. })
  319. it('Default user background settings should match admin theming settings', function() {
  320. cy.get('[data-user-theming-background-default]').should('be.visible')
  321. cy.get('[data-user-theming-background-default]').should('have.class', 'background--active')
  322. cy.waitUntil(() => validateUserThemingDefaultCss(selectedColor, '/apps/theming/image/background?v='))
  323. })
  324. })
  325. describe('The user default background settings reflect the admin theming settings with background removed', function() {
  326. before(function() {
  327. // Just in case previous test failed
  328. cy.resetAdminTheming()
  329. cy.login(admin)
  330. })
  331. after(function() {
  332. cy.resetAdminTheming()
  333. })
  334. it('See the admin theming section', function() {
  335. cy.visit('/settings/admin/theming')
  336. cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible')
  337. })
  338. it('Remove the default background', function() {
  339. cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
  340. cy.get('[data-admin-theming-setting-file-remove]').click()
  341. cy.wait('@removeBackground')
  342. cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, null))
  343. })
  344. it('Login page should match admin theming settings', function() {
  345. cy.logout()
  346. cy.visit('/')
  347. cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, null))
  348. })
  349. it('Login as user', function() {
  350. cy.createRandomUser().then((user) => {
  351. cy.login(user)
  352. })
  353. })
  354. it('See the user background settings', function() {
  355. cy.visit('/settings/user/theming')
  356. cy.get('[data-user-theming-background-settings]').scrollIntoView().should('be.visible')
  357. })
  358. it('Default user background settings should match admin theming settings', function() {
  359. cy.get('[data-user-theming-background-default]').should('be.visible')
  360. cy.get('[data-user-theming-background-default]').should('have.class', 'background--active')
  361. cy.waitUntil(() => validateUserThemingDefaultCss(defaultPrimary, null))
  362. })
  363. })