Repository: parse-community/Parse-SDK-JS
Pull request #1029 (2019-12-10 21:06:44)

Improve file upload progress
* Add support for wechat
* Add length of data downloaded
* Add length of total data

https://developers.weixin.qq.com/miniprogram/en/dev/api/network/download/DownloadTask.onProgressUpdate.html

https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent

@kartheeknagasuri Can you try this?

codecov[bot]: # [Codecov](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029?src=pr&el=h1) Report
> Merging [#1029](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029?src=pr&el=desc) into [master](https://codecov.io/gh/parse-community/Parse-SDK-JS/commit/272c4a8fcc1969e788064482514c3f267cbaec2a?src=pr&el=desc) will **increase** coverage by `0.08%`.
> The diff coverage is `80%`.

[![Impacted file tree graph](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029/graphs/tree.svg?width=650&token=8nCENM0QHj&height=150&src=pr)](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1029      +/-   ##
==========================================
+ Coverage   91.94%   92.03%   +0.08%     
==========================================
  Files          53       53              
  Lines        5118     5112       -6     
  Branches     1145     1142       -3     
==========================================
- Hits         4706     4705       -1     
+ Misses        412      407       -5
```


| [Impacted Files](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/RESTController.js](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029/diff?src=pr&el=tree#diff-c3JjL1JFU1RDb250cm9sbGVyLmpz) | `83.87% <80%> (+2.5%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029?src=pr&el=footer). Last update [272c4a8...b243793](https://codecov.io/gh/parse-community/Parse-SDK-JS/pull/1029?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/src/RESTController.js b/src/RESTController.js
index f02d17e..5e89bb7 100644
--- a/src/RESTController.js
+++ b/src/RESTController.js
@@ -167,28 +167,18 @@ const RESTController = {
       for (const key in customHeaders) {
         headers[key] = customHeaders[key];
       }
-      if(options && typeof options.progress === 'function') {
-        if (xhr.upload) {
-          xhr.upload.addEventListener('progress', (oEvent) => {
-            if (oEvent.lengthComputable) {
-              options.progress(oEvent.loaded / oEvent.total);
-            } else {
-              options.progress(null);
-            }
-          });
-        } else if (xhr.addEventListener) {
-          xhr.addEventListener('progress', (oEvent) => {
-            if (oEvent.lengthComputable) {
-              options.progress(oEvent.loaded / oEvent.total);
-            } else {
-              options.progress(null);
-            }
-          });
-        }
-      }
       xhr.onabort = () => {
         aborted = true;
       };
+      xhr.onprogress = (event) => {
+        if(options && typeof options.progress === 'function') {
+          if (event.lengthComputable) {
+            options.progress(event.loaded / event.total, event.loaded, event.total);
+          } else {
+            options.progress(null);
+          }
+        }
+      };
       xhr.open(method, url, true);
 
       for (const h in headers) {
diff --git a/src/Xhr.weapp.js b/src/Xhr.weapp.js
index e86be3f..ec6c204 100644
--- a/src/Xhr.weapp.js
+++ b/src/Xhr.weapp.js
@@ -16,6 +16,7 @@ module.exports = class XhrWeapp {
     this.method = '';
     this.url = '';
     this.onabort = () => {};
+    this.onprogress = () => {};
     this.onerror = () => {};
     this.onreadystatechange = () => {};
     this.requestTask = null;
@@ -72,6 +73,14 @@ module.exports = class XhrWeapp {
         this.requestTask = null;
         this.onerror(err);
       }
-    })
+    });
+    this.requestTask.onProgressUpdate((res) => {
+      const event = {
+        lengthComputable: (res.totalBytesExpectedToWrite !== 0),
+        loaded: res.totalBytesWritten,
+        total: res.totalBytesExpectedToWrite,
+      };
+      this.onprogress(event);
+    });
   }
 };


Test patch:
diff --git a/src/__tests__/RESTController-test.js b/src/__tests__/RESTController-test.js
index 1d68742..1b5fa9c 100644
--- a/src/__tests__/RESTController-test.js
+++ b/src/__tests__/RESTController-test.js
@@ -429,15 +429,11 @@ describe('RESTController', () => {
   });
 
   it('reports upload progress of the AJAX request when callback is provided', (done) => {
-    const xhr = mockXHR([{ status: 200, response: { success: true }}], {
-      addEventListener: (name, callback) => {
-        if(name === "progress") {
-          callback({
-            lengthComputable: true,
-            loaded: 5,
-            total: 10
-          });
-        }
+    const xhr = mockXHR([{ status: 200, response: { success: true } }], {
+      progress: {
+        lengthComputable: true,
+        loaded: 5,
+        total: 10
       }
     });
     RESTController._setXHR(xhr);
@@ -448,7 +444,30 @@ describe('RESTController', () => {
     jest.spyOn(options, 'progress');
 
     RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then(({ response, status }) => {
-      expect(options.progress).toHaveBeenCalledWith(0.5);
+      expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10);
+      expect(response).toEqual({ success: true });
+      expect(status).toBe(200);
+      done();
+    });
+  });
+
+  it('does not upload progress when total is uncomputable', (done) => {
+    const xhr = mockXHR([{ status: 200, response: { success: true } }], {
+      progress: {
+        lengthComputable: false,
+        loaded: 5,
+        total: 0
+      }
+    });
+    RESTController._setXHR(xhr);
+
+    const options = {
+      progress: function(){}
+    };
+    jest.spyOn(options, 'progress');
+
+    RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then(({ response, status }) => {
+      expect(options.progress).toHaveBeenCalledWith(null);
       expect(response).toEqual({ success: true });
       expect(status).toBe(200);
       done();
diff --git a/src/__tests__/test_helpers/mockXHR.js b/src/__tests__/test_helpers/mockXHR.js
index a144642..75ee661 100644
--- a/src/__tests__/test_helpers/mockXHR.js
+++ b/src/__tests__/test_helpers/mockXHR.js
@@ -16,7 +16,7 @@
  * alongside it.
  * `upload` can be provided to mock the XMLHttpRequest.upload property.
  */
-function mockXHR(results, upload) {
+function mockXHR(results, options = {}) {
   const XHR = function() { };
   let attempts = 0;
   XHR.prototype = {
@@ -28,8 +28,8 @@ function mockXHR(results, upload) {
       this.readyState = 4;
       attempts++;
       this.onreadystatechange();
-    },
-    upload: upload
+      this.onprogress(options.progress);
+    }
   };
   return XHR;
 }