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
- Host: GitHub
- URL: https://github.com/localvoid/iko
- Owner: localvoid
- License: mit
- Created: 2017-07-23T07:27:22.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2018-04-29T07:01:20.000Z (almost 8 years ago)
- Last Synced: 2025-03-17T05:38:35.520Z (about 1 year ago)
- Topics: testing, typescript
- Language: TypeScript
- Homepage:
- Size: 79.1 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
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"