Definitelytyped: angular-protractor: conflict with JQuery

Created on 28 Aug 2014  ·  51Comments  ·  Source: DefinitelyTyped/DefinitelyTyped

I'm seeing the following conflict when using Protractor with JQuery.

Subsequent variable declarations must have the same type.  
Variable '$' must be of type 'cssSelectorHelper', but here has type 'JQueryStatic'.
Web\Scripts\typings\jquery\jquery.d.ts   3936

I tried to uninstall JQuery, but 'angularjs.TypeScript.DefinitelyTyped 2.0.6 depend(s) on it.

I'm using the following version:

<package id="angularjs.TypeScript.DefinitelyTyped" version="2.0.6" targetFramework="net45" /
<package id="angular-protractor.TypeScript.DefinitelyTyped" version="0.0.4" targetFramework="net45" />
<package id="jquery.TypeScript.DefinitelyTyped" version="1.3.8" targetFramework="net45" />

Thanks
Jay

Most helpful comment

Hi everyone. I've had this issue bookmarked for a very long time and have been meaning to respond.

Since angular-protractor is built off an older version of Protractor, we decided to not maintain this.

Protractor has been slowly migrating JavaScript files to TypeScript. If you are using the latest version of Protractor (v 4.0.9), it has built in TypeScript support. There is a sample TypeScript project in the Protractor repo as well as in the cookbook. Just a quick note: TypeScript support is still experimental, check the changelog for any potential breaking changes.

So to not have a jQuery conflict, you must set noGlobals to true. (See config file). This will ensure that protractor publishes a single global object called 'protractor'.

import {$} from 'protractor';

The import actually uses the global protractor.$ and does not use global $ that jQuery uses.

So let's say you are using $ for jQuery. The above typing doesn't work if you are importing $ from Protractor... so maybe you want to do the following:

import {$ as Protractor$} from 'protractor';

All 51 comments

+1

It seems that it is not possible to reference both files in the same project, even if they aren't used in the same

@turp You could handle this by moving your e2e tests to a new project.

Yeah, rather annoying even though it's not the fault of either TSD. Given that both libraries set up a global $ function, I'm not even sure you can load both underlying JS libraries at the same time?

+1

I had created the above issue in typescript, but as I was thinking about it I came to the conclusion that this is likely an issue with how TSD is creating the tsd.d.ts file. Since we shouldn't be using both JQuery and angular-protractor in the same typescript file, then we should have a dedicated set of references for each scenario...

However, not sure how this would be done specifically... Maybe something like having a "dev" version of a tsd.d.ts for tests? (i.e. tsd install --save-dev that would save to "tsd.dev.d.ts"?)

I set up two TSDs, one used by my main app, and one to reference from functional test code. Obviously, the protractor d.ts isn't part of my main app TSD.

I gave that a try & it didn't work for me. Maybe I have something different in my project, but by simply including the d.ts (regardless of the in the ts files) causes the build issue. Do you have a single VS project for both your unit\functional test code & your app?

After playing with this for a couple hours now, it really seems like there's something off with the typescript compiler that might be compounding this issue... If I have 2 ts files in my project, 1 references angular-protractor and the other ts file references jquery, then I get "TS2134: Build: Subsequent variable declarations...". Since the ts are independent of each other and don't reference both angular-protractor & jquery at the same time, then this build issue should never be hit.

I'm going to create a simple github project to demonstrate & file an issue against typescript (again).

I don't use Visual Studio so I'm not sure if that's part of the issue or not. I use IDEA to code, and Gulp to watch the file system, compile, and produce the build artifacts.

when Gulp compiles, does it call TSC per file or once for all files? For example,

tsc a.ts b.ts c.d.ts

or

tsc a.ts
tsc b.ts

