-
-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replay progress events in unit tests (#1017)
Skips the browser, http, network etc. and lets us test the smallest unit of our internals – an UploadFile having its state updated by a series of ProgressEvent events. For each scenario I'm pretty sure we only need to test a single file with a stream of synchronous events. Covers some recorded events from different browsers and endpoints. We can add more scenarios here if we come across them. Specifically, the Chrome scenario proves the fix in #1016 – this was previously failing early with 100% progress, which is the same issue reported by users in #1013 I've painstakingly copied values from log screenshots to setup this existing suite. Hopefully contributors can PR full tests in future to make things a bit easier 😅 Fixes #1013
- Loading branch information
Showing
3 changed files
with
326 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,14 @@ | ||
import DataTransferWrapper from './system/data-transfer-wrapper.ts'; | ||
import HTTPRequest from './system/http-request.ts'; | ||
import UploadFileReader from './system/upload-file-reader.ts'; | ||
import { onloadstart, onprogress, onloadend } from './system/upload.ts'; | ||
|
||
export { | ||
// Non-public classes imported by the test app | ||
DataTransferWrapper, | ||
HTTPRequest, | ||
UploadFileReader, | ||
onloadstart, | ||
onprogress, | ||
onloadend, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
/* eslint-disable qunit/no-conditional-assertions */ | ||
|
||
import { module, test } from 'qunit'; | ||
import { setupTest } from 'ember-qunit'; | ||
import { FileSource, UploadFile } from 'ember-file-upload'; | ||
import { type TestContext } from '@ember/test-helpers'; | ||
import { png } from 'test-app/tests/utils/file-data'; | ||
import { onloadstart, onprogress, onloadend } from 'ember-file-upload/internal'; | ||
|
||
interface Handlers { | ||
[key: string]: typeof onloadstart; | ||
} | ||
|
||
const handlers: Handlers = { | ||
loadstart: onloadstart, | ||
progress: onprogress, | ||
loadend: onloadend, | ||
}; | ||
|
||
type Step = { | ||
assertProgressBefore?: number; | ||
event: ProgressEvent; | ||
assertProgressAfter?: number; | ||
}; | ||
|
||
const replayEvents = ( | ||
assert: Assert, | ||
uploadFile: UploadFile, | ||
steps: Step[], | ||
) => { | ||
for (const step of steps) { | ||
if (typeof step.assertProgressBefore === 'number') { | ||
assert.strictEqual( | ||
uploadFile.progress, | ||
step.assertProgressBefore, | ||
`before (index: ${steps.indexOf(step)}), progress is: ${ | ||
step.assertProgressBefore | ||
}% type: ${step.event.type}, total: ${step.event.total}, loaded: ${ | ||
step.event.loaded | ||
}`, | ||
); | ||
} | ||
|
||
const handler = handlers[step.event.type]; | ||
if (!handler) throw new Error(`No handler matched ${step.event.type}`); | ||
|
||
handler(uploadFile, step.event); | ||
|
||
if (typeof step.assertProgressAfter === 'number') { | ||
assert.strictEqual( | ||
uploadFile.progress, | ||
step.assertProgressAfter, | ||
`after (index: ${steps.indexOf(step)}), progress is: ${ | ||
step.assertProgressAfter | ||
}% type: ${step.event.type}, total: ${step.event.total}, loaded: ${ | ||
step.event.loaded | ||
}`, | ||
); | ||
} | ||
} | ||
}; | ||
|
||
module('Unit | upload progress', function (hooks) { | ||
setupTest(hooks); | ||
|
||
test('nominal progress (recorded from Firefox in issue #1002)', function (this: TestContext, assert) { | ||
const uploadFile = new UploadFile( | ||
new File(png, 'test-filename.png'), | ||
FileSource.Browse, | ||
); | ||
|
||
const steps = [ | ||
{ | ||
assertProgressBefore: 0, | ||
event: new ProgressEvent('loadstart', { | ||
lengthComputable: true, | ||
loaded: 0, | ||
total: 0, | ||
}), | ||
}, | ||
{ | ||
event: new ProgressEvent('loadstart', { | ||
lengthComputable: true, | ||
loaded: 0, | ||
total: 618220, | ||
}), | ||
assertProgressAfter: 0, | ||
}, | ||
{ | ||
assertProgressBefore: 0, | ||
event: new ProgressEvent('progress', { | ||
lengthComputable: true, | ||
loaded: 30954, | ||
total: 618220, | ||
}), | ||
assertProgressAfter: 5.0069554527514475, | ||
}, | ||
{ | ||
event: new ProgressEvent('progress', { | ||
lengthComputable: true, | ||
loaded: 62954, | ||
total: 618220, | ||
}), | ||
assertProgressAfter: 10.18310633754974, | ||
}, | ||
]; | ||
|
||
replayEvents(assert, uploadFile, steps); | ||
|
||
assert.strictEqual( | ||
uploadFile.size, | ||
618220, | ||
'upload filesize is set from handlers', | ||
); | ||
}); | ||
|
||
test('regression: content length of final `progress` and `loadend` is less than file size (Issue #1002)', function (this: TestContext, assert) { | ||
const uploadFile = new UploadFile( | ||
new File(png, 'test-filename.png'), | ||
FileSource.Browse, | ||
); | ||
|
||
const steps = [ | ||
{ | ||
assertProgressBefore: 0, | ||
event: new ProgressEvent('progress', { | ||
lengthComputable: true, | ||
loaded: 248723, | ||
total: 248723, | ||
}), | ||
assertProgressAfter: 100, | ||
}, | ||
{ | ||
assertProgressBefore: 100, | ||
event: new ProgressEvent('loadend', { | ||
lengthComputable: true, | ||
loaded: 248723, | ||
total: 248723, | ||
}), | ||
assertProgressAfter: 100, | ||
}, | ||
{ | ||
assertProgressBefore: 100, | ||
event: new ProgressEvent('progress', { | ||
lengthComputable: true, | ||
loaded: 390, | ||
total: 390, | ||
}), | ||
assertProgressAfter: 100, | ||
}, | ||
{ | ||
assertProgressBefore: 100, | ||
event: new ProgressEvent('loadend', { | ||
lengthComputable: true, | ||
loaded: 390, | ||
total: 390, | ||
}), | ||
assertProgressAfter: 100, | ||
}, | ||
]; | ||
|
||
replayEvents(assert, uploadFile, steps); | ||
|
||
assert.strictEqual( | ||
uploadFile.size, | ||
248723, | ||
'upload filesize is set from handlers', | ||
); | ||
}); | ||
|
||
test('regression: incorrect `total` in second `loadstart` event (recorded from Google Chrome in issue #1002)', function (this: TestContext, assert) { | ||
const uploadFile = new UploadFile( | ||
new File(png, 'test-filename.png'), | ||
FileSource.Browse, | ||
); | ||
|
||
const steps = [ | ||
{ | ||
assertProgressBefore: 0, | ||
event: new ProgressEvent('loadstart', { | ||
lengthComputable: true, | ||
loaded: 0, | ||
total: 0, | ||
}), | ||
}, | ||
{ | ||
event: new ProgressEvent('loadstart', { | ||
lengthComputable: true, | ||
loaded: 0, | ||
total: 712, | ||
}), | ||
}, | ||
{ | ||
assertProgressBefore: 0, | ||
event: new ProgressEvent('progress', { | ||
lengthComputable: true, | ||
loaded: 16384, | ||
total: 618122, | ||
}), | ||
assertProgressAfter: 2.6506094266180464, | ||
}, | ||
{ | ||
event: new ProgressEvent('progress', { | ||
lengthComputable: true, | ||
loaded: 32768, | ||
total: 618122, | ||
}), | ||
assertProgressAfter: 5.301218853236093, | ||
}, | ||
]; | ||
|
||
replayEvents(assert, uploadFile, steps); | ||
|
||
assert.strictEqual( | ||
uploadFile.size, | ||
618122, | ||
'upload filesize is set from handlers', | ||
); | ||
}); | ||
|
||
test('final response has `Content-Length: 0` (loadend with total: 0)', function (this: TestContext, assert) { | ||
const uploadFile = new UploadFile( | ||
new File(png, 'test-filename.png'), | ||
FileSource.Browse, | ||
); | ||
|
||
const steps = [ | ||
{ | ||
assertProgressBefore: 0, | ||
event: new ProgressEvent('loadstart', { | ||
lengthComputable: true, | ||
loaded: 0, | ||
total: 0, | ||
}), | ||
}, | ||
{ | ||
event: new ProgressEvent('loadstart', { | ||
lengthComputable: true, | ||
loaded: 0, | ||
total: 618220, | ||
}), | ||
}, | ||
{ | ||
event: new ProgressEvent('progress', { | ||
lengthComputable: true, | ||
loaded: 618220, | ||
total: 618220, | ||
}), | ||
assertProgressAfter: 100, | ||
}, | ||
{ | ||
event: new ProgressEvent('loadend', { | ||
lengthComputable: true, | ||
loaded: 0, | ||
total: 0, | ||
}), | ||
assertProgressAfter: 100, | ||
}, | ||
]; | ||
|
||
replayEvents(assert, uploadFile, steps); | ||
|
||
assert.strictEqual( | ||
uploadFile.size, | ||
618220, | ||
'upload filesize is set from handlers', | ||
); | ||
}); | ||
}); |