Skip to content

Commit

Permalink
fix(unit-test): updated operator tests
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanGerbeth committed Jan 12, 2025
1 parent 8c666a7 commit 05ab39b
Show file tree
Hide file tree
Showing 14 changed files with 337 additions and 69 deletions.
3 changes: 2 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export default [
globals: {
...globals.browser,
expect: 'readonly',
global: 'readonly'
global: 'readonly',
__dirname: 'readonly'
}
},
plugins: {
Expand Down
7 changes: 2 additions & 5 deletions packages/mocks/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import { mockAsync } from './async';

export const mockBlob = () => {
return vi.fn(([e], type) => ({
text: () => {
console.log(type);
return mockAsync(new TextDecoder().decode(e));
},
type: e.type
text: () => mockAsync(new TextDecoder().decode(e)),
type
}));
};
Binary file added packages/operators/fixtures/videos/demo.mp4
Binary file not shown.
8 changes: 4 additions & 4 deletions packages/operators/src/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export const blobToXML = () => {
);
};

export const blobToVideo = () => {
return source => source.pipe();
export const blobToURL = () => {
return source => source.pipe(map(blob => URL.createObjectURL(blob)));
};

export const blobTo = () => {
Expand All @@ -40,12 +40,12 @@ const getOperator = blob => {
};

const TYPES = {
'video/*': blobToVideo,
'video/*': blobToURL,
'application/json': blobToJSON,
'text/plain': blobToText,
'text/html': blobToXML,
'text/xml': blobToXML,
'application/xml': blobToXML,
'application/xhtml+xml': blobToXML,
'image/svg+xml': blobToVideo
'image/svg+xml': blobToXML
};
116 changes: 105 additions & 11 deletions packages/operators/src/blob.test.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,117 @@
import { describe, test } from 'vitest';
import { mockBlob } from '#mocks/blob.js';
import fs from 'node:fs';
import { map } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';

describe('blob', () => {
test('blob to text', () => {
//
let testScheduler;

beforeEach(() => {
vi.spyOn(global, 'Blob').mockImplementation(mockBlob());
testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected));
});

test('blob to json', () => {
//
afterEach(() => {
vi.restoreAllMocks();
});

test('blob to xml', () => {
//
test('blob to text', async () => {
const { blobToText } = await import('./blob.js');

const expectedVal = {
a: 'hello world',
b: 'foo bar'
};

const triggerVal = {
a: new Blob([new TextEncoder().encode(expectedVal.a)], 'text/plain'),
b: new Blob([new TextEncoder().encode(expectedVal.b)], 'text/plain')
};

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(cold('a-b|', triggerVal).pipe(blobToText())).toBe('a-b|', expectedVal);
});
});

test('blob to video', () => {
//
test('blob to json', async () => {
const { blobToJSON } = await import('./blob.js');

const expectedVal = {
a: { hello: 'world' },
b: { foo: 'bar' }
};

const triggerVal = {
a: new Blob([new TextEncoder().encode(JSON.stringify(expectedVal.a))], 'application/json'),
b: new Blob([new TextEncoder().encode(JSON.stringify(expectedVal.b))], 'application/json')
};

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(cold('a-b|', triggerVal).pipe(blobToJSON())).toBe('a-b|', expectedVal);
});
});

test('blob to (auto detect)', () => {
//
test('blob to xml', async () => {
const { blobToXML } = await import('./blob.js');

const expectedVal = {
a: new DOMParser().parseFromString('<xml></xml>', 'text/xml'),
b: new DOMParser().parseFromString('<xml><a></a></xml>', 'text/xml')
};

const triggerVal = {
a: new Blob([new TextEncoder().encode('<xml></xml>')], 'text/xml'),
b: new Blob([new TextEncoder().encode('<xml><a></a></xml>')], 'text/xml')
};

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(cold('a-b|', triggerVal).pipe(blobToXML())).toBe('a-b|', expectedVal);
});
});

test('blob to url', async () => {
vi.restoreAllMocks();

const { blobToURL } = await import('./blob.js');

const triggerVal = {
a: new Blob([fs.readFileSync(`${__dirname}/../fixtures/videos/demo.mp4`)], 'video/mp4')
};

const expectedVal = {
a: 'blob:nodedata:'
};

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(
cold('a|', triggerVal).pipe(
blobToURL(),
map(v => v.replace(/([a-z0-9-]+)$/, ''))
)
).toBe('a|', expectedVal);
});
});

test('blob to (auto detect)', async () => {
const { blobTo } = await import('./blob.js');

const expectedVal = {
a: 'hello world',
b: { foo: 'bar' },
c: new DOMParser().parseFromString('<xml><a></a></xml>', 'text/xml'),
d: new Blob([new TextEncoder().encode('aha')], 'x-text/plain')
};

const triggerVal = {
a: new Blob([new TextEncoder().encode('hello world')], 'text/plain'),
b: new Blob([new TextEncoder().encode(JSON.stringify({ foo: 'bar' }))], 'application/json'),
c: new Blob([new TextEncoder().encode('<xml><a></a></xml>')], 'text/xml'),
d: expectedVal.d
};

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(cold('a-b-c-d|', triggerVal).pipe(blobTo())).toBe('a-b-c-d|', expectedVal);
});
});
});
16 changes: 8 additions & 8 deletions packages/operators/src/request.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { test, describe, beforeEach, expect, vi, afterAll, beforeAll } from 'vit