Visual Studio builds the first way, which I think is why I'm seeing the issue & why having multiple tsd.d.ts files isn't working for me. I would guess Gulp does it the 2nd way (though, i've never used Gulp, so this is just a guess).

I'm actually not sure. I have it compiling and aggregating the JS into a single file, along with a source map for easier debugging, but you can also have it compile out to individual JS files. It can also do incremental compilation for updates, which speeds things up. So it almost seems like it does both, but that's really just a guess. (If it helps, you can see what it is using here: https://github.com/ivogabe/gulp-typescript/tree/master/typescript).

I am struggling with this issue as well

+1

+1

I ended up using the workaround suggested by @awerlang.

+1 This is most annoying.

I'm not really sure what's not sinking in here. Angular depends on jQuery, which defines a $() function. The Protractor JS library also defines a $() function (because this is what the underlying Webdriver API is). The jQuery and Protractor TSD's can only match the API declared by the original JS libraries. If you include both the Angular and Protractor TSDs, you're going to have a conflict. There's nothing the author of the Protractor TSD can do about this.

The only possible option would be to create a Protractor TSD that omits $() from the definition. But then, anyone using the TSD would be forced to use something like element(by.css(selector)) everywhere, instead of $(). And I doubt that anyone would be happy with that.

Since I don't think there's any reason for Protractor code to depend on Angular or jQuery anyway, the only viable solution seems to be just not referencing the Angular TSD within the Protractor project/code. That probably means using a separate project, or at least separate TSD listings.

If you're using Visual Studio to build & have both protractor/angular in the same project, then please put your "+1" in https://github.com/Microsoft/TypeScript/issues/1516 to let them know I'm not the only one seeing this issue

This is the first google hit for the issue. I knew at the time it was VS's fault but the red mis, it made me do it.

For those who want main app and tests on the same VS project, refer to PR #3528. Get it and see if anything's broken at your side. It must fix this issue.

+1

This is really annoying indeed. I wonder why protractor used $ in the first place, wasn't jQuery well established when Protractor was developed? I can't get my e2e tests compiled with TS and TSLint and don't seem to find a way of fixing this.

Has anyone found a good workaround? I was thinking about settings up two tsd folders, but since both my app and my e2e tests needs type definitions for angular this wouldn't help anyway.

I understand the implications of this problem, and that it doesn't really help anyone to

Protractor is just a wrapper for Selenium/Webdriver, which uses $ and $$ extensively.

However, I'm not sure why your e2e tests project would actually need the Angular or JQuery definitions?

+1 @brian428

Keep in mind that angular-mocks also has a reference to angular.d.ts — so you may have to further split your unit test definition files from your e2e ones.

Hi guys,

I sent a PR to DefinitelyTyped https://github.com/borisyankov/DefinitelyTyped/pull/4844 to allow embedding of a noConflict version of jQuery. This would be an acceptable solution for me. Please feel free to add your comments and thoughts to the proposed workaround.

Until this PR is merged, I use the following tsd.json configuration (I am using a fork of DefinitelyTyped and replaced the jQuery lib). A tsd reinstall -o should override the current jQuery version.

{
  "version": "v4",
  "repo": "chaosmail/DefinitelyTyped",
  "ref": "master",
  "path": "typings",
  "bundle": "typings/tsd.d.ts",
  "installed": {
    "angularjs/angular.d.ts": {
      "commit": "220ada3f90a7b9e769593650e6aba824bf2f085a"
    },
    "jquery/jquery.d.ts": {
      "commit": "705b4cc80bced7c0cc95575741113667d210602f"
    },
    "angular-protractor/angular-protractor.d.ts": {
      "commit": "2fe8a6fda29c3340a5e5672b1809a84c88729a30"
    },
    "selenium-webdriver/selenium-webdriver.d.ts": {
      "commit": "2fe8a6fda29c3340a5e5672b1809a84c88729a30"
    }
  }
}

Hope this helps someone.

Edit: It didn't work as expected, because version names are appended in the *.d.ts file. At the moment my repo contains a noConflict version of jQuery.

Best.
Christoph

Here's what I did for converting the official AngularSeed project for TypeScript : https://github.com/Microsoft/TypeScriptSamples/blob/master/angular1/CONVERSION.md

The final project : https://github.com/Microsoft/TypeScriptSamples/tree/master/angular1

It won't work if your tests will include functionality, which depends on jQuery.
Lets say you need to test directive's controller or something else and this directive requires jQuery.

@SergeySolonko to test controller's you use karma, not protractor. A unit test is what you need, while protractor offers integration tests.

@awerlang you're right. But in this case unit tests also use jasmine and maybe another libraries for testing. And in this case if you'll create one typings.d.ts file and include it for all types of testings - you'll get this error. And in this case you'll need to create 3 typings.d.ts files:

typings.d.ts - for you app sources
typings.tests.unit.d.ts - for your unit tests
typings.tests.e2e.d.ts - for your e2e tests

Difference between them will be in these files:

/// <reference path="../typings/angular-protractor/angular-protractor.d.ts" />
/// <reference path="../typings/selenium-webdriver/selenium-webdriver.d.ts" />

Rest of the references should be the same.
Right?

P.S. if you will setup grunt/gulp task to compile TS sources, you need to exclude test files. In other case, if you'll compile all sources - you'll get this error.

Correct. I use separate TSDs, and separate gulp tasks to compile source vs. test code.

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

We should really make a new issue, this one is from 2014. This issue is also for the first angular/protractor and I am sure all of us are here for angular2.

angular1 here :)

@jakeNiemiec Nope, using AngularJS 1.x here. We're just trying to minimize the migration effort in the future.

+1

+1

Is there any way i can use jquery and protractor typings in the same project, without modifying typings sources and without getting this error? After all this time, there must be a way :(

+1

This is really annoying. Introduction of "Types" to Javascript is supposed to increase productivity! I am JS pro & I have been working on it since month and I still keep on getting such annoying issues which diverts your focus from actual functionality! Sadly, I don't see productivity in action with Types!

+1
Really, 2 years?

Fix it please!

There is ~1000 open issues, no one is going to find this (2 years and counting).

Looking at the history of contributors, @cnishina may be able to help (his profile tagline: Mission: typescript protractor tests)

@vvakame is also a recent contributor (seemingly related issue here: https://github.com/Microsoft/TypeScript/pull/3102#issuecomment-101759155.

Hi everyone. I've had this issue bookmarked for a very long time and have been meaning to respond.

Since angular-protractor is built off an older version of Protractor, we decided to not maintain this.

Protractor has been slowly migrating JavaScript files to TypeScript. If you are using the latest version of Protractor (v 4.0.9), it has built in TypeScript support. There is a sample TypeScript project in the Protractor repo as well as in the cookbook. Just a quick note: TypeScript support is still experimental, check the changelog for any potential breaking changes.

So to not have a jQuery conflict, you must set noGlobals to true. (See config file). This will ensure that protractor publishes a single global object called 'protractor'.

import {$} from 'protractor';

The import actually uses the global protractor.$ and does not use global $ that jQuery uses.

So let's say you are using $ for jQuery. The above typing doesn't work if you are importing $ from Protractor... so maybe you want to do the following:

import {$ as Protractor$} from 'protractor';

Hopefully the above response is enough to close this issue. 🎉

Below is more details about "fixing" angular-protractor and probably why it might not be ideal:

API mismatch

Since Protractor version 1.5, some of the APIs have changed causing a version mismatch for the ambient typings. This is probably the most important reason why Protractor now supports TypeScript.

Below is the proposed fix; however, making this change will ultimately break tests for users that do not have an ambient typing problem with jQuery. This might be a good reason to use Protractor 4.0.9+.

The fix for Protractor 3.2+

For users that are using Protractor 3.2+ and < 4, using the noGlobals flag would ensure that there are no conflicts at the global namespace for $. The fix would be to remove the declare var $ as well as other global variables completely from angular-protractor.d.ts. This would require users to set up their own Protractor variables.

import {Protractor} from 'protractor';

let protractor: Protractor = (global as any)['protractor'];
let $ = protractor.$; 

The fix for Protractor < 3.2

Again, the fix would be to remove the declare var $ and other global variables as stated above and would also require users to set up their own Protractor variables (also shown above). However, if you are using jQuery in your Protractor file, there still is a global namespace problem with Protractor's $ and jQuery's $.

@cnishina Thanks for following up!

@andy-ms This should be closed since angular-protractor does not exist.

Was this page helpful?
0 / 5 - 0 ratings