Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9c3668e

Browse files
committedJan 15, 2025·
fix(request): added stats test and optimized stats
1 parent c8a50e8 commit 9c3668e

File tree

13 files changed

+239
-77
lines changed

13 files changed

+239
-77
lines changed
 

‎packages/mocks/Date.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { vi } from 'vitest';
2+
3+
export const mockDate = testScheduler => {
4+
const mockClassConstructor = vi.fn().mockReturnValue({
5+
method: vi.fn()
6+
});
7+
8+
return {
9+
/**
10+
* Here, we're assigning properties to the mock function we made above
11+
*/
12+
Date: Object.assign(mockClassConstructor, {
13+
/**
14+
* This the mock for the static method. Replace "staticMethod" with the
15+
* name of the method you're mocking.
16+
*/
17+
now: vi.fn()
18+
})
19+
};
20+
};

‎packages/mocks/blob.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,5 @@ import { vi } from 'vitest';
33
import { mockAsync } from './async';
44

55
export const mockBlob = () => {
6-
return vi.fn(([e], type) => ({
7-
text: () => mockAsync(new TextDecoder().decode(e)),
8-
type
9-
}));
6+
return vi.fn(([e], type) => ({ text: () => mockAsync(new TextDecoder().decode(e)), type }));
107
};

‎packages/mocks/readableStream.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { vi } from 'vitest';
2+
3+
import { mockAsync } from './async';
4+
5+
export const mockReadableStream = () => {
6+
return vi.fn(([e], type) => ({ text: () => mockAsync(new TextDecoder().decode(e)), type }));
7+
};

‎packages/operators/src/request.test.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { test, describe, beforeEach, expect, vi, afterAll, beforeAll } from 'vit
99

