0

I have a hybrid Angular and Angular.js app testing with Karma / Jasmine. The old code used custom matchers and it works great, the same matchers are used in the new TypeScript code as well. The TypeScript compiler for Webpack compiles and runs the spec's just fine, but the WebStorm inspector underlines them as errors like so:

enter image description here

With the error message:

TS2339: Property 'toBeNgVisible' does not exist on type 'ArrayLikeMatchers '.

The environment looks like:

  • "@types/angular-mocks": "^1.5.11",
  • "@types/jasmine": "^3.3.1",
  • "@types/jasmine-jquery": "^1.5.33",
  • "@types/jquery": "^1.10.33",
  • "@angular/upgrade": "^9.1.13",
  • "@angular/core": "^9.1.13",
  • "angular": "^1.8.2",
  • "angular-mocks": "^1.8.2",
  • "typescript": "^3.8.3",
  • "karma": "^5.2.3",
  • "karma-jasmine": "^3.3.1",
  • "karma-webpack": "^4.0.2",
  • "jasmine-core": "^3.5.0",

My custom matchers are written in JavaScript like so:

const matchers = {
  toBeNgVisible: () => {
    return {
      compare: function (actual) {
        return {
          pass: actual && $(actual).closest('[hidden]').length === 0;,
          message: 'Expected "' + actual + '," and all of its parents, to not have a hidden attribute.'
        };
      }
    };
  }
}
beforeEach(() => { jasmine.addMatchers(matchers); });

There is a declaration file, matchers.d.ts, that looks like:

declare namespace jasmine {
  interface Matchers<T> {
    toBeNgVisible(): boolean;
  }
}

My tsconfig file does not have any file includes/excludes and my matchers.d.ts file is included in the files list.

This issue obfuscates real problems and gets in the way of efficient development. Has anyone experienced this? Is there any guidance into what I can try next? I am not even sure if the issue is when my Webpack configuration or my WebStorm configuration so any suggestions would be welcome.

1 Answer 1

2

I have experienced this problem.

Current Answer

You don't need to specify a separate declaration file. Instead, you can decorate the global Jasmine namespace. This syntax will work, and the WebStorm inspector should be happy enough with it:

In matchers.ts:

declare global {
  namespace jasmine {
    interface Matchers<T> {
      toBeNgVisible<V>(): boolean;
    }
  }
}

export const Matchers: jasmine.CustomMatcherFactories = {
  toBeNgVisible: () => {
    // ... your implementation here
  }
}

You'll still need to add the matchers to Jasmine before running tests, but this technique is working well for my use-case.

One reference for this approach is here (see the final comment).

Original Answer

The workaround that I have used is to rename the declaration file so that it doesn't have the same name. For example:

matchers.ts
matchers.d.ts       <-- does not work if named this way
matcher-types.d.ts  <-- same file as above, renaming resolves the issue for WebStorm

I'll try to find the link that helped me with this solution, but in the meantime you can give this a go.

-edit- The solution is actually in an existing post at https://stackoverflow.com/a/58690686/8029707

Sign up to request clarification or add additional context in comments.

2 Comments

I attempted this without success, it may be an answer, but something else about my build seems to be causing the problem. Thanks for the info, I have been completely stumped about what to even try.
I got around to testing this - it does not work in my case. I think it is because I have a hybrid app and the marchers are defined in JavaScript, so there is are likely more steps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.