List.test.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. import { ConsoleMessage, ElementHandle } from 'puppeteer';
  2. import {
  3. isLightboxClosed,
  4. isPageReady,
  5. isLightboxShown,
  6. expectToastShown,
  7. isElementGone,
  8. isElementThere,
  9. } from '../lib/isReady';
  10. import trailingSlash from '../../src/lib/trailingSlash';
  11. import * as fs from 'fs';
  12. const BASE_URL = process.env.BASE_URL ?? 'http://localhost:8080/',
  13. DESTINATION_FONT_FILE = '/tmp/BlackAndWhitePicture-Regular.ttf';
  14. if (process.argv.some((flag) => flag.match(/-debug/))) {
  15. page.on('console', (message: ConsoleMessage): void => {
  16. if (message.type() === 'error') {
  17. console.error(message.text());
  18. const trace = message.stackTrace();
  19. if (trace.length) {
  20. console.error(
  21. [
  22. `Stack trace:`,
  23. ...trace.map(
  24. (message): string =>
  25. message.url +
  26. ' (' +
  27. message.lineNumber +
  28. ':' +
  29. message.columnNumber +
  30. ')'
  31. ),
  32. ].join('\n')
  33. );
  34. }
  35. return;
  36. }
  37. if (message.type() === 'warning') {
  38. console.warn(message.text());
  39. return;
  40. }
  41. if (message.type() === 'info') {
  42. console.info(message.text());
  43. return;
  44. }
  45. console.log(message.text());
  46. });
  47. }
  48. describe('WebDAV.js', () => {
  49. describe('List', () => {
  50. it('should be possible to preview items', async () => {
  51. // Wait for page JS to replace page contents
  52. await isPageReady(page, BASE_URL);
  53. await (
  54. [
  55. [
  56. '[data-full-path="/0.jpg"]',
  57. async (lightbox: ElementHandle) => {
  58. await expect(await lightbox.$('img')).toBeTruthy();
  59. },
  60. ],
  61. [
  62. '[data-full-path="/BlackAndWhitePicture-Regular.ttf"]',
  63. async (lightbox: ElementHandle) => {
  64. await expect(await lightbox.$('img')).toBeFalsy();
  65. await expect(await lightbox.$$('style')).toHaveLength(1);
  66. await expect(await lightbox.$$('h1')).toHaveLength(1);
  67. await expect(await lightbox.$$('p')).toHaveLength(4);
  68. },
  69. ],
  70. [
  71. '[data-full-path="/dummy.pdf"]',
  72. async (lightbox: ElementHandle) => {
  73. await expect(await lightbox.$('iframe')).toBeTruthy();
  74. },
  75. ],
  76. [
  77. '[data-full-path="/style.css"]',
  78. async (lightbox: ElementHandle) => {
  79. await expect(await lightbox.$('pre.language-css')).toBeTruthy();
  80. },
  81. ],
  82. [
  83. '[data-full-path="/video.mp4"]',
  84. async (lightbox: ElementHandle) => {
  85. await expect(await lightbox.$('video[autoplay]')).toBeTruthy();
  86. },
  87. ],
  88. ] as [string, (lightbox: ElementHandle) => Promise<void>][]
  89. ).reduce(
  90. async (
  91. previous: Promise<void>,
  92. [selector, expectation]
  93. ): Promise<void> => {
  94. await previous;
  95. await page.click(selector);
  96. await expectation(await isLightboxShown(page));
  97. await isLightboxClosed(page);
  98. await page.waitForTimeout(500);
  99. },
  100. Promise.resolve(null)
  101. );
  102. });
  103. it('should be possible to create a new navigable directory, rename it and delete it', async () => {
  104. await isPageReady(page, BASE_URL);
  105. page.once(
  106. 'dialog',
  107. async (dialog) => await dialog.accept('new-directory')
  108. );
  109. await page.click('.create-directory');
  110. await isElementThere(page, '[data-full-path="/new-directory/"]');
  111. await expectToastShown(
  112. page,
  113. `'new-directory' has been created.`,
  114. 'success'
  115. );
  116. await page.click('[data-full-path="/new-directory/"]');
  117. await page.waitForTimeout(200);
  118. await expect(await page.$$('main ul li')).toHaveLength(1);
  119. await expect(await page.$('[data-full-path="/"]')).toBeTruthy();
  120. await page.click('[data-full-path="/"]');
  121. await page.waitForTimeout(200);
  122. await expect(await page.$$('main ul li')).toHaveLength(24);
  123. await page.click('[data-full-path="/new-directory/"] .rename');
  124. await page.waitForFunction(() =>
  125. document.activeElement.matches(
  126. '[data-full-path="/new-directory/"] input[type="text"]'
  127. )
  128. );
  129. await page.keyboard.down('Control');
  130. await page.keyboard.press('Backspace');
  131. await page.keyboard.up('Control');
  132. await page.type(
  133. '[data-full-path="/new-directory/"] input[type="text"]',
  134. 'folder'
  135. );
  136. await page.keyboard.press('Enter');
  137. await expectToastShown(
  138. page,
  139. `'new-directory' successfully renamed to 'new-folder'.`,
  140. 'success'
  141. );
  142. await isElementThere(page, '[data-full-path="/new-folder/"]');
  143. page.once('dialog', async (dialog) => await dialog.accept());
  144. await page.click('[data-full-path="/new-folder/"] .delete');
  145. await isElementGone(page, '[data-full-path="/new-folder/"]');
  146. await expectToastShown(page, `'new-folder' has been deleted.`, 'success');
  147. });
  148. it('should show expected errors', async () => {
  149. await isPageReady(page, BASE_URL);
  150. await page.click('[data-full-path="/inaccessible-dir/"]');
  151. await expectToastShown(
  152. page,
  153. `HEAD ${trailingSlash(
  154. BASE_URL
  155. )}inaccessible-dir/ failed: Forbidden (403)`,
  156. 'error'
  157. );
  158. await page.click('[data-full-path="/inaccessible-file"]');
  159. await expectToastShown(
  160. page,
  161. `HEAD ${trailingSlash(
  162. BASE_URL
  163. )}inaccessible-file failed: Forbidden (403)`,
  164. 'error'
  165. );
  166. await page.click('[data-full-path="/inaccessible-image.jpg"]');
  167. await expectToastShown(
  168. page,
  169. `HEAD ${trailingSlash(
  170. BASE_URL
  171. )}inaccessible-image.jpg failed: Forbidden (403)`,
  172. 'error'
  173. );
  174. await page.click('[data-full-path="/inaccessible-text-file.txt"]');
  175. await expectToastShown(
  176. page,
  177. `HEAD ${trailingSlash(
  178. BASE_URL
  179. )}inaccessible-text-file.txt failed: Forbidden (403)`,
  180. 'error'
  181. );
  182. });
  183. it('should be possible to download a file', async () => {
  184. await isPageReady(page, BASE_URL);
  185. await expect(() => fs.accessSync(DESTINATION_FONT_FILE)).toThrow();
  186. await page
  187. .target()
  188. .createCDPSession()
  189. .then((client) =>
  190. client.send('Page.setDownloadBehavior', {
  191. behavior: 'allow',
  192. downloadPath: '/tmp',
  193. })
  194. );
  195. await page.click(
  196. '[data-full-path="/BlackAndWhitePicture-Regular.ttf"] [download]'
  197. );
  198. // wait for the file to download
  199. await page.waitForTimeout(400);
  200. await expect(() => fs.accessSync(DESTINATION_FONT_FILE)).not.toThrow();
  201. fs.rmSync(DESTINATION_FONT_FILE);
  202. });
  203. it('should be possible to upload a file', async () => {
  204. await isPageReady(page, BASE_URL);
  205. const elementHandle = (await page.$(
  206. 'input[type=file]'
  207. )) as ElementHandle<HTMLInputElement>;
  208. await elementHandle.uploadFile('./package.json');
  209. await expectToastShown(
  210. page,
  211. `'package.json' has been successfully uploaded.`,
  212. 'success'
  213. );
  214. await page.click('[data-full-path="/package.json"]');
  215. await page.once('dialog', async (dialog) => {
  216. await dialog.accept();
  217. });
  218. await page.click('[data-full-path="/package.json"] .delete');
  219. await isElementGone(page, '[data-full-path="/package.json"]');
  220. await expectToastShown(
  221. page,
  222. `'package.json' has been deleted.`,
  223. 'success'
  224. );
  225. });
  226. });
  227. beforeAll(async () => {
  228. try {
  229. fs.accessSync(DESTINATION_FONT_FILE);
  230. fs.rmSync(DESTINATION_FONT_FILE);
  231. } catch (e) {
  232. // we don't need to do anything here
  233. }
  234. });
  235. });