Skip to content

Commit

Permalink
feat(expect, @jest/expect-utils): allow isA utility to take a type …
Browse files Browse the repository at this point in the history
…argument (#13355)
  • Loading branch information
mrazauskas committed Oct 2, 2022
1 parent 8759d63 commit d75433d
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
### Features

- `[jest-core]` Enable testResultsProcessor to be async ([#13343](https://github.com/facebook/jest/pull/13343))
- `[expect, @jest/expect-utils]` Allow `isA` utility to take a type argument ([#13355](https://github.com/facebook/jest/pull/13355))

### Fixes

Expand Down
12 changes: 12 additions & 0 deletions packages/expect-utils/__typetests__/tsconfig.json
@@ -0,0 +1,12 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"composite": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"skipLibCheck": true,

"types": []
},
"include": ["./**/*"]
}
38 changes: 38 additions & 0 deletions packages/expect-utils/__typetests__/utils.test.ts
@@ -0,0 +1,38 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {expectType} from 'tsd-lite';
import {isA} from '@jest/expect-utils';

// isA

expectType<boolean>(isA('String', 'default'));
expectType<boolean>(isA<number>('Number', 123));

const sample = {} as unknown;

expectType<unknown>(sample);

if (isA('String', sample)) {
expectType<unknown>(sample);
}

if (isA<string>('String', sample)) {
expectType<string>(sample);
}

if (isA<number>('Number', sample)) {
expectType<number>(sample);
}

if (isA<Map<unknown, unknown>>('Map', sample)) {
expectType<Map<unknown, unknown>>(sample);
}

if (isA<Set<unknown>>('Set', sample)) {
expectType<Set<unknown>>(sample);
}
4 changes: 3 additions & 1 deletion packages/expect-utils/package.json
Expand Up @@ -20,8 +20,10 @@
"jest-get-type": "workspace:^"
},
"devDependencies": {
"@tsd/typescript": "~4.8.2",
"immutable": "^4.0.0",
"jest-matcher-utils": "workspace:^"
"jest-matcher-utils": "workspace:^",
"tsd-lite": "^0.6.0"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
Expand Down
15 changes: 4 additions & 11 deletions packages/expect-utils/src/jasmineUtils.ts
Expand Up @@ -224,7 +224,7 @@ function hasKey(obj: any, key: string) {
return Object.prototype.hasOwnProperty.call(obj, key);
}

export function isA(typeName: string, value: unknown) {
export function isA<T>(typeName: string, value: unknown): value is T {
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
}

Expand Down Expand Up @@ -262,10 +262,7 @@ export function isImmutableUnorderedSet(maybeSet: any) {
}

export function isImmutableList(maybeList: any) {
return !!(
maybeList &&
maybeList[IS_LIST_SENTINEL]
);
return !!(maybeList && maybeList[IS_LIST_SENTINEL]);
}

export function isImmutableOrderedKeyed(maybeKeyed: any) {
Expand All @@ -276,7 +273,6 @@ export function isImmutableOrderedKeyed(maybeKeyed: any) {
);
}


export function isImmutableOrderedSet(maybeSet: any) {
return !!(
maybeSet &&
Expand All @@ -286,8 +282,5 @@ export function isImmutableOrderedSet(maybeSet: any) {
}

export function isImmutableRecord(maybeSet: any) {
return !!(
maybeSet &&
maybeSet[IS_RECORD_SYMBOL]
);
}
return !!(maybeSet && maybeSet[IS_RECORD_SYMBOL]);
}
7 changes: 5 additions & 2 deletions packages/expect-utils/src/utils.ts
Expand Up @@ -184,7 +184,7 @@ export const iterableEquality = (
if (a.size !== undefined) {
if (a.size !== b.size) {
return false;
} else if (isA('Set', a) || isImmutableUnorderedSet(a)) {
} else if (isA<Set<unknown>>('Set', a) || isImmutableUnorderedSet(a)) {
let allFound = true;
for (const aValue of a) {
if (!b.has(aValue)) {
Expand All @@ -206,7 +206,10 @@ export const iterableEquality = (
aStack.pop();
bStack.pop();
return allFound;
} else if (isA('Map', a) || isImmutableUnorderedKeyed(a)) {
} else if (
isA<Map<unknown, unknown>>('Map', a) ||
isImmutableUnorderedKeyed(a)
) {
let allFound = true;
for (const aEntry of a) {
if (
Expand Down
15 changes: 8 additions & 7 deletions packages/expect/src/asymmetricMatchers.ts
Expand Up @@ -185,7 +185,7 @@ class ArrayContaining extends AsymmetricMatcher<Array<unknown>> {
super(sample, inverse);
}

asymmetricMatch(other: Array<unknown>) {
asymmetricMatch(other: unknown) {
if (!Array.isArray(this.sample)) {
throw new Error(
`You must provide an array to ${this.toString()}, not '${typeof this
Expand Down Expand Up @@ -257,8 +257,8 @@ class StringContaining extends AsymmetricMatcher<string> {
super(sample, inverse);
}

asymmetricMatch(other: string) {
const result = isA('String', other) && other.includes(this.sample);
asymmetricMatch(other: unknown) {
const result = isA<string>('String', other) && other.includes(this.sample);

return this.inverse ? !result : result;
}
Expand All @@ -280,8 +280,8 @@ class StringMatching extends AsymmetricMatcher<RegExp> {
super(new RegExp(sample), inverse);
}

asymmetricMatch(other: string) {
const result = isA('String', other) && this.sample.test(other);
asymmetricMatch(other: unknown) {
const result = isA<string>('String', other) && this.sample.test(other);

return this.inverse ? !result : result;
}
Expand All @@ -297,6 +297,7 @@ class StringMatching extends AsymmetricMatcher<RegExp> {

class CloseTo extends AsymmetricMatcher<number> {
private precision: number;

constructor(sample: number, precision = 2, inverse = false) {
if (!isA('Number', sample)) {
throw new Error('Expected is not a Number');
Expand All @@ -311,8 +312,8 @@ class CloseTo extends AsymmetricMatcher<number> {
this.precision = precision;
}

asymmetricMatch(other: number) {
if (!isA('Number', other)) {
asymmetricMatch(other: unknown) {
if (!isA<number>('Number', other)) {
return false;
}
let result = false;
Expand Down
2 changes: 2 additions & 0 deletions yarn.lock
Expand Up @@ -2695,9 +2695,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "@jest/expect-utils@workspace:packages/expect-utils"
dependencies:
"@tsd/typescript": ~4.8.2
immutable: ^4.0.0
jest-get-type: "workspace:^"
jest-matcher-utils: "workspace:^"
tsd-lite: ^0.6.0
languageName: unknown
linkType: soft

Expand Down

0 comments on commit d75433d

Please sign in to comment.