Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TypeScript definition file #734

Merged
merged 1 commit into from Aug 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
99 changes: 62 additions & 37 deletions README.md
Expand Up @@ -78,6 +78,19 @@ $ lab unit.js
```

Test files must require the **lab** module, and export a test script:

```javascript
const { expect, it } = exports.lab = require('lab').script();

it('returns true when 1 + 1 equals 2', (done) => {

expect(1 + 1).to.equal(2);
done();
});
```

Or

```javascript
const Lab = require('lab');
const lab = exports.lab = Lab.script();
Expand Down Expand Up @@ -182,6 +195,9 @@ lab.experiment('with only', () => {
});
```


### `note()`

The `test()` callback has a `note()` function attached to it that can be used to
attach notes to the test case. These notes are included in the console reporter
at the end of the output. For example, if you would like to add a note with the
Expand All @@ -200,6 +216,8 @@ Multiple notes can be appended for the same test case by simply calling `note()`
repeatedly.


### `onCleanup()`

The `test()` callback provides a second `onCleanup` argument which is a function used to register a runtime cleanup function
to be executed after the test completed. The cleanup function will execute even in the event of a timeout. Note that the cleanup
function will be executed as-is without any timers and if it fails to call it's `next` argument, the runner will freeze.
Expand All @@ -218,6 +236,8 @@ lab.test('cleanups after test', (done, onCleanup) => {
});
```

### `plan()`

