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

Custom reporter integration #3064

Closed
wants to merge 63 commits into from

Conversation

abdulhannanali
Copy link
Contributor

@abdulhannanali abdulhannanali commented Mar 4, 2017

Summary
This PR adds the ability to specify custom reporter to be used with Jest. Right now, there's no way for the user to specify the custom reporter they want to use, without tinkering the internals. This let's them specify the Custom reporter(s) if any users want to use with their tests.

This PR relies heavily on the work @DmitriiAbramov did in #2115 for adding XUnitReporter. Right now, only the interface through which we can use different reporters has been developed. Reporters such as Nyan and XUnitReporter are work in progress.

This PR reuses

Test plan

Integration tests for custom reporters are work in progress.

@@ -57,6 +57,9 @@ module.exports = ({
noStackTrace: false,
notify: false,
preset: 'react-native',
reporters: [
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@thymikee Would appreciate some feedback from you on this. There was ValidationError being thrown but after a certain number of tries when I added a sample reporters file here, it stopped throwing the error. Shouldn't adding it to types/Config.js be suffice

Copy link
Collaborator

Choose a reason for hiding this comment

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

nope, types/Config.js holds types for Flow (which is stripped with babel for runtime). jest-validate checks for actual valid JS object, which in our case is validConfig.js.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool makes sense thanks

@@ -354,6 +354,9 @@ function normalize(config: InitialConfig, argv: Object = {}) {
case 'persistModuleRegistryBetweenSpecs':
case 'preset':
case 'replname':
case 'reporters':
value = _replaceRootDirTags(config.rootDir, config[key]);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The previous PR #2115 adds a validation here in order to check the type of the options passed. But after jest-validate that doesn't seem to be necessary.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It is necessary, jest-validate only checks for your config to be valid against an example and throws otherwise, it doesn't modify anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@thymikee So, If you take a look at the #2115 it adds in a type validation here, which is doing Array.isArray to type check if it's an array, but do we really need that here. As I am getting a ValidationError just based on what's there in validConfig.js.

Here's the ValidationError, I think this error should be suffice. Do we need a custom error here.

 Validation Error:

  Option "reporters" must be of type:
    array
  but instead received:
    string

  Example:
  {
    "reporters": [["./here-it-goes.js", {"option1": true}]]
  }

  Configuration Documentation:
  https://facebook.github.io/jest/docs/configuration.html

@abdulhannanali
Copy link
Contributor Author

The first custom reporter is going to be a Nyan Cat, as it's trivial to implement

@abdulhannanali
Copy link
Contributor Author

abdulhannanali commented Mar 4, 2017

@thymikee I am interested in knowing how we can add a better validation check for the Reporters being imported,

Unexpected custom reporter configuration.
Expected to get either a path string or an array of [path, confg]
got: ${JSON.stringify(entry)}
`);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will be quite heavily indented

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I can see this dirsrupting the output badly. Instead of using a Custom Error message, Are there any functions in jest-validate specifically for this purpose?

Copy link
Contributor

Choose a reason for hiding this comment

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

i actually always use that kind of error messages and i don't mind them being so heavily indented.
maybe we can add a shared utility function that trims indentation to the minimum value of the block?
probably shouldn't be addressed in this PR tho

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes we can have a function similar to what we are doing with createConfigError maybe. I'll open up another PR for this purpose, after some time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@thymikee @DmitriiAbramov Ideally will this be added to jest-validate or I guess Validate can be used here, since it's kind of a validation error.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be great if we could extend validation possibilities. Right now it's indeed pretty limited.

Copy link
Member

Choose a reason for hiding this comment

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

There is a module on npm for this purpose called dedent. The code style Jest uses here is to separate multiline strings by using string concatenation. Please follow this style here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cpojer Will do that however, it's going to be a temporary fix, as we need this to be in jest-validate ideally.

@@ -379,6 +379,10 @@ class TestRunner {
_setupReporters() {
const config = this._config;

if (config.reporters) {
return this._addCustomReporters(config.reporters);
Copy link
Collaborator

Choose a reason for hiding this comment

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

So when you setup any custom reporter, you're getting rid of all default ones, like DefaultReporter, CoverageReporter, SummaryReporter? I'm not happy with that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ooopsie! Let me change this. It was added there for testing purposes. Thanks for pointing it out.

Copy link
Contributor

Choose a reason for hiding this comment

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

although in some cases that might be a desired behavior. I'm not really sure how to go about that. maybe add another option noDefaultReporters: true?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@DmitriiAbramov Makes sense will add this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@DmitriiAbramov The configuration open noDefaultReporters: true has been added. One concern here is, Should this option only perform the desired behavior when it's used in tandem with config.reporters and otherwise give a warning maybe? Or should it work regardless of config.reporters?

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 have added the first iteration of this which used regardless of reporters option specified or not.

@@ -57,6 +57,9 @@ module.exports = ({
noStackTrace: false,
notify: false,
preset: 'react-native',
reporters: [
Copy link
Collaborator

Choose a reason for hiding this comment

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

nope, types/Config.js holds types for Flow (which is stripped with babel for runtime). jest-validate checks for actual valid JS object, which in our case is validConfig.js.

@abdulhannanali
Copy link
Contributor Author

abdulhannanali commented Mar 4, 2017

@DmitriiAbramov In a Test Suite, Can we consider the the fullPath of the test as the value for the classname and package attribute within tescase and testsuite tag.?

@abdulhannanali
Copy link
Contributor Author

abdulhannanali commented Mar 4, 2017

Not adding it in this PR as @DmitriiAbramov suggested, but here's the initial version of XUnitReporter written to be used a Custom Reporter. Any feedback is welcomed. https://gist.github.com/abdulhannanali/6560aa5f53e65ca3cf92fb9ad0836d02 . I was going to push this too, but thanks to @DmitriiAbramov for pointing it out that it should be a separate PR.

noDefaultReporters option let's user turn
off all the reporters set by default
// Checking for the method _addCustomReporters
// Custom reporters used here are the reporters within the package
// No extra reporters are included to be used
describe('_addCustomReporters', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@thymikee Hey! I am new to testing. Wrote some unit tests to check the integration. Would you mind giving it a review?

runner._addCustomReporters(reporters);
};

expect(addInvalidReporters).toThrow();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Calling this passes the test, but at the same time throws an error too, because of the require calls that are done. Is there any way I can avoid this?

Copy link
Contributor

Choose a reason for hiding this comment

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

you can create a mock file and require it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@DmitriiAbramov But then the error which is currently thrown won't be thrown. We need to check if the error is thrown. I am doubtful at this point, if really need to test for this, as here we are checking if the require is going to throw invalid error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@DmitriiAbramov Sorry! I think this test is way too ambiguous these aren't invalid but non existent reporters. Should be more clearer. Removing this test for now.

Copy link
Contributor Author

@abdulhannanali abdulhannanali Mar 8, 2017

Choose a reason for hiding this comment

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

However, I still would like to clarify, if Mock file is going to be helpful in testing for the case where we are checking if file exists or not.

@@ -38,6 +38,115 @@ test('.addReporter() .removeReporter()', () => {
expect(runner._dispatcher._reporters).not.toContain(reporter);
});

describe('noDefaultReporters option', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding test for noDefaltReporters option. As I am using this same option for testing the reporters in the next describe function block too.

let runner;

beforeEach(() => {
runner = new TestRunner({}, {noDefaultReporters: true}, {});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using noDefualtReporters here to make the addition of tests easier.

@abdulhannanali
Copy link
Contributor Author

abdulhannanali commented Mar 6, 2017

One of the major concern I need to clear out is how the path resolution for the reporters will work. I am currently working on Integration Tests for Custom reporters and for this purpose I am writing a simple reporter, which just checks if the whole integration of reporters work fine.

@abdulhannanali
Copy link
Contributor Author

abdulhannanali commented Mar 6, 2017

@DmitriiAbramov The Reporters in the Jest extend from a BaseReporter, but in Mocha the biggest difference is that the BaseReporter is responsible for keeping track of the whole progress of the tests within it's stats object while the BaseReporter within the Jest is just exposing two more methods and removing the preRunMessage.

We can even remove the BaseReporter. However, it has a few advantages, as the code in the TestRunner would break if the reporters don't implement all of the methods on the base reporter. Also, we can additionally check in the code if the reports are inheriting from BaseReporter, adding kind of a validation check, but we definitely need a way to expose BaseReporter to the application.

this.addReporter(
config.verbose ? new VerboseReporter(config) : new DefaultReporter(),
);

Copy link
Member

Choose a reason for hiding this comment

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

please don't add more than two newlines at a time :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 to no multiple empty lines in a separate PR!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 for no-multiple-empty-lines like in StandardJS..

Copy link
Member

Choose a reason for hiding this comment

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

@abdulhannanali mind sending a separate PR that adds that lint rule? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cpojer Definitely thanks a lot! 👍

]
],
"eslint.enable": true,
"javascript.validate.enable": false
Copy link
Member

Choose a reason for hiding this comment

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

hmmm.. should we really add this here? Shall we do it in a separate PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a big mistake. I get this committed with each PR I do, as this is part of my development workflow. Sorry! Will remove it.


// Default Reporters are setup when
// noDefaultReporters is false, which is false by default
// and can be set to true in configuration.
Copy link
Member

Choose a reason for hiding this comment

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

I think this comment is superfluous as it describes what the if statement does. Mind removing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, need to get over this habit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comments that describe what statements does are superfluous. Noted! Will remove them!

${JSON.stringify(reporterPath)}
Config:
${JSON.stringify(reporterConfig)}
`);
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 print this similarly to how we are already printing warnings/errors, with colors etc? I don't think you need JSON.stringify for the reporterPath, for example.

@@ -9,11 +9,11 @@ const assign = require('object-assign');

const center = React.createClass({
render() {
let {style, ...props} = this.props;
style = assign({}, style, {textAlign: 'center'});
const {style, ...props} = this.props;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doing this to get all the code linted, this is an eslint error as we were previously reassigning to style.

@abdulhannanali abdulhannanali changed the title [WIP] Custom reporter integration Custom reporter integration Apr 5, 2017
@abdulhannanali
Copy link
Contributor Author

@DmitriiAbramov @cpojer I have pushed the working version containing the tests. The custom reporters right now are reusing much of the Reporter functionality Jest already has for it's own reporters. The API to implement custom reporters is exactly the same. It's kind of really providing the hook with which you can add your own custom reporter.

In order for the reporters to confirm to the standard, I implemented a _validateReporters method which validates the reporter by checking if various methods are implemented for sure, but since this makes it very unflexible I removed it.

I would like to know any other suggestions, I have removed the [WIP] prefix from this PR too.

Thank you for your help everyone ❤️

@abdulhannanali
Copy link
Contributor Author

Circle CI build is failed for some weird yarn reason, I have nothing to do with

@bookman25
Copy link
Contributor

Does this allow for reporters being passed in via the CLI? It didn't look like it, but I might have missed it. For jest-editor-support it would a big benefit to have CLI support for the reports arg.

@abdulhannanali
Copy link
Contributor Author

@bookman25 As discussed before, this PR will only add the capability for the jest-config. A separate PR should be opened if we want to add the capability to CLI too. However, I haven't given a lot of thought to it, right now, even though Karma and Ava already does it.. Will think about it once this one is merged.

@aaronabramov aaronabramov mentioned this pull request Apr 22, 2017
@aaronabramov
Copy link
Contributor

closing in favor of #3349

@github-actions
Copy link

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants