Skip to content
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

feat(config): Add preprocessorOrder option to config for when prepr… #1899

Merged
merged 1 commit into from
Feb 24, 2016

Conversation

sjelin
Copy link
Contributor

@sjelin sjelin commented Feb 13, 2016

…ocessors

must be run in a specific order.

Some karma users at Google discovered karma-coverage needs to be run before
karma-googmodule-preprocessor, hence we need this feature.

This required an update to karma-browserify, which can be found here: nikku/karma-browserify#168.

Since this version is not yet released, this will break travis.

@@ -355,7 +355,7 @@
"engines": {
"node": "0.10 || 0.12 || 4 || 5"
},
"version": "0.13.21",
"version": "0.13.22",
Copy link
Member

Choose a reason for hiding this comment

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

Please remove this, version bumps are generated automatically on release

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. The problem now is that I'll have nothing to reference in the browserify change

@nikku
Copy link

nikku commented Feb 13, 2016

I'd like to put a different solution for this on the table: Allow config.preprocessors to be an array instead of an object. This way the processing order for individual preprocessors is clear from the start and no additional configuration property is needed.

Example JSON:

{
  "preprocessors": [
    [ ".js", "googmodule" ],
    [ ".js", "coverage" ]
  ]
}

@sjelin Could you provide us with an example project + karma configuration that fails with the current version of karma?

@sjelin
Copy link
Contributor Author

sjelin commented Feb 16, 2016

@nikku we were having problems with a config file like:

"preprocessors":  {
  "**/*.js": [ "googmodule" ],
  "**/client/**/*.js": [ "coverage" ]
},

Which caused googmodule to run before coverage, which in caused problems in the coverage information (not sure exactly why).

The problem with the preprocessors array option is that you'd run into problems combining multiple config files if one assumed preprocessors was an array and the other assumed preprocessors was an object.

@dignifiedquire
Copy link
Member

@nikku have you tried doing sth like this:

"preprocessors":  {
  "!(client)/**/*.js": [ "googmodule" ],
  "client/**/*.js": ["googmodule", "coverage" ]
},

You would need to explicitly define the top level path, but you wouldn't need to add any code to karma to get this working.

@sjelin
Copy link
Contributor Author

sjelin commented Feb 16, 2016

Yes, that would probably work in this instance. But users may have a more complicated group of files they need coverage data for. For instance:

"preprocessors":  {
  "a/**/*.js": ["googmodule", "coverage" ],
  "**/b/*.js": ["googmodule", "coverage" ],
  "c*d/*.js": ["googmodule", "coverage" ],
  "<else *.js>": [ "googmodule" ]
},

In this case I have no idea what pattern goes in the <else *.js> case. I'm also not sure what would happen to a file like a/b/x.js, which ends up getting ["googmodule", "coverage", "googmodule", "coverage"] run on it.

Plus, while it's good that it requires no karma code change, it feels like a hack. I want googmodule to be run everywhere, and it should be simple to write that in the config.

@@ -36,7 +36,7 @@ var createNextProcessor = function (preprocessors, file, done) {
}
}

