custom-themes.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. var t = require('assert')
  2. var defaults = require('./utils/defaults')
  3. module.exports = ({popup, advanced, content}) => {
  4. before(async () => {
  5. await defaults({popup, advanced, content})
  6. })
  7. describe('validate input', () => {
  8. before(async () => {
  9. // advanced
  10. await advanced.bringToFront()
  11. })
  12. it('missing name and url', async () => {
  13. // both empty
  14. await advanced.evaluate(() => {
  15. document.querySelector('.m-add-theme [placeholder=Name]').value = ''
  16. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  17. document.querySelector('.m-add-theme [placeholder~=URL]').value = ''
  18. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  19. document.querySelector('.m-add-theme button').click()
  20. })
  21. t.equal(
  22. await advanced.evaluate(() => {
  23. document.querySelector('.m-themes .m-list')
  24. }),
  25. null,
  26. 'should not add theme with missing name and url'
  27. )
  28. })
  29. it('missing name', async () => {
  30. // empty name
  31. await advanced.evaluate(() => {
  32. document.querySelector('.m-add-theme [placeholder=Name]').value = ''
  33. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  34. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'hey'
  35. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  36. document.querySelector('.m-add-theme button').click()
  37. })
  38. t.equal(
  39. await advanced.evaluate(() => {
  40. document.querySelector('.m-themes .m-list')
  41. }),
  42. null,
  43. 'should not add theme with missing name'
  44. )
  45. })
  46. it('missing url', async () => {
  47. // empty url
  48. await advanced.evaluate(() => {
  49. document.querySelector('.m-add-theme [placeholder=Name]').value = 'hey'
  50. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  51. document.querySelector('.m-add-theme [placeholder~=URL]').value = ''
  52. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  53. document.querySelector('.m-add-theme button').click()
  54. })
  55. t.equal(
  56. await advanced.evaluate(() => {
  57. document.querySelector('.m-themes .m-list')
  58. }),
  59. null,
  60. 'should not add theme with missing url'
  61. )
  62. })
  63. it('duplicate name from the default themes', async () => {
  64. await advanced.evaluate(() => {
  65. document.querySelector('.m-add-theme [placeholder=Name]').value = 'github'
  66. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  67. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'hey'
  68. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  69. document.querySelector('.m-add-theme button').click()
  70. })
  71. t.equal(
  72. await advanced.evaluate(() => {
  73. document.querySelector('.m-themes .m-list')
  74. }),
  75. null,
  76. 'should not add theme with duplicate name'
  77. )
  78. })
  79. })
  80. describe('add', () => {
  81. before(async () => {
  82. await advanced.bringToFront()
  83. })
  84. it('add custom theme', async () => {
  85. // add theme
  86. await advanced.evaluate(() => {
  87. document.querySelector('.m-add-theme [placeholder=Name]').value = 'a custom theme'
  88. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  89. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'file:///hey'
  90. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  91. document.querySelector('.m-add-theme button').click()
  92. })
  93. await advanced.waitFor(300)
  94. t.equal(
  95. await advanced.evaluate(() =>
  96. document.querySelectorAll('.m-themes .m-list li').length
  97. ),
  98. 1,
  99. 'the new theme should be added to the list of custom themes'
  100. )
  101. t.equal(
  102. await advanced.evaluate(() =>
  103. document.querySelector('.m-themes .m-list .m-title').innerText
  104. ),
  105. 'a custom theme',
  106. 'the custom theme name should be set in the list'
  107. )
  108. t.equal(
  109. await advanced.evaluate(() =>
  110. document.querySelector('.m-add-theme [placeholder=Name]').innerText
  111. ),
  112. '',
  113. 'cleanup name input'
  114. )
  115. t.equal(
  116. await advanced.evaluate(() =>
  117. document.querySelector('.m-add-theme [placeholder~=URL]').innerText
  118. ),
  119. '',
  120. 'cleanup url input'
  121. )
  122. })
  123. it('duplicate name from the custom themes', async () => {
  124. await advanced.evaluate(() => {
  125. document.querySelector('.m-add-theme [placeholder=Name]').value = 'a custom theme'
  126. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  127. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'hey'
  128. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  129. document.querySelector('.m-add-theme button').click()
  130. })
  131. t.equal(
  132. await advanced.evaluate(() =>
  133. document.querySelectorAll('.m-themes .m-list').length
  134. ),
  135. 1,
  136. 'should not add theme with duplicate name'
  137. )
  138. })
  139. it('preserve state', async () => {
  140. await advanced.reload()
  141. await advanced.waitFor(300)
  142. t.equal(
  143. await advanced.evaluate(() =>
  144. document.querySelectorAll('.m-themes .m-list').length
  145. ),
  146. 1,
  147. 'the new theme should be added to the list of custom themes'
  148. )
  149. t.equal(
  150. await advanced.evaluate(() =>
  151. document.querySelector('.m-themes .m-list .m-title').innerText
  152. ),
  153. 'a custom theme',
  154. 'the custom theme name should be set in the list'
  155. )
  156. })
  157. })
  158. describe('choose', () => {
  159. before(async () => {
  160. // advanced
  161. await advanced.bringToFront()
  162. // add theme
  163. await advanced.evaluate(() => {
  164. document.querySelector('.m-add-theme [placeholder=Name]').value = 'a custom theme'
  165. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  166. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'file:///hey'
  167. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  168. document.querySelector('.m-add-theme button').click()
  169. })
  170. })
  171. it('choose custom theme from the popup', async () => {
  172. // popup
  173. await popup.bringToFront()
  174. await popup.reload()
  175. // theme tab
  176. await popup.click('.m-tabs a:nth-of-type(1)')
  177. // select the first theme
  178. await popup.select('.m-panel:nth-of-type(1) select', 'a custom theme')
  179. t.equal(
  180. await popup.evaluate(() =>
  181. state.theme.name
  182. ),
  183. 'a custom theme',
  184. 'custom theme should be selected'
  185. )
  186. await popup.reload()
  187. await popup.waitFor(300)
  188. t.equal(
  189. await popup.evaluate(() =>
  190. state.theme.name
  191. ),
  192. 'a custom theme',
  193. 'custom theme should be selected'
  194. )
  195. })
  196. it('theme should be added to the content', async () => {
  197. await content.goto('http://localhost:3000/correct-content-type')
  198. await content.bringToFront()
  199. await content.waitFor(300)
  200. t.equal(
  201. await content.evaluate(() =>
  202. document.querySelector('#_theme').getAttribute('href')
  203. ),
  204. 'file:///hey',
  205. 'custom theme should be embedded'
  206. )
  207. })
  208. })
  209. describe('update url', () => {
  210. before(async () => {
  211. // advanced
  212. await advanced.bringToFront()
  213. // add theme
  214. await advanced.evaluate(() => {
  215. document.querySelector('.m-add-theme [placeholder=Name]').value = 'a custom theme'
  216. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  217. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'file:///hey'
  218. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  219. document.querySelector('.m-add-theme button').click()
  220. })
  221. // popup
  222. await popup.bringToFront()
  223. await popup.reload()
  224. // theme tab
  225. await popup.click('.m-tabs a:nth-of-type(1)')
  226. // select the first theme
  227. await popup.select('.m-panel:nth-of-type(1) select', 'a custom theme')
  228. })
  229. it('update custom theme url', async () => {
  230. // advanced
  231. await advanced.bringToFront()
  232. // expand theme
  233. if (!await advanced.evaluate(() => document.querySelector('.m-themes .m-list li:nth-of-type(1)').classList.contains('m-expanded'))) {
  234. await advanced.click('.m-themes .m-list li:nth-of-type(1)')
  235. }
  236. // update theme
  237. await advanced.evaluate(() => {
  238. document.querySelector('.m-themes .m-option:nth-of-type(2) input').value = 'file:///hi'
  239. document.querySelector('.m-themes .m-option:nth-of-type(2) input').dispatchEvent(new Event('keyup'))
  240. })
  241. // there is debounce timeout of 750ms in the options UI
  242. await advanced.waitFor(800)
  243. // reload
  244. await advanced.reload()
  245. await advanced.waitFor(300)
  246. t.equal(
  247. await advanced.evaluate(() =>
  248. document.querySelector('.m-themes .m-option:nth-of-type(2) input').value
  249. ),
  250. 'file:///hi',
  251. 'the custom theme URL should be updated'
  252. )
  253. })
  254. it('check content', async () => {
  255. await content.goto('http://localhost:3000/correct-content-type')
  256. await content.bringToFront()
  257. await content.waitFor(300)
  258. t.equal(
  259. await content.evaluate(() =>
  260. document.querySelector('#_theme').getAttribute('href')
  261. ),
  262. 'file:///hi',
  263. 'custom theme url should be updated'
  264. )
  265. })
  266. })
  267. describe('update name', () => {
  268. before(async () => {
  269. // advanced
  270. await advanced.bringToFront()
  271. // add theme
  272. await advanced.evaluate(() => {
  273. document.querySelector('.m-add-theme [placeholder=Name]').value = 'a custom theme'
  274. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  275. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'file:///hey'
  276. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  277. document.querySelector('.m-add-theme button').click()
  278. })
  279. // popup
  280. await popup.bringToFront()
  281. await popup.reload()
  282. // theme tab
  283. await popup.click('.m-tabs a:nth-of-type(1)')
  284. // select the first theme
  285. await popup.select('.m-panel:nth-of-type(1) select', 'a custom theme')
  286. // advanced
  287. await advanced.bringToFront()
  288. // expand theme
  289. if (!await advanced.evaluate(() => document.querySelector('.m-themes .m-list li:nth-of-type(1)').classList.contains('m-expanded'))) {
  290. await advanced.click('.m-themes .m-list li:nth-of-type(1)')
  291. }
  292. })
  293. it('update custom theme name', async () => {
  294. // update theme
  295. await advanced.evaluate(() => {
  296. document.querySelector('.m-themes .m-option:nth-of-type(1) input').value = 'a very custom theme'
  297. document.querySelector('.m-themes .m-option:nth-of-type(1) input').dispatchEvent(new Event('keyup'))
  298. })
  299. // there is debounce timeout of 750ms in the options UI
  300. await advanced.waitFor(800)
  301. t.equal(
  302. await advanced.evaluate(() =>
  303. document.querySelector('.m-themes .m-list .m-title').innerText
  304. ),
  305. 'a very custom theme',
  306. 'the custom theme name should be updated in the list title'
  307. )
  308. // reload
  309. await advanced.reload()
  310. await advanced.waitFor(300)
  311. t.equal(
  312. await advanced.evaluate(() =>
  313. document.querySelector('.m-themes .m-list .m-title').innerText
  314. ),
  315. 'a very custom theme',
  316. 'the custom theme name should be updated in the list title'
  317. )
  318. t.equal(
  319. await advanced.evaluate(() =>
  320. document.querySelector('.m-themes .m-option:nth-of-type(1) input').value
  321. ),
  322. 'a very custom theme',
  323. 'the custom theme name should be updated'
  324. )
  325. })
  326. it('check popup', async () => {
  327. // popup
  328. await popup.bringToFront()
  329. await popup.reload()
  330. // theme tab
  331. await popup.click('.m-tabs a:nth-of-type(1)')
  332. t.equal(
  333. await popup.evaluate(() =>
  334. document.querySelector('.m-panel:nth-of-type(1) select option').innerText
  335. ),
  336. 'a very custom theme',
  337. 'the custom theme should be updated'
  338. )
  339. })
  340. it('check content', async () => {
  341. await content.goto('http://localhost:3000/correct-content-type')
  342. await content.bringToFront()
  343. await content.waitFor(300)
  344. t.ok(
  345. /github\.css$/.test(
  346. await content.evaluate(() =>
  347. document.querySelector('#_theme').getAttribute('href')
  348. )
  349. ),
  350. 'defaults to github theme if the custom theme was active'
  351. )
  352. })
  353. })
  354. describe('remove', () => {
  355. before(async () => {
  356. // advanced
  357. await advanced.bringToFront()
  358. // add theme
  359. await advanced.evaluate(() => {
  360. document.querySelector('.m-add-theme [placeholder=Name]').value = 'a custom theme'
  361. document.querySelector('.m-add-theme [placeholder=Name]').dispatchEvent(new Event('change'))
  362. document.querySelector('.m-add-theme [placeholder~=URL]').value = 'file:///hey'
  363. document.querySelector('.m-add-theme [placeholder~=URL]').dispatchEvent(new Event('change'))
  364. document.querySelector('.m-add-theme button').click()
  365. })
  366. // advanced
  367. await advanced.bringToFront()
  368. // expand theme
  369. if (!await advanced.evaluate(() => document.querySelector('.m-themes .m-list li:nth-of-type(1)').classList.contains('m-expanded'))) {
  370. await advanced.click('.m-themes .m-list li:nth-of-type(1)')
  371. }
  372. })
  373. it('remove custom theme', async () => {
  374. // remove
  375. await advanced.evaluate(() => {
  376. document.querySelector('.m-themes .m-list button').click()
  377. })
  378. t.equal(
  379. await advanced.evaluate(() => {
  380. document.querySelector('.m-themes .m-list')
  381. }),
  382. null,
  383. 'should not have any themes'
  384. )
  385. })
  386. })
  387. }