Skip to content

Commit

Permalink
chore: add tests & fix: add return to skip() operator
Browse files Browse the repository at this point in the history
  • Loading branch information
jeengbe committed Jul 23, 2024
1 parent acd8fbd commit 6e9ddc8
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 22 deletions.
22 changes: 21 additions & 1 deletion spec/asynciterable-operators/catcherror-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { jest } from '@jest/globals';
import '../asynciterablehelpers.js';
import { of, range, sequenceEqual, single, throwError } from 'ix/asynciterable/index.js';
import {
first,
from,
of,
range,
sequenceEqual,
single,
throwError,
} from 'ix/asynciterable/index.js';
import { catchError } from 'ix/asynciterable/operators/index.js';

test('AsyncIterable#catchError error catches', async () => {
Expand All @@ -26,3 +35,14 @@ test('AsyncIterable#catchError source and handler types are composed', async ()
const res = xs.pipe(catchError(async (_: Error) => of('foo')));
await expect(sequenceEqual(res, xs)).resolves.toBeTruthy();
});

test('AsyncIterable#catchError calls return() on source iterator when stopped early', async () => {
const xs = range(0, 10)[Symbol.asyncIterator]();
const returnSpy = jest.spyOn(xs, 'return');

const res = from(xs).pipe(catchError((_: Error) => from([])));

await first(res);

expect(returnSpy).toHaveBeenCalled();
});
14 changes: 13 additions & 1 deletion spec/asynciterable-operators/skip-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { jest } from '@jest/globals';
import { hasNext, noNext } from '../asynciterablehelpers.js';
import { of, throwError } from 'ix/asynciterable/index.js';
import { as, first, of, range, throwError } from 'ix/asynciterable/index.js';
import { skip } from 'ix/asynciterable/operators/index.js';

test('AsyncIterable#skip skips some', async () => {
Expand Down Expand Up @@ -40,3 +41,14 @@ test('AsyncIterable#skip throws', async () => {
const it = ys[Symbol.asyncIterator]();
await expect(it.next()).rejects.toThrow(err);
});

test('Iterable#skip calls return() on source iterator when stopped early', async () => {
const xs = range(0, 10)[Symbol.asyncIterator]();
const returnSpy = jest.spyOn(xs, 'return');

const res = as(xs).pipe(skip(2));

await first(res);

expect(returnSpy).toHaveBeenCalled();
});
31 changes: 26 additions & 5 deletions spec/asynciterable/catcherror-spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { skip } from 'ix/asynciterable/operators.js';
import { hasNext } from '../asynciterablehelpers.js';
import { catchError, concat, range, sequenceEqual, throwError } from 'ix/asynciterable/index.js';

test('AsyncIterable#catch with no errors', async () => {
import {
catchError,
concat,
first,
from,
range,
sequenceEqual,
throwError,
} from 'ix/asynciterable/index.js';

test('AsyncIterable#catchError with no errors', async () => {
const res = catchError(range(0, 5), range(5, 5));
expect(await sequenceEqual(res, range(0, 5))).toBeTruthy();
});

test('AsyncIterable#catch with concat error', async () => {
test('AsyncIterable#catchError with concat error', async () => {
const res = catchError(concat(range(0, 5), throwError(new Error())), range(5, 5));

expect(await sequenceEqual(res, range(0, 10))).toBeTruthy();
});

test('AsyncIterable#catch still throws', async () => {
test('AsyncIterable#catchError still throws', async () => {
const e1 = new Error();
const er1 = throwError(e1);

Expand All @@ -31,3 +40,15 @@ test('AsyncIterable#catch still throws', async () => {
await hasNext(it, 3);
await expect(it.next()).rejects.toThrow();
});

test('AsyncIterable#catchError calls return() on source iterator when stopped early', async () => {
const xs1 = range(0, 2);
const xs2 = range(2, 2)[Symbol.asyncIterator]();
const returnSpy = jest.spyOn(xs2, 'return');

const res = catchError(xs1, from(xs2)).pipe(skip(2));

await first(res);

expect(returnSpy).toHaveBeenCalled();
});
14 changes: 13 additions & 1 deletion spec/iterable-operators/catcherror-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { jest } from '@jest/globals';
import '../iterablehelpers';
import { of, range, sequenceEqual, single, throwError } from 'ix/iterable/index.js';
import { first, from, of, range, sequenceEqual, single, throwError } from 'ix/iterable/index.js';
import { catchError } from 'ix/iterable/operators/index.js';

test('Iterable#catchError error catches', () => {
Expand All @@ -26,3 +27,14 @@ test('Iterable#catchError source and handler types are composed', () => {
const res = xs.pipe(catchError((_: Error) => of('foo')));
expect(sequenceEqual(res, xs)).toBeTruthy();
});

test('Iterable#catchError calls return() on source iterator when stopped early', () => {
const xs = range(0, 10)[Symbol.iterator]();
const returnSpy = jest.spyOn(xs, 'return');

const res = from(xs).pipe(catchError((_: Error) => from([])));

first(res);

expect(returnSpy).toHaveBeenCalled();
});
14 changes: 13 additions & 1 deletion spec/iterable-operators/skip-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { jest } from '@jest/globals';
import { hasNext, noNext } from '../iterablehelpers.js';
import { as, throwError } from 'ix/iterable/index.js';
import { as, first, range, throwError } from 'ix/iterable/index.js';
import { skip } from 'ix/iterable/operators/index.js';

test('Iterable#skip skips some', () => {
Expand Down Expand Up @@ -39,3 +40,14 @@ test('Iterable#skip throws', () => {
const it = ys[Symbol.iterator]();
expect(() => it.next()).toThrow();
});

test('Iterable#skip calls return() on source iterator when stopped early', () => {
const xs = range(0, 10)[Symbol.iterator]();
const returnSpy = jest.spyOn(xs, 'return');

const res = as(xs).pipe(skip(2));

first(res);

expect(returnSpy).toHaveBeenCalled();
});
24 changes: 23 additions & 1 deletion spec/iterable/catcherror-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { jest } from '@jest/globals';
import { skip } from 'ix/iterable/operators.js';
import { hasNext } from '../iterablehelpers.js';
import { catchError, concat, range, sequenceEqual, throwError } from 'ix/iterable/index.js';
import {
from,
catchError,
concat,
range,
sequenceEqual,
throwError,
first,
} from 'ix/iterable/index.js';

test('Iterable.catchError with no errors', () => {
const res = catchError(range(0, 5), range(5, 5));
Expand Down Expand Up @@ -31,3 +41,15 @@ test('Iterable.catchError still throws', () => {
hasNext(it, 3);
expect(() => it.next()).toThrow();
});

test('Iterable.catchError calls return() on source iterator when stopped early', () => {
const xs1 = range(0, 2);
const xs2 = range(2, 2)[Symbol.iterator]();
const returnSpy = jest.spyOn(xs2, 'return');

const res = catchError(xs1, from(xs2)).pipe(skip(2));

first(res);

expect(returnSpy).toHaveBeenCalled();
});
18 changes: 12 additions & 6 deletions src/asynciterable/operators/skip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AsyncIterableX } from '../asynciterablex.js';
import { MonoTypeOperatorAsyncFunction } from '../../interfaces.js';
import { wrapWithAbort } from './withabort.js';
import { throwIfAborted } from '../../aborterror.js';
import { returnAsyncIterator } from 'ix/util/returniterator.js';

/** @ignore */
export class SkipAsyncIterable<TSource> extends AsyncIterableX<TSource> {
Expand All @@ -20,13 +21,18 @@ export class SkipAsyncIterable<TSource> extends AsyncIterableX<TSource> {
const it = source[Symbol.asyncIterator]();
let count = this._count;
let next;
while (count > 0 && !(next = await it.next()).done) {
count--;
}
if (count <= 0) {
while (!(next = await it.next()).done) {
yield next.value;

try {
while (count > 0 && !(next = await it.next()).done) {
count--;
}
if (count <= 0) {
while (!(next = await it.next()).done) {
yield next.value;
}
}
} finally {
returnAsyncIterator(it);
}
}
}
Expand Down
18 changes: 12 additions & 6 deletions src/iterable/operators/skip.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IterableX } from '../iterablex.js';
import { MonoTypeOperatorFunction } from '../../interfaces.js';
import { returnIterator } from 'ix/util/returniterator.js';

/** @ignore */
export class SkipIterable<TSource> extends IterableX<TSource> {
Expand All @@ -16,13 +17,18 @@ export class SkipIterable<TSource> extends IterableX<TSource> {
const it = this._source[Symbol.iterator]();
let count = this._count;
let next;
while (count > 0 && !(next = it.next()).done) {
count--;
}
if (count <= 0) {
while (!(next = it.next()).done) {
yield next.value;

try {
while (count > 0 && !(next = it.next()).done) {
count--;
}
if (count <= 0) {
while (!(next = it.next()).done) {
yield next.value;
}
}
} finally {
returnIterator(it);
}
}
}
Expand Down

0 comments on commit 6e9ddc8

Please sign in to comment.