user-background.cy.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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. import { User } from '@nextcloud/cypress'
  23. import { defaultPrimary, defaultBackground, pickRandomColor, validateBodyThemingCss } from './themingUtils'
  24. const admin = new User('admin', 'admin')
  25. describe('User default background settings', function() {
  26. before(function() {
  27. cy.resetAdminTheming()
  28. cy.resetUserTheming(admin)
  29. cy.createRandomUser().then((user: User) => {
  30. cy.login(user)
  31. })
  32. })
  33. it('See the user background settings', function() {
  34. cy.visit('/settings/user/theming')
  35. cy.get('[data-user-theming-background-settings]').scrollIntoView()
  36. cy.get('[data-user-theming-background-settings]').should('be.visible')
  37. })
  38. // Default cloud background is not rendered if admin theming background remains unchanged
  39. it('Default cloud background is not rendered', function() {
  40. cy.get(`[data-user-theming-background-shipped="${defaultBackground}"]`).should('not.exist')
  41. })
  42. it('Default is selected on new users', function() {
  43. cy.get('[data-user-theming-background-default]').should('be.visible')
  44. cy.get('[data-user-theming-background-default]').should('have.class', 'background--active')
  45. })
  46. it('Default background has accessibility attribute set', function() {
  47. cy.get('[data-user-theming-background-default]').should('have.attr', 'aria-pressed', 'true')
  48. })
  49. })
  50. describe('User select shipped backgrounds and remove background', function() {
  51. before(function() {
  52. cy.createRandomUser().then((user: User) => {
  53. cy.login(user)
  54. })
  55. })
  56. it('See the user background settings', function() {
  57. cy.visit('/settings/user/theming')
  58. cy.get('[data-user-theming-background-settings]').scrollIntoView()
  59. cy.get('[data-user-theming-background-settings]').should('be.visible')
  60. })
  61. it('Select a shipped background', function() {
  62. const background = 'anatoly-mikhaltsov-butterfly-wing-scale.jpg'
  63. cy.intercept('*/apps/theming/background/shipped').as('setBackground')
  64. // Select background
  65. cy.get(`[data-user-theming-background-shipped="${background}"]`).click()
  66. // Set the accessibility state
  67. cy.get(`[data-user-theming-background-shipped="${background}"]`).should('have.attr', 'aria-pressed', 'true')
  68. // Validate changed background and primary
  69. cy.wait('@setBackground')
  70. cy.waitUntil(() => validateBodyThemingCss('#a53c17', background))
  71. })
  72. it('Select a bright shipped background', function() {
  73. const background = 'bernie-cetonia-aurata-take-off-composition.jpg'
  74. cy.intercept('*/apps/theming/background/shipped').as('setBackground')
  75. // Select background
  76. cy.get(`[data-user-theming-background-shipped="${background}"]`).click()
  77. // Set the accessibility state
  78. cy.get(`[data-user-theming-background-shipped="${background}"]`).should('have.attr', 'aria-pressed', 'true')
  79. // Validate changed background and primary
  80. cy.wait('@setBackground')
  81. cy.waitUntil(() => validateBodyThemingCss('#869171', background))
  82. })
  83. it('Remove background', function() {
  84. cy.intercept('*/apps/theming/background/custom').as('clearBackground')
  85. // Clear background
  86. cy.get('[data-user-theming-background-clear]').click()
  87. // Set the accessibility state
  88. cy.get('[data-user-theming-background-clear]').should('have.attr', 'aria-pressed', 'true')
  89. // Validate clear background
  90. cy.wait('@clearBackground')
  91. cy.waitUntil(() => validateBodyThemingCss('#869171', null))
  92. })
  93. })
  94. describe('User select a custom color', function() {
  95. before(function() {
  96. cy.createRandomUser().then((user: User) => {
  97. cy.login(user)
  98. })
  99. })
  100. it('See the user background settings', function() {
  101. cy.visit('/settings/user/theming')
  102. cy.get('[data-user-theming-background-settings]').scrollIntoView()
  103. cy.get('[data-user-theming-background-settings]').should('be.visible')
  104. })
  105. it('Select a custom color', function() {
  106. cy.intercept('*/apps/theming/background/color').as('setColor')
  107. pickRandomColor()
  108. // Validate custom colour change
  109. cy.wait('@setColor')
  110. cy.waitUntil(() => cy.window().then((win) => {
  111. const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary')
  112. return primary !== defaultPrimary && primary !== defaultPrimary
  113. }))
  114. })
  115. })
  116. describe('User select a bright custom color and remove background', function() {
  117. before(function() {
  118. cy.createRandomUser().then((user: User) => {
  119. cy.login(user)
  120. })
  121. })
  122. it('See the user background settings', function() {
  123. cy.visit('/settings/user/theming')
  124. cy.get('[data-user-theming-background-settings]').scrollIntoView()
  125. cy.get('[data-user-theming-background-settings]').should('be.visible')
  126. })
  127. it('Remove background', function() {
  128. cy.intercept('*/apps/theming/background/custom').as('clearBackground')
  129. // Clear background
  130. cy.get('[data-user-theming-background-clear]').click()
  131. // Validate clear background
  132. cy.wait('@clearBackground')
  133. cy.waitUntil(() => validateBodyThemingCss(undefined, null))
  134. })
  135. it('Select a custom color', function() {
  136. cy.intercept('*/apps/theming/background/color').as('setColor')
  137. // Pick one of the bright color preset
  138. cy.contains('button', 'Change color').click()
  139. cy.get('.color-picker__simple-color-circle:eq(4)').click()
  140. // Validate custom colour change
  141. cy.wait('@setColor')
  142. })
  143. it('See the header being inverted', function() {
  144. cy.waitUntil(() => cy.window().then((win) => {
  145. const firstEntry = win.document.querySelector('.app-menu-main li img')
  146. if (!firstEntry) {
  147. return false
  148. }
  149. return getComputedStyle(firstEntry).filter === 'invert(1)'
  150. }))
  151. })
  152. it('Select another but non-bright shipped background', function() {
  153. const background = 'anatoly-mikhaltsov-butterfly-wing-scale.jpg'
  154. cy.intercept('*/apps/theming/background/shipped').as('setBackground')
  155. // Select background
  156. cy.get(`[data-user-theming-background-shipped="${background}"]`).click()
  157. // Validate changed background and primary
  158. cy.wait('@setBackground')
  159. cy.waitUntil(() => validateBodyThemingCss('#a53c17', background))
  160. })
  161. it('See the header NOT being inverted this time', function() {
  162. cy.waitUntil(() => cy.window().then((win) => {
  163. const firstEntry = win.document.querySelector('.app-menu-main li')
  164. if (!firstEntry) {
  165. return false
  166. }
  167. return getComputedStyle(firstEntry).filter === 'none'
  168. }))
  169. })
  170. })
  171. describe('User select a custom background', function() {
  172. const image = 'image.jpg'
  173. before(function() {
  174. cy.createRandomUser().then((user: User) => {
  175. cy.uploadFile(user, image, 'image/jpeg')
  176. cy.login(user)
  177. })
  178. })
  179. it('See the user background settings', function() {
  180. cy.visit('/settings/user/theming')
  181. cy.get('[data-user-theming-background-settings]').scrollIntoView()
  182. cy.get('[data-user-theming-background-settings]').should('be.visible')
  183. })
  184. it('Select a custom background', function() {
  185. cy.intercept('*/apps/theming/background/custom').as('setBackground')
  186. cy.on('uncaught:exception', (err) => {
  187. // This can happen because of blink engine & skeleton animation, its not a bug just engine related.
  188. if (err.message.includes('ResizeObserver loop limit exceeded')) {
  189. return false
  190. }
  191. })
  192. // Pick background
  193. cy.get('[data-user-theming-background-custom]').click()
  194. cy.get('.file-picker__files tr').contains(image).click()
  195. cy.get('.dialog__actions .button-vue--vue-primary').click()
  196. // Wait for background to be set
  197. cy.wait('@setBackground')
  198. cy.waitUntil(() => validateBodyThemingCss('#4c0c04', 'apps/theming/background?v='))
  199. })
  200. })
  201. describe('User changes settings and reload the page', function() {
  202. const image = 'image.jpg'
  203. const primaryFromImage = '#4c0c04'
  204. let selectedColor = ''
  205. before(function() {
  206. cy.createRandomUser().then((user: User) => {
  207. cy.uploadFile(user, image, 'image/jpeg')
  208. cy.login(user)
  209. })
  210. })
  211. it('See the user background settings', function() {
  212. cy.visit('/settings/user/theming')
  213. cy.get('[data-user-theming-background-settings]').scrollIntoView()
  214. cy.get('[data-user-theming-background-settings]').should('be.visible')
  215. })
  216. it('Select a custom background', function() {
  217. cy.intercept('*/apps/theming/background/custom').as('setBackground')
  218. cy.on('uncaught:exception', (err) => {
  219. // This can happen because of blink engine & skeleton animation, its not a bug just engine related.
  220. if (err.message.includes('ResizeObserver loop limit exceeded')) {
  221. return false
  222. }
  223. })
  224. // Pick background
  225. cy.get('[data-user-theming-background-custom]').click()
  226. cy.get('.file-picker__files tr').contains(image).click()
  227. cy.get('.dialog__actions .button-vue--vue-primary').click()
  228. // Wait for background to be set
  229. cy.wait('@setBackground')
  230. cy.waitUntil(() => validateBodyThemingCss(primaryFromImage, 'apps/theming/background?v='))
  231. })
  232. it('Select a custom color', function() {
  233. cy.intercept('*/apps/theming/background/color').as('setColor')
  234. cy.contains('button', 'Change color').click()
  235. cy.get('.color-picker__simple-color-circle:eq(5)').click()
  236. // Validate clear background
  237. cy.wait('@setColor')
  238. cy.waitUntil(() => cy.window().then((win) => {
  239. selectedColor = getComputedStyle(win.document.body).getPropertyValue('--color-primary')
  240. return selectedColor !== primaryFromImage
  241. }))
  242. })
  243. it('Reload the page and validate persistent changes', function() {
  244. cy.reload()
  245. cy.waitUntil(() => validateBodyThemingCss(selectedColor, 'apps/theming/background?v='))
  246. // validate accessibility state
  247. cy.get('[data-user-theming-background-custom]').should('have.attr', 'aria-pressed', 'true')
  248. })
  249. })