An open API service indexing awesome lists of open source software.

https://github.com/localvoid/iko

[UNMAINTAINED] TypeScript Assertion Library
https://github.com/localvoid/iko

testing typescript

Last synced: about 1 year ago
JSON representation

[UNMAINTAINED] TypeScript Assertion Library

Awesome Lists containing this project

README

          

# TypeScript Assertion Library

This library and its API is designed to provide a good developer experience in TypeScript environment, so it is
recommended only for TypeScript developers.

![iko screenshot][screenshot]

## Features

- TypeScript-friendly API
- Nicely formatted error messages in a [rtext](https://github.com/localvoid/rtext) format
- Side-effect free assertions
- Using [lodash](https://lodash.com) deep equality and matching functions
- Snapshot testing in a browser

## Packages

- [iko](https://www.npmjs.com/package/iko) Assertion library.
- [iko-karma-snapshot](https://www.npmjs.com/package/iko-karma-snapshot) Support for
[karma-snapshot](https://github.com/localvoid/karma-snapshot) plugin.
- [karma-iko](https://www.npmjs.com/package/karma-iko) Improved [Mocha](https://mochajs.org) adapter and reporter for
[Karma](https://karma-runner.github.io/).
- [mocha-iko-reporter](https://www.npmjs.com/package/mocha-iko-reporter) Improved [Mocha](https://mochajs.org) reporter.

## Namespaces for different Types

When `expect(obj)` function is invoked, it will return different `Assertion` depending on its type.

In order for compiler to get correct type when `expect(obj)` is invoked, we are using [function overloading](https://www.typescriptlang.org/docs/handbook/functions.html).

```ts
function expect(obj: null): NullAssertion;
function expect(obj: undefined): UndefinedAssertion;
function expect(obj: void): UndefinedAssertion;
function expect(obj: number): NumberAssertion;
function expect(obj: boolean): BooleanAssertion;
function expect(obj: string): StringAssertion;
function expect(obj: symbol): SymbolAssertion;
function expect(obj: Function): FunctionAssertion;
function expect(obj: Array): ArrayAssertion;
function expect(obj: Date): DateAssertion;
function expect(obj: RegExp): RegExpAssertion;
function expect(obj: Map): MapAssertion;
function expect(obj: WeakMap): WeakMapAssertion;
function expect(obj: Set): SetAssertion;
function expect(obj: WeakSet): WeakSetAssertion;
function expect(obj: E): ErrorAssertion;
function expect(obj: T): ObjectAssertion;
function expect(obj: any): Assertion;
```

### Adding your own type

```ts
import { Assertion, addAssertionType } from "iko";
import { MyType } from "./mylib";

declare module "iko" {
function expect(obj: MyType): MyTypeAssertion;
}

addAssertionType((obj: any) => {
if (typeof obj === "object" && obj instanceof MyType) {
return new MyTypeAssertion(obj);
}
return undefined;
}):

export class MyTypeAssertion extends Assertion {
// ...
}
```

### Extending existing namespaces

```ts
import { Assertion, mh, r } from "iko";
import { richText } from "rtext-writer";

declare module "iko" {
interface Assertion {
toBeMyType(): MyTypeAssertion;
}
}

Assertion.prototype.toBeMyType = function(
message?: ErrorMessage,
): MyTypeAssertion {
const received = this.obj;
const pass = typeof received === "object" && obj instanceof MyType;
if (!pass) {
const message = richText()
.write(mh("toBeMyType", "received", ""))
.write("Expected Object to have MyType type:\n")
.write(" ", r(received));

throw new AssertionError(message.compose(), received, "MyType", this.toBeMyType);
}

return this as any as MyTypeAssertion;
}
```

## API

```ts
class Assertion {
readonly obj: T;

constructor(obj: T);

toSnapshot(): string | { lang?: string, code: string };

assert(
expr: (() => boolean) | boolean,
message: (expected: E, actual?: T) => RichText,
expected: E,
actual?: T,
): this;

toBeFalsy(): this;
toBeTruthy(): this;
toBe(value: T): this;
toBeNull(): NullAssertion;
toBeUndefined(): UndefinedAssertion;
toBeInstanceOf(type: Function): this;

notToBe(value: T): this;
notToBeNull(): this;
notToBeUndefined(): this;
notToBeInstanceOf(type: Function): this;

toBeObject(): ObjectAssertion;
toBeArray(): ArrayAssertion;
toBeBoolean(): BooleanAssertion;
toBeNumber(): NumberAssertion;
toBeString(): StringAssertion;
toBeFunction(): FunctionAssertion;
toBeSymbol(): SymbolAssertion;
toBeDate(): DateAssertion;
toBeRegExp(): RegExpAssertion;
toBeError(): ErrorAssertion;
toBeMap(): MapAssertion;
toBeWeakMap(): WeakMapAssertion;
toBeSet(): SetAssertion;
toBeWeakSet(): WeakSetAssertion;
}

class NullAssertion extends Assertion { }

class UndefinedAssertion extends Assertion { }

class BooleanAssertion extends Assertion { }

class FunctionAssertion extends Assertion {
toHaveArgumentsLength(length: number): this;
toThrow(expected?: string | E): this;

notToHaveArgumentsLength(length: number): this;
notToThrow(expected?: string | E): this;
}

class NumberAssertion extends Assertion {
toBeApproximatelyEqual(number: number, epsilon = Number.EPSILON): this;
toBeEssentiallyEqual(number: number, epsilon = Number.EPSILON): this;
toBeDefinetelyGreaterThan(number: number, epsilon = Number.EPSILON): this;
toBeDefinetelyLessThan(number: number, epsilon = Number.EPSILON): this;
toBeGreaterThan(number: number): this;
toBeGreaterThanOrEqual(number: number): this;
toBeLessThan(number: number): this;
toBeLessThanOrEqual(number: number): this;
toBeNaN(): this;

notToBeApproximatelyEqual(number: number, epsilon = Number.EPSILON): this;
notToBeEssentiallyEqual(number: number, epsilon = Number.EPSILON): this;
notToBeDefinetelyGreaterThan(number: number, epsilon = Number.EPSILON): this;
notToBeDefinetelyLessThan(number: number, epsilon = Number.EPSILON): this;
notToBeGreaterThan(number: number): this;
notToBeGreaterThanOrEqual(number: number): this;
notToBeLessThan(number: number): this;
notToBeLessThanOrEqual(number: number): this;
notToBeNaN(): this;
}

class StringAssertion extends Assertion {
toHaveLength(length: number): this;
toInclude(text: string): this;
toMatch(text: string | RegExp): this;

notToHaveLength(length: number): this;
notToInclude(text: string): this;
notToMatch(text: string | RegExp): this;
}

class SymbolAssertion extends Assertion { }

class ObjectAssertion extends Assertion {
readonly type: string;

constructor(obj: T, type = "object");

toBeEqual(expected: T): this;
toBeEqualWith(expected: T, customizer: isMatchCustomizer): this;
toMatch(expected: any): this;
toMatchWith(expected: any, customizer: isMatchCustomizer): this;

notToBeEqual(expected: T): this;
notToBeEqualWith(expected: T, customizer: isMatchCustomizer): this;
notToMatch(expected: any): this;
notToMatchWith(expected: any, customizer: isMatchCustomizer): this;
}

class ArrayAssertion extends ObjectAssertion {
toHaveLength(length: number): this;
notToHaveLength(length: number): this;
toContain(value: T): this;
notToContain(value: T): this;
}

class DateAssertion extends ObjectAssertion { }

class ErrorAssertion extends ObjectAssertion { }

class RegExpAssertion extends ObjectAssertion {
toTest(text: string): this;

notToTest(text: string): this;
}

class MapAssertion extends ObjectAssertion> {
toHaveSize(size: number): this;
toHave(key: K): this;

notToHaveSize(size: number): this;
notToHave(key: K): this;
}

class SetAssertion extends ObjectAssertion> {
toHaveSize(size: number): this;
toHave(value: V): this;

notToHaveSize(size: number): this;
notToHave(value: V): this;
}

class WeakMapAssertion extends ObjectAssertion> {
toHave(key: K): this;

notToHave(key: K): this;
}

class WeakSetAssertion extends ObjectAssertion> {
toHave(value: V): this;

notToHave(value: V): this;
}
```

## License

MIT

[screenshot]: https://localvoid.github.io/karma-snapshot/images/example.png "iko screenshot"