diff --git a/README.md b/README.md index a2d531b..137fb4f 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Mocking library for TypeScript inspired by http://mockito.org/ * `thenThrow` - throw an error * `thenCall` - call custom method * Checking if methods were called with given arguments (`verify`) - * `anything`, `notNull`, `anyString`, `anyOfClass` etc. - for more flexible comparision + * `anything`, `notNull`, `anyString`, `anyOfClass`, `not` etc. - for more flexible comparision * `once`, `twice`, `times`, `atLeast` etc. - allows call count verification * `calledBefore`, `calledAfter` - allows call order verification * Resetting mock (`reset`, `resetCalls`) @@ -105,13 +105,16 @@ foo.getBar(2); foo.getBar(3); // Call count verification -verify(mockedFoo.getBar(1)).once(); // was called with arg === 1 only once -verify(mockedFoo.getBar(2)).twice(); // was called with arg === 2 exactly two times -verify(mockedFoo.getBar(between(2, 3))).thrice(); // was called with arg beween 2-3 exactly three times -verify(mockedFoo.getBar(anyNumber()).times(4); // was called with any number arg exactly four times -verify(mockedFoo.getBar(2)).atLeast(2); // was called with arg === 2 min two times -verify(mockedFoo.getBar(1)).atMost(1); // was called with arg === 1 max one time -verify(mockedFoo.getBar(4)).never(); // was never called with arg === 4 +verify(mockedFoo.getBar(1)).once(); // was called with arg === 1 only once +verify(mockedFoo.getBar(2)).twice(); // was called with arg === 2 exactly two times +verify(mockedFoo.getBar(not().strictEqual(2))).once(); // was called with anything except 2 once +verify(mockedFoo.getBar(between(2, 3))).thrice(); // was called with arg beween 2-3 exactly three times +verify(mockedFoo.getBar(anyNumber()).times(4); // was called with any number arg exactly four times +verify(mockedFoo.getBar(not().anyNumber()).times(4); // was called with anything but not a number exactly four times +verify(mockedFoo.match(/param\d+/)).once(); // was once called with arg matching regexp +verify(mockedFoo.getBar(2)).atLeast(2); // was called with arg === 2 min two times +verify(mockedFoo.getBar(1)).atMost(1); // was called with arg === 1 max one time +verify(mockedFoo.getBar(4)).never(); // was never called with arg === 4 ``` ### Call order verification @@ -159,7 +162,7 @@ let mockedFoo:Foo = mock(Foo); let foo:Foo = instance(mockedFoo); when(mockedFoo.sumTwoNumbers(anyNumber(), anyNumber())).thenCall((arg1:number, arg2:number) => { - return arg1 * arg2; + return arg1 * arg2; }); // prints '50' because we've changed sum method implementation to multiply! @@ -335,13 +338,13 @@ const spiedFoo = spy(foo); foo.bar(); -console.log(capture(spiedFoo.bar).last()); // [42] +console.log(capture(spiedFoo.bar).last()); // [42] ``` ### Thanks -* Szczepan Faber (https://www.linkedin.com/in/szczepiq) -* Sebastian Konkol (https://www.linkedin.com/in/sebastiankonkol) +* Szczepan Faber (https://www.linkedin.com/in/szczepiq) +* Sebastian Konkol (https://www.linkedin.com/in/sebastiankonkol) * Clickmeeting (http://clickmeeting.com) * Michał Stocki (https://github.com/michalstocki) * Łukasz Bendykowski (https://github.com/viman) diff --git a/src/matcher/type/AnyFunctionMatcher.ts b/src/matcher/type/AnyFunctionMatcher.ts index bf9a1b9..bf1592f 100644 --- a/src/matcher/type/AnyFunctionMatcher.ts +++ b/src/matcher/type/AnyFunctionMatcher.ts @@ -7,10 +7,10 @@ export class AnyFunctionMatcher extends Matcher { } public match(value: any): boolean { - return _.isFunction(value); + return this.reverseResult(_.isFunction(value)); } public toString(): string { - return "anyFunction()"; + return `${this.prefix}anyFunction()`; } } diff --git a/src/matcher/type/AnyNumberMatcher.ts b/src/matcher/type/AnyNumberMatcher.ts index 9a69149..ecad65e 100644 --- a/src/matcher/type/AnyNumberMatcher.ts +++ b/src/matcher/type/AnyNumberMatcher.ts @@ -7,10 +7,10 @@ export class AnyNumberMatcher extends Matcher { } public match(value: any): boolean { - return _.isNumber(value); + return this.reverseResult(_.isNumber(value)); } public toString(): string { - return "anyNumber()"; + return `${this.prefix}anyNumber()`; } } diff --git a/src/matcher/type/AnyOfClassMatcher.ts b/src/matcher/type/AnyOfClassMatcher.ts index a4098de..6515368 100644 --- a/src/matcher/type/AnyOfClassMatcher.ts +++ b/src/matcher/type/AnyOfClassMatcher.ts @@ -9,10 +9,10 @@ export class AnyOfClassMatcher extends Matcher { } public match(value: any): boolean { - return value instanceof this.expectedClass; + return this.reverseResult(value instanceof this.expectedClass); } public toString() { - return `anyOfClass(${this.expectedClass["name"]})`; + return `${this.prefix}anyOfClass(${this.expectedClass["name"]})`; } } diff --git a/src/matcher/type/AnyStringMatcher.ts b/src/matcher/type/AnyStringMatcher.ts index efbab75..2437a27 100644 --- a/src/matcher/type/AnyStringMatcher.ts +++ b/src/matcher/type/AnyStringMatcher.ts @@ -7,10 +7,10 @@ export class AnyStringMatcher extends Matcher { } public match(value: any): boolean { - return _.isString(value); + return this.reverseResult(_.isString(value)); } public toString(): string { - return "anyString()"; + return `${this.prefix}anyString()`; } } diff --git a/src/matcher/type/AnythingMatcher.ts b/src/matcher/type/AnythingMatcher.ts index b273ced..b6de219 100644 --- a/src/matcher/type/AnythingMatcher.ts +++ b/src/matcher/type/AnythingMatcher.ts @@ -6,10 +6,10 @@ export class AnythingMatcher extends Matcher { } public match(value: any): boolean { - return true; + return this.reverseResult(true); } public toString(): string { - return "anything()"; + return `${this.prefix}anything()`; } } diff --git a/src/matcher/type/BetweenMatcher.ts b/src/matcher/type/BetweenMatcher.ts index 5a8bc56..65c2d0c 100644 --- a/src/matcher/type/BetweenMatcher.ts +++ b/src/matcher/type/BetweenMatcher.ts @@ -10,10 +10,10 @@ export class BetweenMatcher extends Matcher { } public match(value: any): boolean { - return value >= this.min && value <= this.max; + return this.reverseResult(value >= this.min && value <= this.max); } public toString(): string { - return `between(${this.min}, ${this.max})`; + return `${this.prefix}between(${this.min}, ${this.max})`; } } diff --git a/src/matcher/type/DeepEqualMatcher.ts b/src/matcher/type/DeepEqualMatcher.ts index 544cb67..b8a9c93 100644 --- a/src/matcher/type/DeepEqualMatcher.ts +++ b/src/matcher/type/DeepEqualMatcher.ts @@ -7,7 +7,7 @@ export class DeepEqualMatcher extends Matcher { } public match(value: any): boolean { - return _.isEqualWith(this.expectedValue, value, + const result = _.isEqualWith(this.expectedValue, value, (expected: any, actual: any): boolean => { if (expected instanceof Matcher) { return expected.match(actual); @@ -15,13 +15,14 @@ export class DeepEqualMatcher extends Matcher { return undefined; }); + return this.reverseResult(result); } public toString(): string { if (this.expectedValue instanceof Array) { - return `deepEqual([${this.expectedValue}])`; + return `${this.prefix}deepEqual([${this.expectedValue}])`; } else { - return `deepEqual(${this.expectedValue})`; + return `${this.prefix}deepEqual(${this.expectedValue})`; } } } diff --git a/src/matcher/type/MatchingStringMatcher.ts b/src/matcher/type/MatchMatcher.ts similarity index 52% rename from src/matcher/type/MatchingStringMatcher.ts rename to src/matcher/type/MatchMatcher.ts index 2806500..af6069d 100644 --- a/src/matcher/type/MatchingStringMatcher.ts +++ b/src/matcher/type/MatchMatcher.ts @@ -1,15 +1,15 @@ import {Matcher} from "./Matcher"; -export class MatchingStringMatcher extends Matcher { +export class MatchMatcher extends Matcher { constructor(private expectedValue: any) { super(); } public match(value: any): boolean { - return value.match(this.expectedValue); + return this.reverseResult(value.match(this.expectedValue)); } public toString(): string { - return `match(${this.expectedValue})`; + return `${this.prefix}match(${this.expectedValue})`; } } diff --git a/src/matcher/type/Matcher.ts b/src/matcher/type/Matcher.ts index 87bbc83..7ffe582 100644 --- a/src/matcher/type/Matcher.ts +++ b/src/matcher/type/Matcher.ts @@ -1,9 +1,24 @@ export class Matcher { - public match(value: any): boolean { - return false; + private isNot: boolean = false; + + public match(...values: any[]): boolean { + return this.reverseResult(false); } public toString(): string { - return ""; + return `${this.prefix}`; + } + + public reverse() { + this.isNot = true; + return this; + } + + protected get prefix(): string { + return this.isNot ? "not()." : ""; + } + + protected reverseResult(result: boolean): boolean { + return this.isNot ? !result : result; } } diff --git a/src/matcher/type/Not.ts b/src/matcher/type/Not.ts new file mode 100644 index 0000000..272c51a --- /dev/null +++ b/src/matcher/type/Not.ts @@ -0,0 +1,60 @@ +import {AnyFunctionMatcher} from "./AnyFunctionMatcher"; +import {AnyNumberMatcher} from "./AnyNumberMatcher"; +import {AnyOfClassMatcher} from "./AnyOfClassMatcher"; +import {AnyStringMatcher} from "./AnyStringMatcher"; +import {AnythingMatcher} from "./AnythingMatcher"; +import {BetweenMatcher} from "./BetweenMatcher"; +import {DeepEqualMatcher} from "./DeepEqualMatcher"; +import {Matcher} from "./Matcher"; +import {MatchMatcher} from "./MatchMatcher"; +import {NotNullMatcher} from "./NotNullMatcher"; +import {ObjectContainingMatcher} from "./ObjectContainingMatcher"; +import {StrictEqualMatcher} from "./StrictEqualMatcher"; + +export class Not { + + public anyOfClass(expectedClass: {new (...args: any[]): T}): Matcher { + return (new AnyOfClassMatcher(expectedClass)).reverse(); + } + + public anyFunction(): Matcher { + return (new AnyFunctionMatcher()).reverse(); + } + + public anyNumber(): Matcher { + return (new AnyNumberMatcher()).reverse(); + } + + public anyString(): Matcher { + return (new AnyStringMatcher()).reverse(); + } + + public anything(): Matcher { + return (new AnythingMatcher()).reverse(); + } + + public between(min: number, max: number): Matcher { + return (new BetweenMatcher(min, max)).reverse(); + } + + public deepEqual(expectedValue: any): Matcher { + return (new DeepEqualMatcher(expectedValue)).reverse(); + } + + public notNull(): Matcher { + return (new NotNullMatcher()).reverse(); + } + + public strictEqual(expectedValue: any): Matcher { + return (new StrictEqualMatcher(expectedValue)).reverse(); + } + + public match(expectedValue: string | RegExp): Matcher { + return (new MatchMatcher(expectedValue)).reverse(); + } + + public objectContaining(expectedValue: Object): Matcher { + return (new ObjectContainingMatcher(expectedValue)).reverse(); + } + +} diff --git a/src/matcher/type/NotNullMatcher.ts b/src/matcher/type/NotNullMatcher.ts index 1337a63..dd528b4 100644 --- a/src/matcher/type/NotNullMatcher.ts +++ b/src/matcher/type/NotNullMatcher.ts @@ -3,10 +3,10 @@ import {Matcher} from "./Matcher"; export class NotNullMatcher extends Matcher { public match(value: any): boolean { - return !_.isNull(value); + return this.reverseResult(!_.isNull(value)); } public toString(): string { - return "notNull()"; + return `${this.prefix}notNull()`; } } diff --git a/src/matcher/type/ObjectContainingMatcher.ts b/src/matcher/type/ObjectContainingMatcher.ts index 7ed3814..c662324 100644 --- a/src/matcher/type/ObjectContainingMatcher.ts +++ b/src/matcher/type/ObjectContainingMatcher.ts @@ -7,10 +7,10 @@ export class ObjectContainingMatcher extends Matcher { } public match(value: Object): boolean { - return _.isMatch(value, this.expectedValue); + return this.reverseResult(_.isMatch(value, this.expectedValue)); } public toString(): string { - return `objectContaining(${this.expectedValue})`; + return `${this.prefix}objectContaining(${this.expectedValue})`; } } diff --git a/src/matcher/type/StrictEqualMatcher.ts b/src/matcher/type/StrictEqualMatcher.ts index 593c2de..c25be4f 100644 --- a/src/matcher/type/StrictEqualMatcher.ts +++ b/src/matcher/type/StrictEqualMatcher.ts @@ -6,14 +6,14 @@ export class StrictEqualMatcher extends Matcher { } public match(value: any): boolean { - return this.expectedValue === value; + return this.reverseResult(this.expectedValue === value); } public toString(): string { if (this.expectedValue instanceof Array) { - return `strictEqual([${this.expectedValue}])`; + return `${this.prefix}strictEqual([${this.expectedValue}])`; } else { - return `strictEqual(${this.expectedValue})`; + return `${this.prefix}strictEqual(${this.expectedValue})`; } } } diff --git a/src/ts-mockito.ts b/src/ts-mockito.ts index 9c51f33..bbce2fd 100644 --- a/src/ts-mockito.ts +++ b/src/ts-mockito.ts @@ -19,7 +19,8 @@ import {AnythingMatcher} from "./matcher/type/AnythingMatcher"; import {BetweenMatcher} from "./matcher/type/BetweenMatcher"; import {DeepEqualMatcher} from "./matcher/type/DeepEqualMatcher"; import {Matcher} from "./matcher/type/Matcher"; -import {MatchingStringMatcher} from "./matcher/type/MatchingStringMatcher"; +import {MatchMatcher} from "./matcher/type/MatchMatcher"; +import {Not} from "./matcher/type/Not"; import {NotNullMatcher} from "./matcher/type/NotNullMatcher"; import {ObjectContainingMatcher} from "./matcher/type/ObjectContainingMatcher"; import {StrictEqualMatcher} from "./matcher/type/StrictEqualMatcher"; @@ -33,7 +34,7 @@ export function spy(instanceToSpy: T): T { return new Spy(instanceToSpy).getMock(); } -export function mock(clazz: { new(...args: any[]): T; } | (Function & { prototype: T }) ): T { +export function mock(clazz: {new(...args: any[]): T; } | (Function & {prototype: T})): T { return new Mocker(clazz).getMock(); } @@ -78,7 +79,7 @@ export function resetCalls(mockedValue: T): void { (mockedValue as any).__tsmockitoMocker.resetCalls(); } -export function anyOfClass(expectedClass: { new (...args: any[]): T }): any { +export function anyOfClass(expectedClass: {new (...args: any[]): T}): any { return new AnyOfClassMatcher(expectedClass) as any; } @@ -115,13 +116,17 @@ export function strictEqual(expectedValue: any): Matcher { } export function match(expectedValue: RegExp | string): Matcher { - return new MatchingStringMatcher(expectedValue); + return new MatchMatcher(expectedValue); } export function objectContaining(expectedValue: Object): Matcher { return new ObjectContainingMatcher(expectedValue); } +export function not(): Not { + return new Not(); +} + import * as mockito from "./ts-mockito"; export default mockito; diff --git a/src/utils/MockableFunctionsFinder.ts b/src/utils/MockableFunctionsFinder.ts index 600b1cd..c73e6a4 100644 --- a/src/utils/MockableFunctionsFinder.ts +++ b/src/utils/MockableFunctionsFinder.ts @@ -1,6 +1,6 @@ /** * Looking for all function calls and declarations and provides an array of their names. The mechanism is greedy - * and tries to match as many function names as it can find and not only those of inspecting class. + * and tries to matchString as many function names as it can find and not only those of inspecting class. * * Matching occurrences are: * - [.]functionName( diff --git a/test/MethodAction.spec.ts b/test/MethodAction.spec.ts index 618ace2..0483246 100644 --- a/test/MethodAction.spec.ts +++ b/test/MethodAction.spec.ts @@ -4,7 +4,7 @@ import {strictEqual} from "../src/ts-mockito"; describe("MethodAction", () => { describe("checking if method with matchers is applicable", () => { describe("when all matchers match", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // given const methodName = "sampleMethodName"; const firstArg = 5; @@ -19,7 +19,7 @@ describe("MethodAction", () => { }); }); describe("when one matcher doesn`t match", () => { - it("returns false", () => { + it("returns false for original matcher and true for not().", () => { // given const methodName = "sampleMethodName"; const firstArg = 5; diff --git a/test/matcher/type/AnyFunctionMatcher.spec.ts b/test/matcher/type/AnyFunctionMatcher.spec.ts index a9ef677..2017bfa 100644 --- a/test/matcher/type/AnyFunctionMatcher.spec.ts +++ b/test/matcher/type/AnyFunctionMatcher.spec.ts @@ -1,71 +1,79 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {anyFunction} from "../../../src/ts-mockito"; +import {anyFunction, not} from "../../../src/ts-mockito"; describe("AnyFunctionMatcher", () => { + let testObj: Matcher; + let notTestObj: Matcher; - describe("checking if function is function", () => { - it("returns true", () => { - // given - const testObj: Matcher = anyFunction(); + beforeEach(() => { + testObj = anyFunction(); + notTestObj = not().anyFunction(); + }); + describe("checking if function is function", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(() => "arbitrary return value"); + const notResult = notTestObj.match(() => "arbitrary return value"); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if string is function", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyFunction(); - + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match("some string"); + const notResult = notTestObj.match("some string"); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if number is function", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyFunction(); - + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match(5); + const notResult = notTestObj.match(5); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if object is function", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyFunction(); - + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match({prop1: "prop1Value"}); + const notResult = notTestObj.match({prop1: "prop1Value"}); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if toString works", () => { it("returns 'anyFunction()'", () => { - // given - const testObj: Matcher = anyFunction(); - // when const result = testObj.toString(); // then expect(result).toEqual("anyFunction()"); }); + + it("returns 'not().anyFunction()' for .not() matcher", () => { + // when + const notResult = notTestObj.toString(); + + // then + expect(notResult).toEqual("not().anyFunction()"); + }); }); }); diff --git a/test/matcher/type/AnyNumberMatcher.spec.ts b/test/matcher/type/AnyNumberMatcher.spec.ts index 0f214a9..8bd2164 100644 --- a/test/matcher/type/AnyNumberMatcher.spec.ts +++ b/test/matcher/type/AnyNumberMatcher.spec.ts @@ -1,69 +1,72 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {anyNumber} from "../../../src/ts-mockito"; +import {anyNumber, not} from "../../../src/ts-mockito"; describe("AnyNumberMatcher", () => { - describe("checking if positive number is matching", () => { - it("returns true", () => { - // given - const testObj: Matcher = anyNumber(); + let testObj: Matcher; + let notTestObj: Matcher; + + beforeEach(() => { + testObj = anyNumber(); + notTestObj = not().anyNumber(); + }); + describe("checking if positive number is matching", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(3); + const notResult = notTestObj.match(3); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if negative number is matching", () => { - it("returns true", () => { - // given - const testObj: Matcher = anyNumber(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(-3); + const notResult = notTestObj.match(-3); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if zero is matching", () => { - it("returns true", () => { - // given - const testObj: Matcher = anyNumber(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(0); + const notResult = notTestObj.match(0); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if string representation of number is matching", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyNumber(); - + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match("5"); + const notResult = notTestObj.match("5"); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if object is matching", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyNumber(); - + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match({}); + const notResult = notTestObj.match({}); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); }); diff --git a/test/matcher/type/AnyOfClassMatcher.spec.ts b/test/matcher/type/AnyOfClassMatcher.spec.ts index d7755a6..415ae84 100644 --- a/test/matcher/type/AnyOfClassMatcher.spec.ts +++ b/test/matcher/type/AnyOfClassMatcher.spec.ts @@ -1,38 +1,45 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {anyOfClass} from "../../../src/ts-mockito"; +import {anyOfClass, not} from "../../../src/ts-mockito"; describe("AnyOfClassMatcher", () => { + let testObj: Matcher; + let notTestObj: Matcher; class Car { constructor() { } } + beforeEach(() => { + testObj = anyOfClass(Car); + notTestObj = not().anyOfClass(Car); + }); + describe("checking if class matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anyOfClass(Car); + it("returns true for original matcher and false for not().", () => { const value = new Car(); // when const result = testObj.match(value); + const notResult = notTestObj.match(value); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if null matches", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyOfClass(Car); + it("returns false for original matcher and true for not().", () => { const value = null; // when const result = testObj.match(value); + const notResult = notTestObj.match(value); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); @@ -48,29 +55,32 @@ describe("AnyOfClassMatcher", () => { }); describe("checking if different classes match", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyOfClass(Car); + it("returns false for original matcher and true for not().", () => { const value = "a string"; // when const result = testObj.match(value); + const notResult = notTestObj.match(value); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if toString works", () => { it("returns 'anyOfClass(Car)'", () => { - // given - const testObj: Matcher = anyOfClass(Car); - - // when const result = testObj.toString(); // then expect(result).toEqual("anyOfClass(Car)"); }); + + it("returns 'not().anyOfClass(Car)' for .not() matcher", () => { + const notResult = notTestObj.toString(); + + // then + expect(notResult).toEqual("not().anyOfClass(Car)"); + }); }); }); diff --git a/test/matcher/type/AnyStringMatcher.spec.ts b/test/matcher/type/AnyStringMatcher.spec.ts index 8904fc7..18384a9 100644 --- a/test/matcher/type/AnyStringMatcher.spec.ts +++ b/test/matcher/type/AnyStringMatcher.spec.ts @@ -1,56 +1,61 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {anyString} from "../../../src/ts-mockito"; +import {anyString, not} from "../../../src/ts-mockito"; describe("AnyStringMatcher", () => { - describe("checking if number matches", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyString(); + let testObj: Matcher; + let notTestObj: Matcher; + + beforeEach(() => { + testObj = anyString(); + notTestObj = not().anyString(); + }); + describe("checking if number matches", () => { + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match(3); + const notResult = notTestObj.match(3); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if object matches", () => { - it("returns false", () => { - // given - const testObj: Matcher = anyString(); + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match({}); + const notResult = notTestObj.match({}); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if empty string matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anyString(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(""); + const notResult = notTestObj.match(""); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if sample string matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anyString(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match("sampleString"); + const notResult = notTestObj.match("sampleString"); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); }); diff --git a/test/matcher/type/AnythingMatcher.spec.ts b/test/matcher/type/AnythingMatcher.spec.ts index 42512ef..af37299 100644 --- a/test/matcher/type/AnythingMatcher.spec.ts +++ b/test/matcher/type/AnythingMatcher.spec.ts @@ -1,69 +1,72 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {anything} from "../../../src/ts-mockito"; +import {anything, not} from "../../../src/ts-mockito"; describe("AnythingMatcher", () => { - describe("checking if number matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anything(); + let testObj: Matcher; + let notTestObj: Matcher; + + beforeEach(() => { + testObj = anything(); + notTestObj = not().anything(); + }); + describe("checking if number matches", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(3); + const notResult = notTestObj.match(3); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if object matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anything(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match({}); + const notResult = notTestObj.match({}); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if empty string matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anything(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(""); + const notResult = notTestObj.match(""); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if sample string matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anything(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match("sampleString"); + const notResult = notTestObj.match("sampleString"); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if null matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = anything(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(null); + const notResult = notTestObj.match(null); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); }); diff --git a/test/matcher/type/BetweenMatcher.spec.ts b/test/matcher/type/BetweenMatcher.spec.ts index 10c0708..7962f4e 100644 --- a/test/matcher/type/BetweenMatcher.spec.ts +++ b/test/matcher/type/BetweenMatcher.spec.ts @@ -1,57 +1,73 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {between} from "../../../src/ts-mockito"; +import {between, not} from "../../../src/ts-mockito"; describe("BetweenMatcher", () => { describe("checking if value matches given min and max", () => { - const testObj: Matcher = between(5, 10); + let testObj: Matcher; + let notTestObj: Matcher; + + beforeEach(() => { + testObj = between(5, 10); + notTestObj = not().between(5, 10); + }); describe("when given value is lower than min", () => { - it("returns false", () => { + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match(4); + const notResult = notTestObj.match(4); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("when given value is equal to min ", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(5); + const notResult = notTestObj.match(5); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("when given value is equal grater then min but lower than max", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(7); + const notResult = notTestObj.match(7); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("when given value is equal to max", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(10); + const notResult = notTestObj.match(10); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("when given value is greater than max", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(11); + const notResult = notTestObj.match(11); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); }); diff --git a/test/matcher/type/DeepEqualMatcher.spec.ts b/test/matcher/type/DeepEqualMatcher.spec.ts index 69a43af..f549b2d 100644 --- a/test/matcher/type/DeepEqualMatcher.spec.ts +++ b/test/matcher/type/DeepEqualMatcher.spec.ts @@ -1,92 +1,110 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {anyString, deepEqual} from "../../../src/ts-mockito"; +import {anyString, deepEqual, not} from "../../../src/ts-mockito"; describe("DeepEqualMatcher", () => { describe("checking if two different instances of same number matches", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // given const firstValue = 3; const secondValue = 3; const testObj: Matcher = deepEqual(firstValue); + const notTestObj: Matcher = not().deepEqual(firstValue); // when const result = testObj.match(secondValue); + const notResult = notTestObj.match(secondValue); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if two different instances of same string matches", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // given const firstValue = "sampleString"; const secondValue = "sampleString"; const testObj: Matcher = deepEqual(firstValue); + const notTestObj: Matcher = not().deepEqual(firstValue); // when const result = testObj.match(secondValue); + const notResult = notTestObj.match(secondValue); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if two different instances of same nested objects matches", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // given const firstValue = {a: 1, b: {c: 2}}; const secondValue = {a: 1, b: {c: 2}}; const testObj: Matcher = deepEqual(firstValue); + const notTestObj: Matcher = not().deepEqual(firstValue); // when const result = testObj.match(secondValue); + const notResult = notTestObj.match(secondValue); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if two nested objects matches when one leaf value is different", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // given const firstValue = {a: 1, b: {c: 2}}; const secondValue = {a: 1, b: {c: 99999}}; const testObj: Matcher = deepEqual(firstValue); + const notTestObj: Matcher = not().deepEqual(firstValue); // when const result = testObj.match(secondValue); + const notResult = notTestObj.match(secondValue); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if expected value has Matcher as a value", () => { - it("returns true if matcher returns true", () => { + it("returns true if matcher returns true for original matcher and false for not().", () => { // given const firstValue = {a: 1, b: anyString()}; const secondValue = {a: 1, b: "2"}; const testObj: Matcher = deepEqual(firstValue); + const notTestObj: Matcher = not().deepEqual(firstValue); // when const result = testObj.match(secondValue); + const notResult = notTestObj.match(secondValue); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); - it("returns false if matcher returns false", () => { + it("returns false if matcher returns false for original matcher and true for not().", () => { // given const firstValue = {a: 1, b: anyString()}; const secondValue = {a: 1, b: 2}; const testObj: Matcher = deepEqual(firstValue); + const notTestObj: Matcher = not().deepEqual(firstValue); // when const result = testObj.match(secondValue); + const notResult = notTestObj.match(secondValue); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); }); diff --git a/test/matcher/type/MatchingStringMatcher.spec.ts b/test/matcher/type/MatchMatcher.spec.ts similarity index 55% rename from test/matcher/type/MatchingStringMatcher.spec.ts rename to test/matcher/type/MatchMatcher.spec.ts index e4288d0..97f8a82 100644 --- a/test/matcher/type/MatchingStringMatcher.spec.ts +++ b/test/matcher/type/MatchMatcher.spec.ts @@ -1,27 +1,32 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {match} from "../../../src/ts-mockito"; +import {match, not} from "../../../src/ts-mockito"; -describe("MatchingStringMatcher", () => { +describe("MatchingMatcher", () => { describe("checking if value matches given regexp", () => { const testObj: Matcher = match(/\w123/); + const notTestObj: Matcher = not().match(/\w123/); describe("when given value matches regexp", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match("a123"); + const notResult = notTestObj.match("a123"); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("when given value doesn\'t match regexp", () => { - it("returns false", () => { + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match("123"); + const notResult = notTestObj.match("123"); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); }); diff --git a/test/matcher/type/Matcher.spec.ts b/test/matcher/type/Matcher.spec.ts new file mode 100644 index 0000000..a879789 --- /dev/null +++ b/test/matcher/type/Matcher.spec.ts @@ -0,0 +1,30 @@ +import {Matcher} from "../../../src/matcher/type/Matcher"; + +export function xor(a: boolean, b: boolean): boolean { + return a && !b || !b && a; +} + +describe("Matcher", () => { + const testObj: Matcher = new Matcher(); + const notTestObj: Matcher = (new Matcher()).reverse(); + + describe("reverse", () => { + it("returns opposite value", () => { + // when + const result = testObj.match(null); + const notResult = notTestObj.match(null); + + // then + expect(xor(result, notResult)).toBeFalsy(); + }); + + it("returns toString with 'not' prepended", () => { + // when + const result = testObj.toString(); + const notResult = notTestObj.toString(); + + // then + expect(`not().${result}`).toEqual(notResult); + }); + }); +}); diff --git a/test/matcher/type/NotNullMatcher.spec.ts b/test/matcher/type/NotNullMatcher.spec.ts index 7e9fd09..c4e5242 100644 --- a/test/matcher/type/NotNullMatcher.spec.ts +++ b/test/matcher/type/NotNullMatcher.spec.ts @@ -1,69 +1,72 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {notNull} from "../../../src/ts-mockito"; +import {not, notNull} from "../../../src/ts-mockito"; describe("NotNullMatcher", () => { - describe("checking if null matches", () => { - it("returns false", () => { - // given - const testObj: Matcher = notNull(); + let testObj: Matcher; + let notTestObj: Matcher; + + beforeEach(() => { + testObj = notNull(); + notTestObj = not().notNull(); + }); + describe("checking if null matches", () => { + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match(null); + const notResult = notTestObj.match(null); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if false matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = notNull(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(false); + const notResult = notTestObj.match(false); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if zero matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = notNull(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match(0); + const notResult = notTestObj.match(0); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if sample object matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = notNull(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match({}); + const notResult = notTestObj.match({}); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("checking if sample string matches", () => { - it("returns true", () => { - // given - const testObj: Matcher = notNull(); - + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match("sampleString"); + const notResult = notTestObj.match("sampleString"); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); }); diff --git a/test/matcher/type/ObjectContainingMatcher.spec.ts b/test/matcher/type/ObjectContainingMatcher.spec.ts index d8c5376..898ead2 100644 --- a/test/matcher/type/ObjectContainingMatcher.spec.ts +++ b/test/matcher/type/ObjectContainingMatcher.spec.ts @@ -1,35 +1,42 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {objectContaining} from "../../../src/ts-mockito"; +import {not, objectContaining} from "../../../src/ts-mockito"; describe("ObjectContainingMatcher", () => { describe("checking if source object contains given object", () => { const testObj: Matcher = objectContaining({b: {c: "c", d: {}}}); + const notTestObj: Matcher = not().objectContaining({b: {c: "c", d: {}}}); describe("when given value contains given object", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match({a: "a", b: {c: "c", d: {}}}); + const notResult = notTestObj.match({a: "a", b: {c: "c", d: {}}}); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // when const result = testObj.match({b: {c: "c", d: {}}}); + const notResult = notTestObj.match({b: {c: "c", d: {}}}); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); describe("when given value doesn't contain given object", () => { - it("returns false", () => { + it("returns false for original matcher and true for not().", () => { // when const result = testObj.match({b: {c: "c"}}); + const notResult = notTestObj.match({b: {c: "c"}}); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); }); diff --git a/test/matcher/type/StrictEqualMatcher.spec.ts b/test/matcher/type/StrictEqualMatcher.spec.ts index dc56efe..28f8dbd 100644 --- a/test/matcher/type/StrictEqualMatcher.spec.ts +++ b/test/matcher/type/StrictEqualMatcher.spec.ts @@ -1,56 +1,68 @@ import {Matcher} from "../../../src/matcher/type/Matcher"; -import {strictEqual} from "../../../src/ts-mockito"; +import {not, strictEqual} from "../../../src/ts-mockito"; describe("StrictEqualMatcher", () => { describe("checking if string representation of number matches with number", () => { - it("returns false", () => { + it("returns false for original matcher and true for not().", () => { // given const testObj: Matcher = strictEqual("5"); + const notTestObj: Matcher = not().strictEqual("5"); // when const result = testObj.match(5); + const notResult = notTestObj.match(5); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if false matches with zero", () => { - it("returns false", () => { + it("returns false for original matcher and true for not().", () => { // given const testObj: Matcher = strictEqual(false); + const notTestObj: Matcher = not().strictEqual(false); // when const result = testObj.match(0); + const notResult = notTestObj.match(0); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if true matches with one", () => { - it("returns false", () => { + it("returns false for original matcher and true for not().", () => { // given const testObj: Matcher = strictEqual(true); + const notTestObj: Matcher = not().strictEqual(true); // when const result = testObj.match(1); + const notResult = notTestObj.match(1); // then expect(result).toBeFalsy(); + expect(notResult).toBeTruthy(); }); }); describe("checking if same strings matches", () => { - it("returns true", () => { + it("returns true for original matcher and false for not().", () => { // given const testObj: Matcher = strictEqual("5"); + const notTestObj: Matcher = not().strictEqual("5"); // when const result = testObj.match("5"); + const notResult = notTestObj.match("5"); // then expect(result).toBeTruthy(); + expect(notResult).toBeFalsy(); }); }); });