Get filename of test/spec being run in reporter
Expected behaviour
When writing a reporter in the onSpecComplete complete function I would expect the result object to have an attribute filePath or similar that shows the path to the file where the test is being run.
Actual behaviour
It does not have that attribute, nor have I found another way to get the filename of the spec.
Environment Details
Karma version: 1.4.1
@Globegitter
- Why do you need this information?
- It does not relate to the karma itself. All tests are loaded by tag script in a browser and runned by test framework. So it should be done in test framework or by, a separate plugin because karma does not know relations between file path in tag script and test case.
In your case, you can try to find the path in error stack trace or create preprocessor which adds file path to the test case description.
it('/a/b/c.js! should be true', function() {...});
@maksimr Thanks for the quick reply. As a bit of background, I have not setup karma on our project, nor got that much experience with it. I am just setting up integration with our code review tool (Phabricator). And that has the possibility to show on each PR which test exactly failed and which file that test belonged to. So I have written a reporter to give me the test results in json, which are then being sent to phabricator.
A preprocessor sounds like a valid idea, thanks. We are also using karma-mocha, so maybe we can also use mocha to create that json information. Will get a bit of a better understanding of how these two pieces play together.
I'm trying to write a preprocessor as @maksimr suggested, but karma is still running the original spec file, not the transformed one. Can you help me to check if I've made any mistake?
My code looks like this:
// karma.conf.js
module.exports = function (config) {
config.set({
frameworks: ['jasmine','@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-myPreprocessor'),
require('@angular-devkit/build-angular/plugins/karma')
],
basePath: 'src/app',
files: ['**/*.spec.ts'],
preprocessors: { '**/*.spec.ts': ['myPreprocessor']},
reporters: ['progress', 'kjhtml'],
client: {
clearContext: false
},
port: 9876,
colors: true,
browsers: ['Chrome'],
logLevel: config.LOG_INFO,
autoWatch: true,
singleRun: false
});
};
// myPreprocessor
var createMyPreprocessor = function() {
return function (content, file, next) {
next(null, content.replace("it('",`it('!#PATH=${file.originalPath}#!`));
}
}
myPreprocessor.$inject = [];
module.exports = {
'preprocessor:myPreprocessor': ['factory', createMyPreprocessor]
};
Just add some console.log('xxxxxxxxxxxxx') calls in the file and in each function to see if the code is even executed.
I already did it. The code is called and the transformation is done. I thought I could be using the "next" function in a wrong way, but I checked the code of other preprocessors (e.g. CoffeeScript). They basically use the same approach. Thank you anyway for your feedback @johnbarton. I believe it is a silly mistake of mine.
In my case I need the path information because I wrote a Karma reporter that genarates a Sonarqube test report. A XML file containing all test results and also the path of each test spec file. Providing these paths, Sonarqube is able to show the test code through its web interface.
Currently, I'm using an heuristic to find the test spec file paths based on "describe" and "it" comments passed by Karma. It doesn't work in some cases. For example, dynamic test cases. That is way I'm trying a different strategy.
Did you find a workaround for your use case @Globegitter?
Another debugging suggestion is to run with --logLevel=debug.
At what point do the .ts files get compiled to .js?
Considering the log output, I believe Tyescript files are transpiled after preprocessor executIon. Though I'm not 100% sure since I'm running Karma using Angular CLI "ng test" command. Not directly. What I do know for sure is when I replace the glob "**/*.spec.ts" by "**/*.spec.js", my preprocessor isn't called...
@johnjbarton I think I understood why this doesn't work. After running the tests I opened the browser's console and I saw there was an error:
Refused to execute script from 'http://localhost:9876/base/about/about.component.spec.ts?f2e42dbfbc22fc25e9d526addc7931e5be14c5cb' because its MIME type ('video/mp2t') is not executable.
This made me to realize preprocessed files don't replace original spec test files as I expected. In reality, they are included as base scripts:
// context.html
<script type="text/javascript">
// Configure our Karma and set up bindings
window.__karma__.config = {
"args": [],
"useIframe":true,
"runInParent":false,
"captureConsole":true,
"clearContext":false
};
window.__karma__.setupContext(window);
// All served files with the latest timestamps
window.__karma__.files = {
// I supressed some files to reduce the code
'/base/about/about.component.spec.ts': 'f2e42dbfbc22fc25e9d526addc7931e5be14c5cb'
};
</script>
Conclusion: using preprocessors to change test code on the fly is not possible. At least not this way :)
Is that right?
Based on what I see here, I would reach a different conclusion: no matter what kind of preprocessing we apply to TypeScript files, the browser will not be able to execute the result unless we compile it to JavaScript.