{"id":21654625,"url":"https://github.com/localvoid/iko","last_synced_at":"2026-05-21T07:35:16.610Z","repository":{"id":57271790,"uuid":"98081732","full_name":"localvoid/iko","owner":"localvoid","description":"[UNMAINTAINED] TypeScript Assertion Library","archived":false,"fork":false,"pushed_at":"2018-04-29T07:01:20.000Z","size":81,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-17T05:38:35.520Z","etag":null,"topics":["testing","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/localvoid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-23T07:27:22.000Z","updated_at":"2020-04-07T06:23:35.000Z","dependencies_parsed_at":"2022-09-09T02:02:19.644Z","dependency_job_id":null,"html_url":"https://github.com/localvoid/iko","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localvoid%2Fiko","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localvoid%2Fiko/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localvoid%2Fiko/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localvoid%2Fiko/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/localvoid","download_url":"https://codeload.github.com/localvoid/iko/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244554121,"owners_count":20471173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["testing","typescript"],"created_at":"2024-11-25T08:28:28.548Z","updated_at":"2026-05-21T07:35:11.574Z","avatar_url":"https://github.com/localvoid.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TypeScript Assertion Library\n\nThis library and its API is designed to provide a good developer experience in TypeScript environment, so it is\nrecommended only for TypeScript developers.\n\n![iko screenshot][screenshot]\n\n## Features\n\n- TypeScript-friendly API\n- Nicely formatted error messages in a [rtext](https://github.com/localvoid/rtext) format\n- Side-effect free assertions\n- Using [lodash](https://lodash.com) deep equality and matching functions\n- Snapshot testing in a browser\n\n## Packages\n\n- [iko](https://www.npmjs.com/package/iko) Assertion library.\n- [iko-karma-snapshot](https://www.npmjs.com/package/iko-karma-snapshot) Support for\n[karma-snapshot](https://github.com/localvoid/karma-snapshot) plugin.\n- [karma-iko](https://www.npmjs.com/package/karma-iko) Improved [Mocha](https://mochajs.org) adapter and reporter for\n[Karma](https://karma-runner.github.io/).\n- [mocha-iko-reporter](https://www.npmjs.com/package/mocha-iko-reporter) Improved [Mocha](https://mochajs.org) reporter.\n\n## Namespaces for different Types\n\nWhen `expect(obj)` function is invoked, it will return different `Assertion` depending on its type.\n\nIn 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).\n\n```ts\nfunction expect(obj: null): NullAssertion;\nfunction expect(obj: undefined): UndefinedAssertion;\nfunction expect(obj: void): UndefinedAssertion;\nfunction expect(obj: number): NumberAssertion;\nfunction expect(obj: boolean): BooleanAssertion;\nfunction expect(obj: string): StringAssertion;\nfunction expect(obj: symbol): SymbolAssertion;\nfunction expect(obj: Function): FunctionAssertion;\nfunction expect\u003cT\u003e(obj: Array\u003cT\u003e): ArrayAssertion\u003cT\u003e;\nfunction expect(obj: Date): DateAssertion;\nfunction expect(obj: RegExp): RegExpAssertion;\nfunction expect\u003cK, V\u003e(obj: Map\u003cK, V\u003e): MapAssertion\u003cK, V\u003e;\nfunction expect\u003cK extends object, V\u003e(obj: WeakMap\u003cK, V\u003e): WeakMapAssertion\u003cK, V\u003e;\nfunction expect\u003cV\u003e(obj: Set\u003cV\u003e): SetAssertion\u003cV\u003e;\nfunction expect\u003cV\u003e(obj: WeakSet\u003cV\u003e): WeakSetAssertion\u003cV\u003e;\nfunction expect\u003cE extends Error\u003e(obj: E): ErrorAssertion\u003cE\u003e;\nfunction expect\u003cT extends object\u003e(obj: T): ObjectAssertion\u003cT\u003e;\nfunction expect(obj: any): Assertion\u003cany\u003e;\n```\n\n### Adding your own type\n\n```ts\nimport { Assertion, addAssertionType } from \"iko\";\nimport { MyType } from \"./mylib\";\n\ndeclare module \"iko\" {\n  function expect(obj: MyType): MyTypeAssertion;\n}\n\naddAssertionType((obj: any) =\u003e {\n  if (typeof obj === \"object\" \u0026\u0026 obj instanceof MyType) {\n    return new MyTypeAssertion(obj);\n  }\n  return undefined;\n}):\n\nexport class MyTypeAssertion extends Assertion\u003cMyType\u003e {\n  // ...\n}\n```\n\n### Extending existing namespaces\n\n```ts\nimport { Assertion, mh, r } from \"iko\";\nimport { richText } from \"rtext-writer\";\n\ndeclare module \"iko\" {\n  interface Assertion\u003cT\u003e {\n    toBeMyType(): MyTypeAssertion;\n  }\n}\n\nAssertion.prototype.toBeMyType = function(\n  message?: ErrorMessage\u003cstring, MyType\u003e,\n): MyTypeAssertion {\n  const received = this.obj;\n  const pass = typeof received === \"object\" \u0026\u0026 obj instanceof MyType;\n  if (!pass) {\n    const message = richText()\n      .write(mh(\"toBeMyType\", \"received\", \"\"))\n      .write(\"Expected Object to have MyType type:\\n\")\n      .write(\"  \", r(received));\n\n    throw new AssertionError(message.compose(), received, \"MyType\", this.toBeMyType);\n  }\n\n  return this as any as MyTypeAssertion;\n}\n```\n\n## API\n\n```ts\nclass Assertion\u003cT\u003e {\n  readonly obj: T;\n\n  constructor(obj: T);\n\n  toSnapshot(): string | { lang?: string, code: string };\n\n  assert\u003cE\u003e(\n    expr: (() =\u003e boolean) | boolean,\n    message: (expected: E, actual?: T) =\u003e RichText,\n    expected: E,\n    actual?: T,\n  ): this;\n\n  toBeFalsy(): this;\n  toBeTruthy(): this;\n  toBe(value: T): this;\n  toBeNull(): NullAssertion;\n  toBeUndefined(): UndefinedAssertion;\n  toBeInstanceOf(type: Function): this;\n\n  notToBe(value: T): this;\n  notToBeNull(): this;\n  notToBeUndefined(): this;\n  notToBeInstanceOf(type: Function): this;\n\n  toBeObject\u003cO extends object\u003e(): ObjectAssertion\u003cO\u003e;\n  toBeArray\u003cU\u003e(): ArrayAssertion\u003cU\u003e;\n  toBeBoolean(): BooleanAssertion;\n  toBeNumber(): NumberAssertion;\n  toBeString(): StringAssertion;\n  toBeFunction(): FunctionAssertion;\n  toBeSymbol(): SymbolAssertion;\n  toBeDate(): DateAssertion;\n  toBeRegExp(): RegExpAssertion;\n  toBeError\u003cE extends Error\u003e(): ErrorAssertion\u003cE\u003e;\n  toBeMap\u003cK extends object = any, V = any\u003e(): MapAssertion\u003cK, V\u003e;\n  toBeWeakMap\u003cK extends object = any, V = any\u003e(): WeakMapAssertion\u003cK, V\u003e;\n  toBeSet\u003cV = any\u003e(): SetAssertion\u003cV\u003e;\n  toBeWeakSet\u003cV = any\u003e(): WeakSetAssertion\u003cV\u003e;\n}\n\nclass NullAssertion extends Assertion\u003cnull\u003e { }\n\nclass UndefinedAssertion extends Assertion\u003cundefined\u003e { }\n\nclass BooleanAssertion extends Assertion\u003cboolean\u003e { }\n\nclass FunctionAssertion extends Assertion\u003cFunction\u003e {\n  toHaveArgumentsLength(length: number): this;\n  toThrow\u003cE extends Error | ErrorConstructor\u003e(expected?: string | E): this;\n\n  notToHaveArgumentsLength(length: number): this;\n  notToThrow\u003cE extends Error | ErrorConstructor\u003e(expected?: string | E): this;\n}\n\nclass NumberAssertion extends Assertion\u003cnumber\u003e {\n  toBeApproximatelyEqual(number: number, epsilon = Number.EPSILON): this;\n  toBeEssentiallyEqual(number: number, epsilon = Number.EPSILON): this;\n  toBeDefinetelyGreaterThan(number: number, epsilon = Number.EPSILON): this;\n  toBeDefinetelyLessThan(number: number, epsilon = Number.EPSILON): this;\n  toBeGreaterThan(number: number): this;\n  toBeGreaterThanOrEqual(number: number): this;\n  toBeLessThan(number: number): this;\n  toBeLessThanOrEqual(number: number): this;\n  toBeNaN(): this;\n\n  notToBeApproximatelyEqual(number: number, epsilon = Number.EPSILON): this;\n  notToBeEssentiallyEqual(number: number, epsilon = Number.EPSILON): this;\n  notToBeDefinetelyGreaterThan(number: number, epsilon = Number.EPSILON): this;\n  notToBeDefinetelyLessThan(number: number, epsilon = Number.EPSILON): this;\n  notToBeGreaterThan(number: number): this;\n  notToBeGreaterThanOrEqual(number: number): this;\n  notToBeLessThan(number: number): this;\n  notToBeLessThanOrEqual(number: number): this;\n  notToBeNaN(): this;\n}\n\nclass StringAssertion extends Assertion\u003cstring\u003e {\n  toHaveLength(length: number): this;\n  toInclude(text: string): this;\n  toMatch(text: string | RegExp): this;\n\n  notToHaveLength(length: number): this;\n  notToInclude(text: string): this;\n  notToMatch(text: string | RegExp): this;\n}\n\nclass SymbolAssertion extends Assertion\u003cSymbol\u003e { }\n\nclass ObjectAssertion\u003cT extends object\u003e extends Assertion\u003cT\u003e {\n  readonly type: string;\n\n  constructor(obj: T, type = \"object\");\n\n  toBeEqual(expected: T): this;\n  toBeEqualWith(expected: T, customizer: isMatchCustomizer): this;\n  toMatch(expected: any): this;\n  toMatchWith(expected: any, customizer: isMatchCustomizer): this;\n\n  notToBeEqual(expected: T): this;\n  notToBeEqualWith(expected: T, customizer: isMatchCustomizer): this;\n  notToMatch(expected: any): this;\n  notToMatchWith(expected: any, customizer: isMatchCustomizer): this;\n}\n\nclass ArrayAssertion\u003cT\u003e extends ObjectAssertion\u003cT[]\u003e {\n  toHaveLength(length: number): this;\n  notToHaveLength(length: number): this;\n  toContain(value: T): this;\n  notToContain(value: T): this;\n}\n\nclass DateAssertion extends ObjectAssertion\u003cDate\u003e { }\n\nclass ErrorAssertion\u003cE extends Error\u003e extends ObjectAssertion\u003cE\u003e { }\n\nclass RegExpAssertion extends ObjectAssertion\u003cRegExp\u003e {\n  toTest(text: string): this;\n\n  notToTest(text: string): this;\n}\n\nclass MapAssertion\u003cK, V\u003e extends ObjectAssertion\u003cMap\u003cK, V\u003e\u003e {\n  toHaveSize(size: number): this;\n  toHave(key: K): this;\n\n  notToHaveSize(size: number): this;\n  notToHave(key: K): this;\n}\n\nclass SetAssertion\u003cV\u003e extends ObjectAssertion\u003cSet\u003cV\u003e\u003e {\n  toHaveSize(size: number): this;\n  toHave(value: V): this;\n\n  notToHaveSize(size: number): this;\n  notToHave(value: V): this;\n}\n\nclass WeakMapAssertion\u003cK extends object, V\u003e extends ObjectAssertion\u003cWeakMap\u003cK, V\u003e\u003e {\n  toHave(key: K): this;\n\n  notToHave(key: K): this;\n}\n\nclass WeakSetAssertion\u003cV\u003e extends ObjectAssertion\u003cWeakSet\u003cV\u003e\u003e {\n  toHave(value: V): this;\n\n  notToHave(value: V): this;\n}\n```\n\n## License\n\nMIT\n\n[screenshot]: https://localvoid.github.io/karma-snapshot/images/example.png \"iko screenshot\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalvoid%2Fiko","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flocalvoid%2Fiko","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalvoid%2Fiko/lists"}