Additionally, `test()` options support a `plan` setting to specify the expected number of assertions for your test to execute. This
setting should only be used with an assertion library that supports a `count()` function, like [`code`](http://npmjs.com/package/code).
*`plan` may not work with parallel test executions*
Expand All @@ -233,6 +253,8 @@ lab.experiment('my plan', () => {
});
```

### Timeouts

`before()`, `after()`, `beforeEach()`, `afterEach()` accept an optional `options` argument which must be an object with the following optional keys:
- `timeout` - set a specific timeout in milliseconds. Disabled by default or the value of `-M`.

Expand All @@ -253,6 +275,8 @@ lab.experiment('math', { timeout: 1000 }, () => {
});
```

### Script options

The `script([options])` method takes an optional `options` argument where `options` is an object with the following optional keys:
- `schedule` - if `false`, an automatic execution of the script is disabled. Automatic execution allows running lab test scripts directly
with node without having to use the cli (e.g. `node test/script.js`). When using **lab** programmatically, this behavior is undesired and
Expand All @@ -262,6 +286,9 @@ The `script([options])` method takes an optional `options` argument where `optio
on commits. Setting this option has no effect when not using the CLI runner. For example setting `cli` to `{ ids: [1] }` will only execute
the first test loaded.


### Behavior Driven Development

To make **lab** look like BDD:
```javascript
const Lab = require('lab');
Expand Down Expand Up @@ -293,6 +320,9 @@ describe('math', () => {
});
```


### Test Driven Development

To make **lab** look like TDD:
```javascript
const Lab = require('lab');
Expand All @@ -312,46 +342,41 @@ suite('math', () => {
});
```

To use source transforms, you must specify a file with the `-T` command line option that tells Lab how to do the transformation. You can specify many extensions with different transform functions such as `.coffee` or `.jsx`. A sample file using the babel transpiler and the CoffeeScript compiler could look like:
### Transforms

```javascript
const Babel = require('babel-core');
const Coffee = require('coffee-script');
const Btoa = require('btoa');

module.exports = [
{ ext: '.js', transform: (content, filename) => {

// Make sure to only transform your code or the dependencies you want
if (filename.indexOf('node_modules') === -1) {
const result = Babel.transform(content, { sourceMap: 'inline', filename, sourceFileName: filename });
return result.code;
}

return content;
} },
{ ext: '.coffee', transform: (content, filename) => {

// Again, make sure to only transform your code or the dependencies you want
if (filename.indexOf('node_modules') === -1) {
const result = Coffee.compile(content, {
sourceMap: true,
inline: true,
sourceRoot: '/',
sourceFiles: [filename]
});
To use source transforms, you must specify a file with the `-T` command line option that tells Lab how to do the transformation. You can specify many extensions with different transform functions such as `.ts` or `.jsx`.

#### TypeScript

A TypeScript definition file is included with **lab** to make it easier to use inside of an existing TypeScript project. Below is a TypeScript test example that uses the [lab-transform-typescript](https://www.npmjs.com/package/lab-transform-typescript) module to manage the transform:

```typescript
import * as Lab from 'lab';

const lab = Lab.script();
const { describe, it, before, expect } = lab;
export { lab };

describe('experiment', () => {
before((done) => {
done();
});

// append source map to end of compiled JS
return result.js +
'\n//# sourceMappingURL=data:application/json;base64,' +
Btoa(unescape(encodeURIComponent(result.v3SourceMap)));
}
it('verifies 1 equals 1', (done) => {
expect(1).to.equal(1);
done();
});
});
```

Then the test can be be executed using the following command line:

return content;
} }
];
```sh
$ lab --sourcemaps --transform node_modules/lab-transform-typescript
```

### Disable Code Coverage

Sometimes you want to disable code coverage for specific lines, and have the coverage report omit them entirely. To do so, use the `$lab:coverage:(off|on)$` comments. For example:
```javascript
// There is no way to cover this in node 0.10
Expand All @@ -365,12 +390,12 @@ if (typeof value === 'symbol') {

## `.labrc.js` file

**lab** supports a `.labrc.js` configuration file for centralizing lab settings.
**lab** supports a `.labrc.js` configuration file for centralizing lab settings.
The `.labrc.js` file can be located in the current working directory, any
directory that is the parent of the current working directory, or in the user's
home directory. The `.labrc.js` file needs to be able to be required by
Node.js. Therefore, either format it as a JSON file or with a `module.exports`
that exports an object with the keys that are the settings.
that exports an object with the keys that are the settings.


Below is an example of a `.labrc.js` file to enable linting and test coverage checking:
Expand Down
129 changes: 129 additions & 0 deletions index.d.ts
@@ -0,0 +1,129 @@
declare module 'lab' {
export function script(options?: ScriptOptions): Script;

interface Script {
after: BeforeAfter,
afterEach: BeforeAfter,
before: BeforeAfter,
beforeEach: BeforeAfter
describe: Experiment,
experiment: Experiment,
suite: Experiment,
it: Test,
test: Test,
expect(value: any): Expect
}

type Done = (err?: Error) => void;
type Callback = (done: Done) => void;
type Cleanup = (next: Function) => void;

interface Options {
timeout: number
}

interface BeforeAfter {
(test: Callback): void,
(options: Options, test: Callback): void
}

interface ScriptOptions extends Options {
schedule: boolean
}

interface ExperimentOptions extends Options {
parallel: boolean,
skip: boolean,
only: boolean
}

interface ExperimentOptionsOnlySkip extends Options {
parallel: boolean
}

interface TestOptions extends ExperimentOptions {
plan: number
}

interface TestOptionsOnlySkip extends Options {
parallel: boolean,
plan: number
}

interface TestFunction {
(done: Done),
(done: Done, onCleanup: Cleanup)
}

interface Test {
(title: String, test: TestFunction): void,
(title: String, options: TestOptions, test: TestFunction): void,
only(title: String, test: TestFunction): void,
only(title: String, options: TestOptionsOnlySkip, test: TestFunction): void,
skip(title: String, test: TestFunction): void,
skip(title: String, options: TestOptionsOnlySkip, test: TestFunction): void
}

interface Experiment {
(title: String, tests: Function): void,
(title: String, options: ExperimentOptions, tests: Function): void,
only(title: String, tests: Function): void,
only(title: String, options: ExperimentOptionsOnlySkip, tests: Function): void,
skip(title: String, tests: Function): void,
skip(title: String, options: ExperimentOptionsOnlySkip, tests: Function): void
}

interface Expect {
a: Expect,
an: Expect,
and: Expect,
at: Expect,
be: Expect,
have: Expect,
in: Expect,
to: Expect,
not: Expect,
once: Expect,
part: Expect,
shallow: Expect,
arguments(): void,
array(): void,
boolean(): void,
buffer(): void,
date(): void,
error(type?: Error, message?: String): void,
function(): void,
number(): void,
regexp(): void,
string(): void,
object(): void,
true(): void,
false(): void,
null(): void,
undefined(): void,
NaN(): void,
include(values: any): void,
startWith(value: String): void,
endWith(value: String): void,
exist(): void,
empty(): void,
length(size: Number): void,
equal(value: any, options?: any): void,
above(value: Number): void,
least(value: Number): void,
below(value: Number): void,
most(value: Number): void,
within(from: Number, to: Number): void,
between(from: Number, to: Number): void,
about(value: Number, delta: Number): void,
instanceof(type: any): void,
match(regex: RegExp): void,
satisfy(validator: Function): void,
throw(type?: Error, message?: String): void,
fail(message: String): void,
count(): Number,
incomplete(): Array<String>,
thrownAt(error?: Error): String
}
}