Skip to content

Build: Don't assume the browser environment; smoke test on Node w/ jsdom #1949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

mgol
Copy link
Member

@mgol mgol commented Dec 17, 2014

Fixes gh-1950

@mgol
Copy link
Member Author

mgol commented Dec 17, 2014

+26 bytes currently; perhaps that can be improved.

EDIT: +35 bytes now.

Final EDIT: the landed commit ended up at +32 bytes.

@@ -11,7 +11,8 @@ jQuery.parseXML = function( data ) {

// Support: IE9
try {
tmp = new DOMParser();
// jQuery.parseXML is browser-only
tmp = new DOMParser(); // jshint ignore: line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOMParser should just be added to globals.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add DOMParser to globals and use it somewhere on the top scope, we'll break Node & other environments that don't have it. That's why I went for explicitly marking places that are browser-only; I think it's safer (and there are only two such places on master).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just don't like jshint comments. What about a jshintrc in the ajax folder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like it either. :) But it seemed as a necessary evil.

We don't know if something in the ajax folder isn't run immediately when including jQuery. We know this about parseXML and the xhr transport but this seems dangerous to do globally for ajax.

I'm open for better suggestions; I just don't see them currently.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about creating a subdirectory src/ajax/var/browser-only/ with vars for DOMParser & XMLHttpRequest and put such a .jshintrc with browser: true there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timmywil We could also use window.DOMParser etc. which has the advantage that if jsdom ever gets support for that it starts to work.

In fact, jsdom already supports XMLHttpRequest. I'll modify the PR.

Edit: done.


support.createHTMLDocument = (function() {
var doc = document.implementation.createHTMLDocument( "" );
// Support: Node with jsdom<=1.5.0+
// jsdom's document created via the above method doesn't contain the body
if (!doc.body) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spacing. Did jscs not pick this up?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't. :/


require( "jsdom" ).env( "", function (errors, window) {
if (errors) {
console.error(errors);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spaces here too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file might need to be added to the Gruntfile.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right; this is taken from my commit (e1303a3) at the standard-then-tests branch where the external file was actually necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, when I inline it spawn isn't even needed.

@mgol mgol force-pushed the node-tests branch 6 times, most recently from d6e7265 to f91bc4a Compare December 17, 2014 22:53
"setTimeout": true,
"clearTimeout": true,
"setInterval": true,
"clearInterval": true,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsdom supports setTimeout etc.; they wrap Node's setTimeout but also cache results in order to auto-clear timeouts/intervals on window.close(). This seems to be an extremely edge-case scenario and I envision we might want to support simpler than jsdom replacements for window so it's better to use global setTimeout.

Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@denis-sokolov claims it's a niche so I tend to agree. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it seems safe to just use setTimeout and the others global then? if node and browsers both support it global I think it should be safe.

@dmethvin
Copy link
Member

@mzgol I grabbed gh-1788 since it was specifically about this bug and moved it to the current release. Seemed good to have a ticket about it. 😸 We can make another issue with a general description since this is much more comprehensive.


support.createHTMLDocument = (function() {
var doc = document.implementation.createHTMLDocument( "" );
// Support: Node with jsdom<=1.5.0+
// jsdom's document created via the above method doesn't contain the body
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, didn't we pull out something similar for framed docs? There are no new bugs it seems.

@mgol
Copy link
Member Author

mgol commented Dec 18, 2014

@mzgol I grabbed gh-1788

@dmethvin OK, I've created #1950 instead.

@mgol mgol self-assigned this Dec 18, 2014
// Short list as a high frequency watch task
grunt.registerTask( "dev", [ "build:*:*", "lint" ] );

// Default grunt
grunt.registerTask( "default", [ "jsonlint", "dev", "uglify", "dist:*", "compare_size" ] );
grunt.registerTask( "default",
[ "jsonlint", "dev", "uglify", "dist:*", "compare_size", "node-smoke-test" ] );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to use the build/dist/test pattern that we have in other projects (e.g., sizzle, qunit). In other words, …, "dist:*", "node-smoke-test", "compare_size", or better still, moving "node-smoke-test" into a "test" task.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better still, moving "node-smoke-test" into a "test" task.

I had this in one version of a patch but this would be the only thing in the test task so far.

We'll also need to change the npm test script to do grunt test instead of just grunt.

Is that what you want?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to update Jenkins jobs to use npm test instead of grunt what they do now. I'll do it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done & done.

@gibson042
Copy link
Member

I like it. 👍

@mgol mgol force-pushed the node-tests branch 2 times, most recently from 30b61b5 to 3143efc Compare December 18, 2014 16:07
// Short list as a high frequency watch task
grunt.registerTask( "dev", [ "build:*:*", "lint" ] );

// Default grunt
grunt.registerTask( "test", [ "default", "node-smoke-test" ] );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't that go the other way (default including test)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's what you meant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, just to be sure:

grunt.registerTask( "test", [ "node-smoke-test" ] );

grunt.registerTask( "default", [ "jsonlint", "dev", "uglify", "dist:*", "test", "compare_size" ] );

That will mean that compare_size won't run if test fails. Is that OK?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with it, not least of all because it's consistent with Sizzle. And if that changes in the future, it should change everywhere.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about it but I'm not convinced that's the best approach. In Core grunt is so far linting and building the project and that's it. Current smoke-testing is short but we'll be adding Promises/A+ compliance test (see e1303a3) which is not quick so I doubt we want to auto-run it just when we just want to build the files.

We can run Node smoke-testing in the default task as it's quick but putting it in the test task will IMO mean we'll need to refactor it again in the nearby future.

Thoughts? cc @markelog @dmethvin @timmywil

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I trust your opinion more than mine here :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to add new task to default task? Those tests are for jsdom compliance, do we really need every time we want to build it?

We need to run grunt testswarm on Jenkins explicitly as it needs parameters, see config of this job:

Don't have access to it, you mean something like this -
grunt testswarm:d6c97abb744bfe8c67ab9158aecdb5bb1c05e47b:/usr/local/bin/tools/node-testswarm-config.json:jquery:jquery?

We could you use new npm feature - passing arguments to npm scripts, although it doesn't look pretty.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markelog

Do we really need to add new task to default task? Those tests are for jsdom compliance, do we really need every time we want to build it?

They're rather fast, though (500 ms on my machine) and they prevent us from accidentally commiting code breaking compat with Node. We do run linters on each grunt run for example.

On the other hand, the jsHint setup when changed like in this PR will catch most Node incompatibilities so maybe it's not so important to check it all the time.

I'll go by the following solution:

npm run build # does npm install && grunt
npm test # does grunt test
grunt testswarm:sthsthsth

I'll land this now without running Node smoke tests on grunt; we can revisit later. I want this on master ASAP, though so that we're covered agains past mistakes from now on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be in favor of running the tests all the time, but that's just me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jaubourg They require jsdom presence, though and some people may have a problem with that (see my comment: #1949 (comment)). I'm not sure if we have a perfect solution here without optionalDevDependencies but that's just one thing to consider.

@mgol
Copy link
Member Author

mgol commented Dec 22, 2014

I was made aware by email that:

  1. jsdom requires node-gyp which - in turn - requires Python & some other build stuff
  2. No other dev dependency of ours requires those tools
  3. Being able to run npm install is necessary to be able to build a custom version.

So it seems we shouldn't just flat out fail if jsdom fails to install as it's not required by the build process. I'd normally just put it in optionalDevDependencies but they don't exist (see npm/npm#3870 - @othiym23, you have a real use case here ;)).

The only way to resolve it that I see is to create an optionalDevDependencies key, move jsdom there and install the specified version optionally in the postinstall hook that will be forgiving if the installation fails. A little ugly.

Any better ideas?

EDIT: I still want to land this PR even if we don't figure out how to solve the presented problem soon; we can figure it out later but it still seems important.

This was referenced Dec 26, 2014
@mgol mgol closed this Dec 26, 2014
@mgol mgol deleted the node-tests branch December 26, 2014 12:27
@mgol
Copy link
Member Author

mgol commented Dec 26, 2014

Landed. I went for running the tests via:

npm install
npm test
grunt testswarm:other:params:here

In this was we can run tests in the same way on master and compat; also, Travis runs npm install && npm test by default so we also get that covered.

npm test on master runs grunt test and on compat: grunt. The test task runs default and then test_fast.

@jaubourg grunt will not run Node smoke tests for you (until we decide otherwise) but npm test and grunt test do so you can use one of them instead. If you miss, Travis has you covered.

@mgol
Copy link
Member Author

mgol commented Dec 27, 2014

I've looked a little at jsdom build requirements and they'll all be gone once Node 0.12 comes out (which, cough, should be soon): jsdom/jsdom#683 (comment)

Judging by how complicated and fragile any workaround would be here and considering that the problem will disappear in some time I'd rather leave it as is.

mgol added a commit to mgol/jquery that referenced this pull request Jul 28, 2015
mgol added a commit to mgol/jquery that referenced this pull request Jul 28, 2015
mgol added a commit to mgol/jquery that referenced this pull request Jul 28, 2015
mgol added a commit to mgol/jquery that referenced this pull request Aug 16, 2015
@lock lock bot locked as resolved and limited conversation to collaborators Jan 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Don't assume the browser environment in src/, run a smoke-test on Node
7 participants