import { log, logResult } from './log.js';
import { resolveBlob, resolveJSON } from './response.js';
import { EstimateTime } from './stream/stats/EstimateTime.js';
import { Progress } from './stream/stats/Progress.js';
import { TransferRate } from './stream/stats/TransferRate.js';
import EstimateTime from './stream/stats/EstimateTime.js';
import Progress from './stream/stats/Progress.js';
import TransferRate from './stream/stats/TransferRate.js';
import { MBYTE, SECOND } from './stream/stats/utils.js';

describe.skip('request', () => {
Expand Down Expand Up @@ -176,13 +176,13 @@ describe.skip('request - demo ', () => {
body: formData
});

const progressUpload = new Progress();
const progressUpload = Progress.create();
progressUpload.subscribe({
next: e => console.log('UPLOAD', e),

Check warning on line 181 in packages/operators/src/request.test.js

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

Unexpected console statement
complete: () => console.log('complete')

Check warning on line 182 in packages/operators/src/request.test.js

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

Unexpected console statement
});

const progressDownload = new Progress();
const progressDownload = Progress.create();
progressDownload.subscribe({
next: e => console.log('DOWNLOAD', e),

Check warning on line 187 in packages/operators/src/request.test.js

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

Unexpected console statement
complete: () => console.log('complete')

Check warning on line 188 in packages/operators/src/request.test.js

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

Unexpected console statement
Expand All @@ -205,13 +205,13 @@ describe('test', () => {
test('progress on download', async () => {
const { request } = await import('./request.js');

const progress = new Progress();
const progress = Progress.create();
progress.subscribe({ next: e => console.log('DOWNLOAD', e) });

Check warning on line 209 in packages/operators/src/request.test.js

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

Unexpected console statement

const byteRate = new TransferRate(MBYTE, SECOND);
const byteRate = TransferRate.create(MBYTE, SECOND);
byteRate.subscribe({ next: e => console.log('RATE', e) });

Check warning on line 212 in packages/operators/src/request.test.js

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

Unexpected console statement

const estimateTime = new EstimateTime(SECOND);
const estimateTime = EstimateTime.create(SECOND);
estimateTime.subscribe({ next: e => console.log('ESTIMATE', e) });

Check warning on line 215 in packages/operators/src/request.test.js

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

Unexpected console statement

const fileMap = {
Expand Down
9 changes: 4 additions & 5 deletions packages/operators/src/stream/stats/EstimateTime.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import { concatWith, distinctUntilChanged, map, of, Subject } from 'rxjs';

import { calcReceivedStats, MSECOND } from './utils';

export class EstimateTime extends Subject {
constructor(timeUnit = MSECOND) {
super();
return this.pipe(
export default {
create: (timeUnit = MSECOND) => {
return new Subject().pipe(
calcReceivedStats(),
calcEstimatedTime(),
concatWith(of(0)),
distinctUntilChanged(),
convertEstimedTimeTo(timeUnit)
);
}
}
};

const calcEstimatedTime = () => {
return source =>
Expand Down
84 changes: 84 additions & 0 deletions packages/operators/src/stream/stats/EstimateTime.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { tap } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { beforeEach, describe, expect, test } from 'vitest';

import EstimateTime from './EstimateTime';
import { SECOND } from './utils';

describe('EstimateTime', () => {
let testScheduler;

beforeEach(() => {
testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected));
});

test('calc estimate time - millisecond', async () => {
const triggerVal = {
a: { value: new TextEncoder().encode('abc'), total: 26, period: 1 },
b: { value: new TextEncoder().encode('def'), total: 26, period: 2 },
c: { value: new TextEncoder().encode('ghi'), total: 26, period: 3 },
d: { value: new TextEncoder().encode('jkl'), total: 26, period: 4 },
e: { value: new TextEncoder().encode('mno'), total: 26, period: 5 },
f: { value: new TextEncoder().encode('pqr'), total: 26, period: 6 },
g: { value: new TextEncoder().encode('stu'), total: 26, period: 7 },
h: { value: new TextEncoder().encode('vwx'), total: 26, period: 8 },
i: { value: new TextEncoder().encode('yz'), total: 26, period: 9 }
};

const expectedVal = {
a: 8,
b: 7,
c: 6,
d: 5,
e: 4,
f: 3,
g: 2,
h: 1,
i: 0
};

const estimateTime = EstimateTime.create();

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(estimateTime).toBe('a-b-c-d-e-f-g-h-i', expectedVal);
expectObservable(
cold('a-b-c-d-e-f-g-h-i|', triggerVal).pipe(tap(val => estimateTime.next(val)))
);
});
});

test('calc estimate time - second', async () => {
const triggerVal = {
a: { value: new TextEncoder().encode('abc'), total: 26, period: 1 },
b: { value: new TextEncoder().encode('def'), total: 26, period: 2 },
c: { value: new TextEncoder().encode('ghi'), total: 26, period: 3 },
d: { value: new TextEncoder().encode('jkl'), total: 26, period: 4 },
e: { value: new TextEncoder().encode('mno'), total: 26, period: 5 },
f: { value: new TextEncoder().encode('pqr'), total: 26, period: 6 },
g: { value: new TextEncoder().encode('stu'), total: 26, period: 7 },
h: { value: new TextEncoder().encode('vwx'), total: 26, period: 8 },
i: { value: new TextEncoder().encode('yz'), total: 26, period: 9 }
};

const expectedVal = {
a: 0.008,
b: 0.007,
c: 0.006,
d: 0.005,
e: 0.004,
f: 0.003,
g: 0.002,
h: 0.001,
i: 0
};

const estimateTimeSecond = EstimateTime.create(SECOND);

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(estimateTimeSecond).toBe('a-b-c-d-e-f-g-h-i', expectedVal);
expectObservable(
cold('a-b-c-d-e-f-g-h-i|', triggerVal).pipe(tap(val => estimateTimeSecond.next(val)))
);
});
});
});
9 changes: 4 additions & 5 deletions packages/operators/src/stream/stats/Progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ import { concatWith, distinctUntilChanged, map, of, Subject } from 'rxjs';

import { calcReceivedStats } from './utils';

export class Progress extends Subject {
constructor() {
super();
return this.pipe(
export default {
create: () => {
return new Subject().pipe(
calcReceivedStats(),
calcPercentageProgress(),
concatWith(of(100)),
distinctUntilChanged()
);
}
}
};

const calcPercentageProgress = () => {
return source => source.pipe(map(({ value, total }) => Math.floor((value / total) * 100)));
Expand Down
Loading

0 comments on commit 05ab39b

Please sign in to comment.