Skip to content

Commit

Permalink
Timeout - covered with unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
dimadeveatii committed Jan 22, 2019
1 parent 42fc1f1 commit c1a3289
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 5 deletions.
9 changes: 4 additions & 5 deletions lib/timeout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export function timeout(milliseconds?: number) {
timeoutId = wait(rej, milliseconds);
});

return Promise.race([expire, func.apply(this, arguments)])
const args = arguments;
const thenable = new Promise(res => res(func.apply(this, args)));

return Promise.race([expire, thenable])
.then(
(res) => {
clearTimeout(timeoutId);
Expand All @@ -36,10 +39,6 @@ export namespace timeout {
* @param milliseconds timeout in milliseconds.
*/
export function current(milliseconds: number): void {
if (milliseconds < 1) {
throw new Error('Invalid timeout value. Provide a value greater than 0.');
}

defaultTimeout = milliseconds;
}
}
Expand Down
153 changes: 153 additions & 0 deletions test/timeout.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { timeout } from '../lib';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';

chai.use(chaiAsPromised);
const expect = chai.expect;

describe('timeout', () => {
describe('When method doesn\'t timeout.', () => {
it('Should resolve with expected result', async () => {
class TestClass {
@timeout(100)
async test() {
await delay(10);
return 42;
}
}

const target = new TestClass();
const result = await target.test();

expect(result).to.equal(42);
});

it('Should return a promise for a sync method.', async () => {
class TestClass {
@timeout(0)
test(): any {
return 42;
}
}

const target = new TestClass();
const result = target.test();

expect(result).to.have.property('then');
await expect(result).eventually.to.be.equal(42);
});

it('Should resolve for a void method.', async () => {
class TestClass {
@timeout(100)
async test() {
await delay(10);
}
}

const target = new TestClass();
await target.test();
});
});

describe('When method times out', () => {
it('Should reject with a `Timeout.` error.', async () => {
class TestClass {
@timeout(10)
async test() {
await delay(15);
}
}

const target = new TestClass();
await expect(target.test()).to.eventually.be.rejectedWith('Timeout.');
});
});

describe('When using default timeout', () => {
it('Should resolve 100ms method', async () => {
class TestClass {
@timeout()
async test() {
await delay(100);
return 42;
}
}

const target = new TestClass();
await expect(target.test()).to.eventually.be.equal(42);
});

it('Should reject 100ms method if default changed to 10ms', async () => {
class TestClass {
@timeout()
async test() {
await delay(100);
return 42;
}
}

timeout.current(10);

const target = new TestClass();
await expect(target.test()).to.eventually.be.rejected;
});
});

describe('When method fails before timeout', () => {
it('Should reject with original error', async () => {
class TestClass {
@timeout()
async test() {
return Promise.reject('Error 42.');
}
}

const target = new TestClass();
await expect(target.test()).to.eventually.be.rejectedWith('Error 42.');
});

it('Should reject with original error on throw', async () => {
class TestClass {
@timeout()
async test() {
throw new Error('Error 42.');
}
}

const target = new TestClass();
await expect(target.test()).to.eventually.be.rejectedWith('Error 42.');
});

it('Should reject with original error for a sync method', async () => {
class TestClass {
@timeout()
test() {
throw new Error('Error 42.');
}
}

const target = new TestClass();
await expect(target.test()).to.eventually.be.rejectedWith('Error 42.');
});
});

describe('When method fails after timeout', () => {
it('Should reject with `Timeout.` error.', async () => {
class TestClass {
@timeout(10)
async test() {
await delay(15);
throw new Error('Error 42.');
}
}

const target = new TestClass();
await expect(target.test()).to.eventually.be.rejectedWith('Timeout.');
});
});
});

function delay(ms: number) {
return new Promise(res => setTimeout(res, ms));
}

0 comments on commit c1a3289

Please sign in to comment.