var createPreprocessor = function (config, basePath, injector) {
var createPreprocessor = function (config, basePath, ppOrder, injector) {
Copy link
Member

Choose a reason for hiding this comment

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

Can we avoid this? I'd rather not risk breaking other preprocessors

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess so. We could use a custom property of config like !!preprocessorOrder which would never be needed to match a real file. I'm also open to any other ideas.

@nikku
Copy link

nikku commented Feb 16, 2016

@sjelin Ok, how does the following (switched order of preprocessor definitions) behave then?

"preprocessors":  {
  "**/client/**/*.js": [ "coverage" ],
  "**/*.js": [ "googmodule" ]
},

@sjelin
Copy link
Contributor Author

sjelin commented Feb 17, 2016

I mean, that works (sometimes at least), but it's not supposed to work. It relies on Object.keys to return the keys in the same order they're written down in, but the spec explicitly says Object.keys returns the keys in an arbitrary order.

@dignifiedquire
Copy link
Member

@sjelin what happens if you do:

"preprocessors":  {
  "**/*.js": [ "googmodule" ],
  "**/client/**/*.js": ["googmodule", "coverage" ]
},

@sjelin
Copy link
Contributor Author

sjelin commented Feb 17, 2016

I think you mean:

"preprocessors":  {
  "**/*.js": [ "googmodule" ],
  "**/client/**/*.js": ["coverage", "googmodule"]
},

since coverage is supposed to run first.

Currently there is no de-duplication in preprocessor.js, so it would run either ["googmodule", "coverage", "googmodule"] or ["coverage", "googmodule", "googmodule"], depending on the order of the Object.keys array. I could write some kind of intelligent de-duplication/ordering into preprocessor.js. The advantage is that it wouldn't change the function's signature or introduce new properties into the config file. The disadvantage is that it would just be a secret version of preprocessorOrder

@dignifiedquire
Copy link
Member

Yes that's what I meant.

I think it would be a very good solution to introduce deduping here and use that order as it would be much more explicit and would solve the more complex use case where you want different orders of the same preprocessors in different files.

As long as we properly document this it wouldn't be a hidden feature.

@sjelin
Copy link
Contributor Author

sjelin commented Feb 17, 2016

Ok, I'm good with that.

@nikku
Copy link

nikku commented Feb 17, 2016

+1 if you get that properly explained to people, too.

@zzo
Copy link
Contributor

zzo commented Feb 18, 2016

thanks sammy fix travis :)

@sjelin
Copy link
Contributor Author

sjelin commented Feb 19, 2016

Ok, I wrote it the other way. I know what you're going to say: "Why is it so complicated?" It turns out merging arrays, trying to keep their orders in tact as much as possible, isn't easy. I'm more than open to similar solutions.

@sjelin sjelin force-pushed the preprocessorOrder branch 2 times, most recently from c8ed95f to a99e897 Compare February 19, 2016 01:03
* header comment above
*
* For those who care, this is very slow, and taking
* O(list2.length*list2.length*(list1.length + list2.length)) time.
Copy link
Member

Choose a reason for hiding this comment

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

😆 who would have guessed we find some big O notation in here one day

/* Merge two lists, removing duplicates, and doing everything possible to
* maintain the order of the two lists.
*
* This function guarantees that the order of list1 is preserved (that is, if x
Copy link
Member

Choose a reason for hiding this comment

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

Style: Please use // for comments to be consistent with the rest of the code

@dignifiedquire
Copy link
Member

@sjelin nice work, didn't expect this to get that complicated though :D

I left some style nitpicks but other than that I'm pretty happy with this solution

@dignifiedquire
Copy link
Member

Also the commit message needs to mention that this is a breaking change, as it might change the order of preprocessors for some expecting the old behaviour.

@dignifiedquire dignifiedquire modified the milestone: v1.0 Feb 19, 2016
@sjelin sjelin force-pushed the preprocessorOrder branch 2 times, most recently from faeee46 to 5de42cb Compare February 19, 2016 23:49
@sjelin
Copy link
Contributor Author

sjelin commented Feb 19, 2016

All comments addressed! Though tbh once I split the list merging into its own repo (https://github.com/sjelin/combine-lists), most of the comments were no longer relevant.

@dignifiedquire
Copy link
Member

Thanks, nearly there, looks like linting is unhappy now. (grunt lint locally)

…, intelligently merge the list of preprocessors, deduping and trying to preserve the order

This could be a breaking change, some users might rely on the old order, or on some preprocessors being run multiple times
@sjelin
Copy link
Contributor Author

sjelin commented Feb 22, 2016

Fixed the lint problems. Looks like some of the e2e tests are failing. Are they flaky though? It seems pretty random

@dignifiedquire
Copy link
Member

@sjelin restarted them, yes they are super flaky atm sometimes travis gets so slow they time out :(

dignifiedquire added a commit that referenced this pull request Feb 24, 2016
feat(config): Add `preprocessorOrder` option to config for when prepr…
@dignifiedquire dignifiedquire merged commit a751293 into karma-runner:master Feb 24, 2016
@dignifiedquire
Copy link
Member

Thanks :octocat:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants