Skip to content

Commit

Permalink
fix(operators): added fetch tests
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanGerbeth committed Nov 14, 2024
1 parent 4ab3e81 commit 84b2614
Show file tree
Hide file tree
Showing 14 changed files with 376 additions and 118 deletions.
2 changes: 1 addition & 1 deletion packages/operators/src/request/autoPagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { request } from './request';
export const autoPagination = ({ resolveRoute }) => {
return source =>
source.pipe(
concatMap(({ url }) => from(resolveRoute(url)).pipe(request(), getNext(resolveRoute, url))),
concatMap(url => from(resolveRoute(url)).pipe(request(), getNext(resolveRoute, url))),
map(resp => resp.clone())
);
};
Expand Down
95 changes: 88 additions & 7 deletions packages/operators/src/request/autoPagination.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,99 @@
import { concatAll, map, of } from 'rxjs';
import { beforeEach, describe, expect, test } from 'vitest';
import { concatAll, concatMap, delay, from, map, of, toArray } from 'rxjs';

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

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

'from' is defined but never used
import { TestScheduler } from 'rxjs/testing';
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';

import { log } from '../log';
import { autoPagination } from './autoPagination';
import { resolveJSON } from './response';

describe('auto pagination', function () {
describe('auto pagination - mocked', function () {
const testScheduler = new TestScheduler((actual, expected) => {
expect(actual).to.eql(expected);
});

beforeEach(function () {
//
vi.doMock('./request', importOriginal => ({

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

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

'importOriginal' is defined but never used
request: () => source => source.pipe(concatMap(({ v, t }) => of(v).pipe(delay(t))))
}));

Object.prototype.clone = vi.fn();
vi.spyOn(Object.prototype, 'clone').mockImplementation(function (e) {

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

View workflow job for this annotation

GitHub Actions / Install (ubuntu-latest, 20)

'e' is defined but never used
return { ...JSON.parse(JSON.stringify(this)) };
});
});

test('auto pagination', async function () {
afterEach(() => {
vi.doUnmock('./request');
});

test('classic testing', async () => {
const { autoPagination } = await import('./autoPagination');

const triggerValues = {
a: { t: 2, v: { value: 'a', next: 1 } },
b: { t: 5, v: { value: 'b', next: 2 } },
c: { t: 3, v: { value: 'c', next: 3 } },
d: { t: 1, v: { value: 'd', next: 4 } },
e: { t: 4, v: { value: 'e', next: null } }
};

const expectedVal = Array.from(Object.entries(triggerValues)).map(([k, { v }]) => v);

const triggerVal = Object.values(triggerValues);
await new Promise((done, error) => {
of(triggerVal[0])
.pipe(
autoPagination({
resolveRoute: (conf, resp) =>
((!resp || resp.next) && [triggerVal[resp?.next || 0]]) || []
}),
toArray()
)
.subscribe({
next: e => expect(e).toStrictEqual(expectedVal),
complete: () => done(),
error: () => error()
});
});
});

test.skip('marble testing', async () => {
const { autoPagination } = await import('./autoPagination');

const triggerVal = {
a: { t: 2, v: { value: 'a', next: 'b' } },
b: { t: 5, v: { value: 'b', next: 'c' } },
c: { t: 3, v: { value: 'c', next: 'd' } },
d: { t: 1, v: { value: 'd', next: 'e' } },
e: { t: 4, v: { value: 'e', next: null } }
};

const expectedVal = Object.fromEntries(
Array.from(Object.entries(triggerVal)).map(([k, { v }]) => [k, v])
);

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(
cold('-a-------------------', triggerVal).pipe(
autoPagination({
resolveRoute: (conf, resp) =>
((!resp || resp.next) && [triggerVal[resp?.next || 'a']]) || []
})
)
).toBe('---a----b--cd---e----', expectedVal);
});
});
});

describe.skip('auto pagination - demo', function () {
beforeEach(function () {
vi.resetModules();
});

test('sample testing', async function () {
const { autoPagination } = await import('./autoPagination');

return new Promise(done => {
return of({ url: new URL('https://dummyjson.com/products') })
return of(new URL('https://dummyjson.com/products'))
.pipe(
autoPagination({
resolveRoute: async (url, resp) => {
Expand Down
6 changes: 4 additions & 2 deletions packages/operators/src/request/cache.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ReplaySubject, share, timer } from 'rxjs';
import { ReplaySubject, share, tap, timer } from 'rxjs';

export const cache = ttl => {
return source =>
source.pipe(
share({
// TODO: check if a buffer size is neccessary
connector: () => new ReplaySubject(),
resetOnComplete: () => timer(ttl)
// resetOnError: false,
resetOnComplete: () => timer(ttl),
resetOnRefCountZero: false
})
);
};
49 changes: 43 additions & 6 deletions packages/operators/src/request/cache.test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,54 @@
import fetchMock from 'fetch-mock';
import { defer, of, tap } from 'rxjs';
import { defer, delay, from, interval, map, mapTo, of, tap, throttleTime } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { afterEach, beforeEach, describe, expect, test } from 'vitest';

import { cache } from './cache';
import { requestText } from './request';

describe('cache - mocked', function () {
beforeEach(function () {
//
});

afterEach(function () {
//
});

test.skip('cache resetted after 100ms', async function () {
let counter = 0;
const a = of(counter).pipe(
tap(e => console.log('U', e)),
cache(5)
);

defer(() => a)
.pipe(delay(2))
.subscribe(e => console.log(e));
defer(() => a)
.pipe(delay(2))
.subscribe(e => console.log(e));

await new Promise(done => setTimeout(done), 500);

defer(() => a)
.pipe(delay(100))
.subscribe(e => console.log(e));

await new Promise(done => setTimeout(done), 1000);
});
});

describe('cache', function () {
beforeEach(function () {
let counter = 0;
fetchMock.mockGlobal().get(
'https://httpbin.org/my-url-fast',
() => {
return new Response(++counter, {
() =>
new Response(++counter, {
status: 200,
headers: { 'Content-type': 'plain/text' }
});
},
}),
{ delay: 0, repeat: 2 }
);
});
Expand All @@ -25,7 +58,11 @@ describe('cache', function () {
});

test('cache resetted after 100ms', async function () {
const a = of('https://httpbin.org/my-url-fast').pipe(requestText(), cache(1000));
const a = of('https://httpbin.org/my-url-fast').pipe(
requestText(),
tap(() => console.log('CHECK')),
cache(1000)
);
await new Promise(done => {
a.subscribe({
next: e => expect(e).toBe('1'),
Expand Down
2 changes: 1 addition & 1 deletion packages/operators/src/request/concurrentRequest.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mergeMap, of, tap } from 'rxjs';
import { mergeMap, of } from 'rxjs';

import { request } from './request';

Expand Down
31 changes: 0 additions & 31 deletions packages/operators/src/request/concurrentRequest.sample.js

This file was deleted.

106 changes: 74 additions & 32 deletions packages/operators/src/request/concurrentRequest.test.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,96 @@
import { concatMap, delay, of, tap, toArray } from 'rxjs';
import { concatAll, concatMap, delay, from, map, of, tap, toArray } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';

import { concurrentRequest } from './concurrentRequest';
import { log } from '../log';
import { resolveJSON } from './response';

describe('multi fetch33', function () {
describe('concurrent request - mocked', function () {
const testScheduler = new TestScheduler((actual, expected) => {
expect(actual).to.eql(expected);
});

const getTriggerValues = () => ({
a: { t: 2, v: 'a' },
b: { t: 5, v: 'b' },
c: { t: 1, v: 'c' },
d: { t: 3, v: 'd' },
e: { t: 4, v: 'e' }
});

beforeEach(function () {
vi.mock('./request.js', async importOriginal => {
return {
request: () => source => source.pipe(concatMap(({ v, t }) => of(v).pipe(delay(t))))
};
});
vi.doMock('./request', importOriginal => ({
request: () => source => source.pipe(concatMap(({ v, t }) => of(v).pipe(delay(t))))
}));
});

afterEach(() => {
vi.resetAllMocks();
vi.doUnmock('./request');
});

test('test', async () => {
const values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(v => ({ v, t: Math.random() * 1000 }));
const sortedResult = [...values].sort((a, b) => a.t - b.t).map(({ v }) => v);
test('classic testing', async () => {
const { concurrentRequest } = await import('./concurrentRequest');

await new Promise(done => {
of(...values)
.pipe(concurrentRequest(values.length), toArray())
.subscribe({ next: e => expect(e).to.eql(sortedResult), complete: () => done() });
const triggerVal = Object.values(getTriggerValues());
const sortedVal = [...triggerVal].sort((a, b) => a.t - b.t).map(({ v }) => v);

await new Promise((done, error) => {
from(triggerVal)
.pipe(concurrentRequest(triggerVal.length), toArray())
.subscribe({
next: e => expect(e).toStrictEqual(sortedVal),
complete: () => done(),
error: e => error(e)
});
});
});

test('test2', async () => {
const triggerValues = {
a: { t: 2, v: 'a' },
b: { t: 5, v: 'b' },
c: { t: 0, v: 'c' },
d: { t: 1, v: 'd' },
e: { t: 1, v: 'd' }
};
const expectedValues = Object.fromEntries(
Array.from(Object.entries(triggerValues)).map(([k, { v }]) => [k, v])
);
test('marble testing', async () => {
const { concurrentRequest } = await import('./concurrentRequest');

const triggerVal = getTriggerValues();
const expectedVal = Object.fromEntries(Object.entries(triggerVal).map(([k, { v }]) => [k, v]));

testScheduler.run(({ cold, expectObservable }) => {
expectObservable(cold('-a-b-c-(de)', triggerValues).pipe(concurrentRequest(3), tap())).toBe(
'---a-c--(bde)',
expectedValues
);
expectObservable(
cold('-a-b-(cd)-e----', triggerVal).pipe(concurrentRequest(Object.keys(triggerVal).length))
).toBe('---a--c-(bd)--e', expectedVal);
});
});
});

describe.skip('concurrent request - demo', function () {
beforeAll(function () {
vi.resetModules();
});

test('sample testing', async () => {
const { concurrentRequest } = await import('./concurrentRequest');

await new Promise(done => {
of(
new URL('https://dummyjson.com/products?limit=10&skip=0&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=10&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=20&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=30&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=40&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=50&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=60&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=70&select=title,price'),
new URL('https://dummyjson.com/products?limit=10&skip=80&select=title,price')
)
.pipe(
concurrentRequest(4),
log(false),
resolveJSON(),
log(false),
map(({ products }) => products),
concatAll()
)
.subscribe({
next: e => console.log(e),
complete: () => done()
});
});
});
});
6 changes: 3 additions & 3 deletions packages/operators/src/request/lazyPagination.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { concatMap, map } from 'rxjs';
import { concatMap, map, tap } from 'rxjs';

import { concurrentRequest } from './concurrentRequest';

export const lazyPagination = ({ resolveRoute }) => {
export const lazyPagination = ({ pager, concurrent, resolveRoute }) => {
return source =>
source.pipe(
concatMap(({ url, pager, concurrent }) => {
concatMap(({ url }) => {
return pager.pipe(
map(options => resolveRoute(url, options)),
concurrentRequest(concurrent)
Expand Down
Loading

0 comments on commit 84b2614

Please sign in to comment.