workflow-tests.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import assert from 'assert';
  2. import Archive from '../../../app/archive';
  3. import FileSender from '../../../app/fileSender';
  4. import FileReceiver from '../../../app/fileReceiver';
  5. const headless = /Headless/.test(navigator.userAgent);
  6. // TODO: save on headless doesn't work as it used to since it now
  7. // follows a link instead of fetch. Maybe there's a way to make it
  8. // work? For now always set noSave.
  9. const options = { noSave: true || !headless, stream: true }; // only run the saveFile code if headless
  10. // FileSender uses a File in real life but a Blob works for testing
  11. const blob = new Blob([new ArrayBuffer(1024 * 128)], { type: 'text/plain' });
  12. blob.name = 'test.txt';
  13. const archive = new Archive([blob]);
  14. navigator.serviceWorker.register('/serviceWorker.js');
  15. describe('Upload / Download flow', function() {
  16. this.timeout(0);
  17. it('can only download once by default', async function() {
  18. const fs = new FileSender();
  19. const file = await fs.upload(archive);
  20. const fr = new FileReceiver({
  21. secretKey: file.toJSON().secretKey,
  22. id: file.id,
  23. nonce: file.keychain.nonce,
  24. requiresPassword: false
  25. });
  26. await fr.getMetadata();
  27. await fr.download(options);
  28. try {
  29. await fr.download(options);
  30. assert.fail('downloaded again');
  31. } catch (e) {
  32. assert.equal(e.message, '404');
  33. }
  34. });
  35. it('downloads with the correct password', async function() {
  36. const fs = new FileSender();
  37. const file = await fs.upload(archive);
  38. await file.setPassword('magic');
  39. const fr = new FileReceiver({
  40. secretKey: file.toJSON().secretKey,
  41. id: file.id,
  42. url: file.url,
  43. nonce: file.keychain.nonce,
  44. requiresPassword: true,
  45. password: 'magic'
  46. });
  47. await fr.getMetadata();
  48. await fr.download(options);
  49. assert.equal(fr.state, 'complete');
  50. });
  51. it('blocks invalid passwords from downloading', async function() {
  52. const fs = new FileSender();
  53. const file = await fs.upload(archive);
  54. await file.setPassword('magic');
  55. const fr = new FileReceiver({
  56. secretKey: file.toJSON().secretKey,
  57. id: file.id,
  58. url: file.url,
  59. nonce: file.keychain.nonce,
  60. requiresPassword: true,
  61. password: 'password'
  62. });
  63. try {
  64. await fr.getMetadata();
  65. assert.fail('got metadata with bad password');
  66. } catch (e) {
  67. assert.equal(e.message, '401');
  68. }
  69. try {
  70. // We can't decrypt without IV from metadata
  71. // but let's try to download anyway
  72. await fr.download(options);
  73. assert.fail('downloaded file with bad password');
  74. } catch (e) {
  75. assert.equal(e.message, '401');
  76. }
  77. });
  78. it('retries a bad nonce', async function() {
  79. const fs = new FileSender();
  80. const file = await fs.upload(archive);
  81. const fr = new FileReceiver({
  82. secretKey: file.toJSON().secretKey,
  83. id: file.id,
  84. nonce: null, // oops
  85. requiresPassword: false
  86. });
  87. await fr.getMetadata();
  88. assert.equal(fr.fileInfo.name, archive.name);
  89. });
  90. it('can cancel the upload', async function() {
  91. const fs = new FileSender();
  92. const up = fs.upload(archive);
  93. fs.cancel(); // before encrypting
  94. try {
  95. await up;
  96. assert.fail('not cancelled 1');
  97. } catch (e) {
  98. assert.equal(e.message, '0');
  99. }
  100. fs.reset();
  101. fs.once('encrypting', () => fs.cancel());
  102. try {
  103. await fs.upload(archive);
  104. assert.fail('not cancelled 2');
  105. } catch (e) {
  106. assert.equal(e.message, '0');
  107. }
  108. fs.reset();
  109. fs.once('progress', () => fs.cancel());
  110. try {
  111. await fs.upload(archive);
  112. assert.fail('not cancelled 3');
  113. } catch (e) {
  114. assert.equal(e.message, '0');
  115. }
  116. });
  117. it('can cancel the download', async function() {
  118. const fs = new FileSender();
  119. const file = await fs.upload(archive);
  120. const fr = new FileReceiver({
  121. secretKey: file.toJSON().secretKey,
  122. id: file.id,
  123. nonce: file.keychain.nonce,
  124. requiresPassword: false
  125. });
  126. await fr.getMetadata();
  127. fr.once('progress', () => fr.cancel());
  128. try {
  129. await fr.download(options);
  130. assert.fail('not cancelled');
  131. } catch (e) {
  132. assert.equal(e.message, '0');
  133. }
  134. });
  135. it('can increase download count on download', async function() {
  136. this.timeout(0);
  137. const fs = new FileSender();
  138. const file = await fs.upload(archive);
  139. const fr = new FileReceiver({
  140. secretKey: file.toJSON().secretKey,
  141. id: file.id,
  142. nonce: file.keychain.nonce,
  143. requiresPassword: false
  144. });
  145. await fr.getMetadata();
  146. await fr.download(options);
  147. await file.updateDownloadCount();
  148. assert.equal(file.dtotal, 1);
  149. });
  150. it('does not increase download count when download cancelled', async function() {
  151. const fs = new FileSender();
  152. const file = await fs.upload(archive);
  153. const fr = new FileReceiver({
  154. secretKey: file.toJSON().secretKey,
  155. id: file.id,
  156. nonce: file.keychain.nonce,
  157. requiresPassword: false
  158. });
  159. await fr.getMetadata();
  160. fr.once('progress', () => fr.cancel());
  161. try {
  162. await fr.download(options);
  163. assert.fail('not cancelled');
  164. } catch (e) {
  165. await file.updateDownloadCount();
  166. assert.equal(file.dtotal, 0);
  167. }
  168. });
  169. it('can allow multiple downloads', async function() {
  170. const fs = new FileSender();
  171. const a = new Archive([blob]);
  172. a.dlimit = 2;
  173. const file = await fs.upload(a);
  174. const fr = new FileReceiver({
  175. secretKey: file.toJSON().secretKey,
  176. id: file.id,
  177. nonce: file.keychain.nonce,
  178. requiresPassword: false
  179. });
  180. await fr.getMetadata();
  181. await fr.download(options);
  182. await file.updateDownloadCount();
  183. assert.equal(file.dtotal, 1);
  184. await fr.download(options);
  185. await file.updateDownloadCount();
  186. assert.equal(file.dtotal, 2);
  187. try {
  188. await fr.download(options);
  189. assert.fail('downloaded too many times');
  190. } catch (e) {
  191. assert.equal(e.message, '404');
  192. }
  193. });
  194. it('can delete the file before download', async function() {
  195. const fs = new FileSender();
  196. const file = await fs.upload(archive);
  197. const fr = new FileReceiver({
  198. secretKey: file.toJSON().secretKey,
  199. id: file.id,
  200. nonce: file.keychain.nonce,
  201. requiresPassword: false
  202. });
  203. await file.del();
  204. try {
  205. await fr.getMetadata();
  206. assert.fail('file still exists');
  207. } catch (e) {
  208. assert.equal(e.message, '404');
  209. }
  210. });
  211. });