workflow-tests.js 6.4 KB

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