1010
import { log, logResult } from './log.js';
1111
import { resolveBlob, resolveJSON } from './response.js';
12+
import ElapsedTime from './stream/stats/ElapsedTime.js';
1213
import EstimateTime from './stream/stats/EstimateTime.js';
1314
import Progress from './stream/stats/Progress.js';
1415
import TransferRate from './stream/stats/TransferRate.js';
@@ -214,6 +215,9 @@ describe('test', () => {
214215
const estimateTime = EstimateTime.create(SECOND);
215216
estimateTime.subscribe({ next: e => console.log('ESTIMATE', e) });
216217

218+
const elapsedTime = ElapsedTime.create(SECOND);
219+
elapsedTime.subscribe({ next: e => console.log('ELAPSED', e) });
220+
217221
const fileMap = {
218222
VIDEO_170MB:
219223
'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
@@ -229,7 +233,7 @@ describe('test', () => {
229233

230234
const value = await lastValueFrom(
231235
of(req).pipe(
232-
request({ stats: { download: [progress, byteRate, estimateTime] } }),
236+
request({ stats: { download: [progress, byteRate, estimateTime, elapsedTime] } }),
233237
resolveBlob()
234238
//
235239
)

‎packages/operators/src/stream/bypassStream.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const interceptStream = (reworkers, chunkSize) => {
4646
if (done) {
4747
return onStreamEnd(controller, reworkers);
4848
}
49-
await onStreamPull(controller, reworkers, value, total, Date.now() - this.time);
49+
await onStreamPull(controller, reworkers, value, total, this.time);
5050
} catch (err) {
5151
onStreamError(err);
5252
throw err;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { mockBlob } from '#mocks/blob.js';
2+
import { mockResponse } from '#mocks/response.js';
3+
import fs from 'node:fs';
4+
import { of, Subject } from 'rxjs';
5+
import { TestScheduler } from 'rxjs/testing';
6+
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
7+
8+
import { bypassStream } from './bypassStream';
9+
10+
describe('bypass stream', () => {
11+
let testScheduler;
12+
13+
beforeAll(() => {
14+
vi.spyOn(global, 'Blob').mockImplementation(mockBlob());
15+
vi.spyOn(global, 'Response').mockImplementation(mockResponse());
16+
});
17+
18+
beforeEach(() => {
19+
testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected));
20+
});
21+
22+
test('bypass response stream', async () => {
23+
const blob = new Blob(
24+
[fs.readFileSync(`${__dirname}/../../fixtures/videos/demo.mp4`)],
25+
'video/mp4'
26+
);
27+
28+
const bypass = new Subject();
29+
30+
const triggerVal = {
31+
a: new Response(blob, { status: 200 })
32+
};
33+
34+
// testScheduler.run(({ cold, expectObservable }) => {
35+
// expectObservable(bypass).toBe('a');
36+
// expectObservable(cold('a|', triggerVal).pipe(bypassStream([bypass])));
37+
// });
38+
});
39+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { map, Subject } from 'rxjs';
2+
3+
import { calcReceivedStats, MSECOND } from './utils';
4+
5+
export default {
6+
create: (timeUnit = MSECOND) => {
7+
return new Subject().pipe(calcReceivedStats(), calcElapsedTime(timeUnit));
8+
}
9+
};
10+
11+
const calcElapsedTime = timeRatio => {
12+
return source => source.pipe(map(({ period }) => period / timeRatio));
13+
};
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { tap } from 'rxjs';
2+
import { TestScheduler } from 'rxjs/testing';
3+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
4+
5+
import ElapsedTime from './ElapsedTime';
6+
import { SECOND } from './utils';
7+
8+
describe('ElapsedTime', () => {
9+
let testScheduler;
10+
11+
beforeEach(() => {
12+
testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected));
13+
14+
vi.spyOn(global.Date, 'now').mockImplementation(() => testScheduler.now());
15+
});
16+
17+
afterEach(() => {
18+
vi.restoreAllMocks();
19+
});
20+
21+
test('calc estimate time - millisecond', async () => {
22+
const time = Date.now();
23+
24+
const triggerVal = {
25+
a: { value: new TextEncoder().encode('abc'), total: 26, period: time },
26+
b: { value: new TextEncoder().encode('def'), total: 26, period: time },
27+
c: { value: new TextEncoder().encode('ghi'), total: 26, period: time },
28+
d: { value: new TextEncoder().encode('jkl'), total: 26, period: time },
29+
e: { value: new TextEncoder().encode('mno'), total: 26, period: time },
30+
f: { value: new TextEncoder().encode('pqr'), total: 26, period: time },
31+
g: { value: new TextEncoder().encode('stu'), total: 26, period: time },
32+
h: { value: new TextEncoder().encode('vwx'), total: 26, period: time },
33+
i: { value: new TextEncoder().encode('yz'), total: 26, period: time }
34+
};
35+
36+
const expectedVal = {
37+
a: 0,
38+
b: 2,
39+
c: 4,
40+
d: 6,
41+
e: 8,
42+
f: 10,
43+
g: 12,
44+
h: 14,
45+
i: 16
46+
};
47+
48+
const elapsedTime = ElapsedTime.create();
49+
50+
testScheduler.run(({ cold, expectObservable }) => {
51+
expectObservable(elapsedTime).toBe('a-b-c-d-e-f-g-h-i|', expectedVal);
52+
expectObservable(cold('a-b-c-d-e-f-g-h-i|', triggerVal).pipe(tap(elapsedTime)));
53+
});
54+
});
55+
56+
test('calc estimate time - second', async () => {
57+
const time = Date.now();
58+
59+
const triggerVal = {
60+
a: { value: new TextEncoder().encode('abc'), total: 26, period: time },
61+
b: { value: new TextEncoder().encode('def'), total: 26, period: time },
62+
c: { value: new TextEncoder().encode('ghi'), total: 26, period: time },
63+
d: { value: new TextEncoder().encode('jkl'), total: 26, period: time },
64+
e: { value: new TextEncoder().encode('mno'), total: 26, period: time },
65+
f: { value: new TextEncoder().encode('pqr'), total: 26, period: time },
66+
g: { value: new TextEncoder().encode('stu'), total: 26, period: time },
67+
h: { value: new TextEncoder().encode('vwx'), total: 26, period: time },
68+
i: { value: new TextEncoder().encode('yz'), total: 26, period: time }
69+
};
70+
71+
const expectedVal = {
72+
a: 0.0,
73+
b: 0.002,
74+
c: 0.004,
75+
d: 0.006,
76+
e: 0.008,
77+
f: 0.01,
78+
g: 0.012,
79+
h: 0.014,
80+
i: 0.016
81+
};
82+
83+
const elapsedTimeSecond = ElapsedTime.create(SECOND);
84+
85+
testScheduler.run(({ cold, expectObservable }) => {
86+
expectObservable(elapsedTimeSecond).toBe('a-b-c-d-e-f-g-h-i|', expectedVal);
87+
expectObservable(cold('a-b-c-d-e-f-g-h-i|', triggerVal).pipe(tap(elapsedTimeSecond)));
88+
});
89+
});
90+
});

‎packages/operators/src/stream/stats/EstimateTime.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ export default {
77
return new Subject().pipe(
88
calcReceivedStats(),
99
calcEstimatedTime(),
10+
convertEstimedTimeTo(timeUnit),
1011
concatWith(of(0)),
11-
distinctUntilChanged(),
12-
convertEstimedTimeTo(timeUnit)
12+
distinctUntilChanged()
1313
);
1414
}
1515
};
Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { tap } from 'rxjs';
22
import { TestScheduler } from 'rxjs/testing';
3-
import { beforeEach, describe, expect, test } from 'vitest';
3+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
44

55
import EstimateTime from './EstimateTime';
66
import { SECOND } from './utils';
@@ -10,75 +10,65 @@ describe('EstimateTime', () => {
1010

1111
beforeEach(() => {
1212
testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected));
13+
14+
vi.spyOn(global.Date, 'now').mockImplementation(() => testScheduler.now());
15+
});
16+
17+
afterEach(() => {
18+
vi.restoreAllMocks();
1319
});
1420

1521
test('calc estimate time - millisecond', async () => {
22+
const time = Date.now();
23+
1624
const triggerVal = {
17-
a: { value: new TextEncoder().encode('abc'), total: 26, period: 1 },
18-
b: { value: new TextEncoder().encode('def'), total: 26, period: 2 },
19-
c: { value: new TextEncoder().encode('ghi'), total: 26, period: 3 },
20-
d: { value: new TextEncoder().encode('jkl'), total: 26, period: 4 },
21-
e: { value: new TextEncoder().encode('mno'), total: 26, period: 5 },
22-
f: { value: new TextEncoder().encode('pqr'), total: 26, period: 6 },
23-
g: { value: new TextEncoder().encode('stu'), total: 26, period: 7 },
24-
h: { value: new TextEncoder().encode('vwx'), total: 26, period: 8 },
25-
i: { value: new TextEncoder().encode('yz'), total: 26, period: 9 }
25+
a: { value: new TextEncoder().encode('abcd'), total: 20, period: time },
26+
b: { value: new TextEncoder().encode('edgh'), total: 20, period: time },
27+
c: { value: new TextEncoder().encode('ijkl'), total: 20, period: time },
28+
d: { value: new TextEncoder().encode('mnop'), total: 20, period: time },
29+
e: { value: new TextEncoder().encode('qrst'), total: 20, period: time }
2630
};
2731

2832
const expectedVal = {
2933
a: 8,
30-
b: 7,
31-
c: 6,
32-
d: 5,
33-
e: 4,
34-
f: 3,
35-
g: 2,
36-
h: 1,
37-
i: 0
34+
b: 6,
35+
c: 4,
36+
d: 2,
37+
e: 0
3838
};
3939

4040
const estimateTime = EstimateTime.create();
4141

4242
testScheduler.run(({ cold, expectObservable }) => {
43-
expectObservable(estimateTime).toBe('a-b-c-d-e-f-g-h-i', expectedVal);
44-
expectObservable(
45-
cold('a-b-c-d-e-f-g-h-i|', triggerVal).pipe(tap(val => estimateTime.next(val)))
46-
);
43+
expectObservable(estimateTime).toBe('--a-b-c-d-e|', expectedVal);
44+
expectObservable(cold('--a-b-c-d-e|', triggerVal).pipe(tap(estimateTime)));
4745
});
4846
});
4947

5048
test('calc estimate time - second', async () => {
49+
const time = Date.now();
50+
5151
const triggerVal = {
52-
a: { value: new TextEncoder().encode('abc'), total: 26, period: 1 },
53-
b: { value: new TextEncoder().encode('def'), total: 26, period: 2 },
54-
c: { value: new TextEncoder().encode('ghi'), total: 26, period: 3 },
55-
d: { value: new TextEncoder().encode('jkl'), total: 26, period: 4 },
56-
e: { value: new TextEncoder().encode('mno'), total: 26, period: 5 },
57-
f: { value: new TextEncoder().encode('pqr'), total: 26, period: 6 },
58-
g: { value: new TextEncoder().encode('stu'), total: 26, period: 7 },
59-
h: { value: new TextEncoder().encode('vwx'), total: 26, period: 8 },
60-
i: { value: new TextEncoder().encode('yz'), total: 26, period: 9 }
52+
a: { value: new TextEncoder().encode('abcd'), total: 20, period: time },
53+
b: { value: new TextEncoder().encode('edgh'), total: 20, period: time },
54+
c: { value: new TextEncoder().encode('ijkl'), total: 20, period: time },
55+
d: { value: new TextEncoder().encode('mnop'), total: 20, period: time },
56+
e: { value: new TextEncoder().encode('qrst'), total: 20, period: time }
6157
};
6258

6359
const expectedVal = {
6460
a: 0.008,
65-
b: 0.007,
66-
c: 0.006,
67-
d: 0.005,
68-
e: 0.004,
69-
f: 0.003,
70-
g: 0.002,
71-
h: 0.001,
72-
i: 0
61+
b: 0.006,
62+
c: 0.004,
63+
d: 0.002,
64+
e: 0
7365
};
7466

7567
const estimateTimeSecond = EstimateTime.create(SECOND);
7668

7769
testScheduler.run(({ cold, expectObservable }) => {
78-
expectObservable(estimateTimeSecond).toBe('a-b-c-d-e-f-g-h-i', expectedVal);
79-
expectObservable(
80-
cold('a-b-c-d-e-f-g-h-i|', triggerVal).pipe(tap(val => estimateTimeSecond.next(val)))
81-
);
70+
expectObservable(estimateTimeSecond).toBe('--a-b-c-d-e|', expectedVal);
71+
expectObservable(cold('--a-b-c-d-e|', triggerVal).pipe(tap(estimateTimeSecond)));
8272
});
8373
});
8474
});

‎packages/operators/src/stream/stats/Progress.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ describe('Progress', () => {
3939
const progress = Progress.create();
4040

4141
testScheduler.run(({ cold, expectObservable }) => {
42-
expectObservable(progress).toBe('a-b-c-d-e-f-g-h-i', expectedVal);
43-
expectObservable(cold('a-b-c-d-e-f-g-h-i', triggerVal).pipe(tap(val => progress.next(val))));
42+
expectObservable(progress).toBe('a-b-c-d-e-f-g-h-i|', expectedVal);
43+
expectObservable(cold('a-b-c-d-e-f-g-h-i|', triggerVal).pipe(tap(progress)));
4444
});
4545
});
4646
});
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Please sign in to comment.