使用Typescript创建自定义茉莉花匹配器

时间:2017-03-22 15:32:52

标签: typescript jasmine jasmine-matchers

我在angular2项目上使用jasmine并且在编写自定义匹配器时遇到了一些麻烦。我希望能够比较两个相对复杂的对象。我发现this article声称解决了这个问题,但它只会导致打字稿错误,说明它没有识别茉莉花的Matchers对象上的新方法。相关代码是:

declare module jasmine {
    interface Matchers {
        toBeNumeric(): void;
    }
}

Another article给出了一个类似但略有不同的解决方案,它会产生同样的错误。

declare namespace jasmine {
    interface Matchers {
        toHaveText(expected: string): boolean;
    }
}

我试过这个

let m: jasmine.Matchers = expect(someSpy.someMethod).toHaveBeenCalled();

并收到此错误:

  

键入' jasmine.Matchers'不能分配给#jasmine.Matchers'。   存在两种具有此名称的不同类型,但它们是不相关的。

这似乎表明declare namespace jasmine语句正在创建一个新的jasmine命名空间,而不是扩展现有的命名空间。

那么如何创建我自己的打字稿,打字稿会很满意?

3 个答案:

答案 0 :(得分:4)

Daf的答案主要适合我,我只是注意到他的示例代码和他命名文件的方式存在问题。我也遇到了另一个无关的问题。因此,一个新的答案。

  • 由于某种原因,当界面文件与匹配文件同名时,我的应用程序不喜欢它。例如foo.ts和foo.d.ts.对于我的应用程序,它需要是foo.ts和foo-interface.d.ts或类似的东西。
  • 也不要将foo.ts中的接口导入到foo-interface.d.ts中,它似乎也不喜欢这样。

示例自定义匹配器: - https://github.com/vespertilian/wallaby-angular-node-yarn-workspaces/tree/master/api/src/test-helpers 此处的示例规格: - https://github.com/vespertilian/wallaby-angular-node-yarn-workspaces/blob/master/api/src/hello/hello.spec.ts

匹配器 - custom-matchers.ts

import MatchersUtil = jasmine.MatchersUtil;
import CustomMatcherFactories = jasmine.CustomMatcherFactories;
import CustomEqualityTester = jasmine.CustomEqualityTester;
import CustomMatcher = jasmine.CustomMatcher;
import CustomMatcherResult = jasmine.CustomMatcherResult;

export const SomeCustomMatchers: CustomMatcherFactories = {
    toReallyEqual: function (util: MatchersUtil, customEqualityTester: CustomEqualityTester[]): CustomMatcher {
        return {
            compare: function (actual: any, expected: any): CustomMatcherResult {
                if(actual === expected) {
                    return {
                        pass: true,
                        message: `Actual equals expected`
                    }
                } else {
                    return {
                        pass: false,
                        message: `Actual does not equal expected`
                    }
                }

            }
        }
    }
};

接口文件 - matcher-types.d.ts - 不能与匹配文件同名

declare namespace jasmine {
    interface Matchers<T> {
        toReallyEqual(expected: any, expectationFailOutput?: any): boolean;
    }
}

自定义匹配器测试

describe('Hello', () => {

    beforeEach(() => {
        jasmine.addMatchers(SomeCustomMatchers)
    });

    it('should allow custom matchers', () => {
        expect('foo').toReallyEqual('foo');
        expect('bar').not.toReallyEqual('test');
    })
});

答案 1 :(得分:2)

基本上,你的第二个例子(“声明命名空间”)是可行的方式,当然,还有其他地方的匹配器的逻辑。

欢迎你看一下https://github.com/fluffynuts/polymer-ts-scratch/tree/5eb799f7c8d144dd8239ab2d2bcc72821327cb24/src/specs/test-utils/jasmine-matchers我写过一些茉莉花匹配器和打字机的地方 - 虽然从技术上来说我用Javascript写了实际的匹配器并命名了逻辑文件.ts安抚我的构建过程。

需要安装@types/jasmine - 并保持最新状态。

请记住@types/jasmine的不同版本可能会破坏事物;具体来说,上面链接的提交是Jasmine类型引入Matchers类型的类型参数(即Matchers<T>),它打破了我所有的.d.ts文件。

答案 2 :(得分:0)

如果您使用的是ES模块,则需要将名称空间声明包装在declare global块中。

以下是更新的示例,其中两个自定义匹配器已合并到相同的定义中:

    declare global {
        namespace jasmine {
            interface Matchers {
                toBeNumeric(): void;
                toHaveText(expected: string): boolean;
            }
        }
    }

也可以将声明分开(甚至分散在多个文件中):

    // File 1 declares this matcher
    declare global {
        namespace jasmine {
            interface Matchers {
                toBeNumeric(): void;
            }
        }
    }

    // File 2 declares this matcher
    declare global {
        namespace jasmine {
            interface Matchers {
                toHaveText(expected: string): boolean;
            }
        }
    }

    // File 3: use the custom matchers
    it(function(){
        expect(3).toBeNumeric();
        expect(result).toHaveText('custom matcher');
    });

注意:在这些摘要中,namespacemodule关键字是等效的,但不建议使用module,而首选namespace(以避免与ES模块或CommonJS模块混淆)