Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Add hidden legendPosition to Chart. #7378

Merged
merged 4 commits into from
Jul 27, 2021
Merged

Add hidden legendPosition to Chart. #7378

merged 4 commits into from
Jul 27, 2021

Conversation

tomalec
Copy link
Member

@tomalec tomalec commented Jul 18, 2021

  1. Add hidden legendPosition to Chart.
    Sometimes, for example, when there is a single data set, there is no need for rendering the legend. It may even introduce more confusion than value. It seems interactive, but there is nothing you can do with it.

    Interactive looking, non-interactive legend

    Fixes: legendPosition: 'hidden' warning on the report pages google-listings-and-ads#618

  2. Add @storybook/addon-knobs to devDependencies.
    It was used but not explicitly stated.

Accessibility

Screenshots:

hidden

Detailed test instructions:

  1. Create <Chart data={ data } legendPosition="hidden" >
  2. Check that no legend is rendered.

or

  1. npm run storybook
  2. visit http://localhost:6007/?path=/docs/woocommerce-admin-components-chart--default play with legendPosition knob

Copy link
Contributor

@louwie17 louwie17 left a comment

Choose a reason for hiding this comment

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

@tomalec thanks for creating a pull request for this and for updating the story book as well.
I think this will be a great addition.
This tested well and the code looks good!

I am approving this, although for some bonus points it would be great to have some tests for this (I do realize we have zero tests for this component at the moment 🙈 so I am leaving it optional )

@tomalec
Copy link
Member Author

tomalec commented Jul 23, 2021

for some bonus points it would be great to have some tests for this

I'd love to, but had a hard time running the existing ones. Running all for the entire repo is too much for my machine ;).

I tried npm install && npm run test from /packages/components/ only, but it fails on install. Do you have any hints, on how to run only a subset of tests for only a single package?

@louwie17
Copy link
Contributor

I tried npm install && npm run test from /packages/components/ only, but it fails on install. Do you have any hints, on how to run only a subset of tests for only a single package?

Thanks for pointing that out, it indeed doesn't work very well after we restructured this.
Running ./node_modules/.bin/jest --config=packages/components/jest.config.json seems to be the easiest for the components package. You can tag on --watch to keep them running in the background.

@tomalec
Copy link
Member Author

tomalec commented Jul 23, 2021

Running ./node_modules/.bin/jest --config=packages/components/jest.config.json seems to be the easiest […]

Thanks :) That works!


Also, I cannot find any components/**/test/*.js that uses window, as my tests fails due to

TypeError: Cannot read property 'addEventListener' of null

I tried

/**
 * @jest-environment jsdom
 */

and naively mocking window but with no avail :(

@tomalec
Copy link
Member Author

tomalec commented Jul 23, 2021

Using window.addEventListener itself looks like a bug to me. As I guess what we actually need there is resize observer.

@louwie17
Copy link
Contributor

louwie17 commented Jul 23, 2021

Also, I cannot find any components/**/test/*.js that uses window, as my tests fails due to

TypeError: Cannot read property 'addEventListener' of null

I tried

/**
 * @jest-environment jsdom
 */

and naively mocking window but with no avail :(

Oooh shoot that is not great, we do mock the window object in a couple different places like this:
https://github.com/woocommerce/woocommerce-admin/blob/main/client/navigation/components/container/test/index.js#L28-L32

I wonder if it an issue with the jest.config.json file in components, does it fix it if you remove the ../ from here? https://github.com/woocommerce/woocommerce-admin/blob/main/packages/components/jest.config.json#L3
As the js-tests folder is only one directory up.
The js-tests config adds the window globals -> https://github.com/woocommerce/woocommerce-admin/blob/main/packages/js-tests/jest.config.js#L21-L22

Clearly this requires some cleaning up. If this becomes to much of a hassle, you can merge it and I can create an issue for writing up some tests.

@tomalec
Copy link
Member Author

tomalec commented Jul 23, 2021

Oooh shoot that is not great, we do mock the window object in a couple different places like this:
main/client/navigation/components/container/test/index.js#L28-L32

The result is still the same: TypeError: Cannot read property 'addEventListener' of null not that this is null not undefined which is pretty strange to me.

I wonder if it an issue with the jest.config.json file in components, does it fix it if you remove the ../ from here? main/packages/components/jest.config.json#L3
As the js-tests folder is only one directory up.

● Validation Error:

  Preset ../js-tests/jest.config.js is invalid:

  The "id" argument must be of type string. Received null
  TypeError [ERR_INVALID_ARG_TYPE]: The "id" argument must be of type string. Received null
    at validateString (internal/validators.js:120:11)
    at Module.require (internal/modules/cjs/loader.js:880:3)
    at require (internal/modules/cjs/helpers.js:74:18)
    at setupPreset (/home/tomalec/repos/woocommerce-admin/node_modules/jest/node_modules/jest-config/build/normalize.js:299:14)
    at normalize (/home/tomalec/repos/woocommerce-admin/node_modules/jest/node_modules/jest-config/build/normalize.js:652:15)
    at readConfig (/home/tomalec/repos/woocommerce-admin/node_modules/jest/node_modules/jest-config/build/index.js:220:68)
    at async readConfigs (/home/tomalec/repos/woocommerce-admin/node_modules/jest/node_modules/jest-config/build/index.js:401:26)
    at async runCLI (/home/tomalec/repos/woocommerce-admin/node_modules/jest/node_modules/@jest/core/build/cli/index.js:198:59)
    at async Object.run (/home/tomalec/repos/woocommerce-admin/node_modules/jest/node_modules/jest-cli/build/cli/index.js:173:37)

  Configuration Documentation:
  https://jestjs.io/docs/configuration.html

@tomalec tomalec mentioned this pull request Jul 26, 2021
@tomalec
Copy link
Member Author

tomalec commented Jul 26, 2021

I double-checked, that this is in fact complaining about the window.addEventListener used by <Chart> component
https://github.com/woocommerce/woocommerce-admin/blob/main/packages/components/src/chart/index.js#L104
For some reason, when setState is called at https://github.com/woocommerce/woocommerce-admin/blob/main/packages/components/src/chart/index.js#L102 jsdom fails to get the right window object and sets it to null, if we comment out this.updateDimensions it gets the correct window.

I thought updating (quite old 11.12.0) jsdom could help. Tried updating jest #7418. But there is a rabbit hole,/cascade of other outdated dependencies and compatibility issues with typescript ts-jest transformer, babel, etc. That might also be the cause of #6483


I'm afraid I had to give up. I already spend 2 days trying to untangle the overload of dependencies, build configs, and legacy code. And I start to think it's not worth too much so much effort for window.addEventListener which needs to be eventually removed anyway.

Naturally, it would be worth updating all those legacy versions, but I start to think, it would be easier to burn devDependencies with fire and start from scratch with a modern, collapsed stack.

@tomalec
Copy link
Member Author

tomalec commented Jul 26, 2021

The test I was trying to start with was:

/packages/components/src/chart/test/legend.js:
/**
 * @jest-environment jsdom
 */
/**
 * External dependencies
 */
import renderer from 'react-test-renderer';
import { createElement } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Chart from '../';

const data = [
	{
		date: '2018-05-30T00:00:00',
		Hoodie: {
			label: 'Hoodie',
			value: 21599,
		},
		Sunglasses: {
			label: 'Sunglasses',
			value: 38537,
		},
		Cap: {
			label: 'Cap',
			value: 106010,
		},
	},
	{
		date: '2018-05-31T00:00:00',
		Hoodie: {
			label: 'Hoodie',
			value: 14205,
		},
		Sunglasses: {
			label: 'Sunglasses',
			value: 24721,
		},
		Cap: {
			label: 'Cap',
			value: 70131,
		},
	},
];


describe( 'Chart', () => {
	test.skip( '<Chart legendPosition="hidden" /> should not render any legend', () => {
		const tree = renderer
			.create( <Chart data={ data } legendPosition="hidden" /> )
			.toJSON();
		expect( tree ).toMatchSnapshot();
	} );
	test.skip( '<Chart legendPosition="bottom" /> should render the legend at the bottom', () => {
		const tree = renderer
			.create( <Chart data={ data } legendPosition="bottom" /> )
			.toJSON();
		expect( tree ).toMatchSnapshot();
	} );
} );

BTW, I tried also * @jest-environment jest-environment-jsdom-sixteen which uses jsdom 16

@jeffstieler
Copy link
Contributor

For running a command in a single package, you can use the --scope parameter with lerna:

lerna --scope @woocommerce/components run test:nobuild --stream should work if you've already built the other packages, but isn't really any shorter of a command.

@louwie17
Copy link
Contributor

The test I was trying to start with was:

BTW, I tried also * @jest-environment jest-environment-jsdom-sixteen which uses jsdom 16

Thanks for sharing the testing file, I had a look and tried it locally. You might not like the fix given it end up being pretty simple. I guess the example you saw used an old test renderer, we usually use the render function from @testing-library/react. Here is a working test file:

/packages/components/src/chart/test/legend.js:

/**
 * @jest-environment jsdom
 */
/**
 * External dependencies
 */
import { render } from '@testing-library/react';
import { createElement } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Chart from '../';

jest.mock('../d3chart', () => ({
    D3Legend: jest.fn().mockReturnValue( '[D3Legend]' ),
}))

const data = [
	{
		date: '2018-05-30T00:00:00',
		Hoodie: {
			label: 'Hoodie',
			value: 21599,
		},
		Sunglasses: {
			label: 'Sunglasses',
			value: 38537,
		},
		Cap: {
			label: 'Cap',
			value: 106010,
		},
	},
	{
		date: '2018-05-31T00:00:00',
		Hoodie: {
			label: 'Hoodie',
			value: 14205,
		},
		Sunglasses: {
			label: 'Sunglasses',
			value: 24721,
		},
		Cap: {
			label: 'Cap',
			value: 70131,
		},
	},
];


describe( 'Chart', () => {
	test( '<Chart legendPosition="hidden" /> should not render any legend', () => {
		const { queryByText } = render( <Chart data={ data } legendPosition="hidden" /> );
        expect( queryByText( '[D3Legend]' ) ).not.toBeInTheDocument();
	} );
	test( '<Chart legendPosition="bottom" /> should render the legend at the bottom', () => {
        const { queryByText } = render( <Chart data={ data } legendPosition="bottom" /> );
        expect( queryByText( '[D3Legend]' ) ).toBeInTheDocument();
	} );
} );

@louwie17
Copy link
Contributor

For running a command in a single package, you can use the --scope parameter with lerna:

lerna --scope @woocommerce/components run test:nobuild --stream should work if you've already built the other packages, but isn't really any shorter of a command.

@jeffstieler thanks 😄 I think the only down side with this approach is that it doesn't allow for using --watch or specifying a specific test directory.

tomalec and others added 4 commits July 27, 2021 11:03
Sometimes, for example, when there is a single data set, there is no need for rendering the legend. It may even introduce more confusion than value. It seems interactive, but there is nothing you can do with it.

Fixes: woocommerce/google-listings-and-ads#618
It was used but not explicitely stated.
@louwie17 louwie17 merged commit 09426f4 into main Jul 27, 2021
@louwie17 louwie17 deleted the add/chart-hidden-legend branch July 27, 2021 14:14
tomalec added a commit that referenced this pull request Jul 27, 2021
from `react-test-renderer` to `{ render } from '@testing-library/react'`,
to avoid confision like #7378 (comment).

Update snapshots respectively.
@tomalec
Copy link
Member Author

tomalec commented Jul 27, 2021

FWIW, besides the renderer the remaining problems I faced locally with Jest, Babel & co. were related to running an older version of node 🤦‍♂️ (12), with 14.17.3 it works much better.

@psealock
Copy link
Collaborator

psealock commented Jul 28, 2021

@tomalec, here is a PR to update Jest to version 27. Until I started also updating several other dependencies some tests were failing for not obvious reasons, so hopefully that is the case here. When it gets merged, I'll give the test in this PR a spin.

EDIT: I should refresh the page before commenting! I see the test has been fixed and merge 🎉

tomalec added a commit that referenced this pull request Jul 30, 2021
from `react-test-renderer` to `{ render } from '@testing-library/react'`,
to avoid confision like #7378 (comment).

Update snapshots respectively.
ObliviousHarmony pushed a commit to woocommerce/woocommerce that referenced this pull request Mar 18, 2022
…n#7378)

* Add `hidden` legendPosition to `Chart`.

Sometimes, for example, when there is a single data set, there is no need for rendering the legend. It may even introduce more confusion than value. It seems interactive, but there is nothing you can do with it.

Fixes: woocommerce/google-listings-and-ads#618

* Add `@storybook/addon-knobs` to devDependencies.

It was used but not explicitely stated.

* Add a changelog entry.

* Add tests for legendPosition in Chart component

Co-authored-by: Lourens Schep <lourensschep@gmail.com>
ObliviousHarmony pushed a commit to woocommerce/woocommerce that referenced this pull request Mar 18, 2022
…n#7425)

from `react-test-renderer` to `{ render } from '@testing-library/react'`,
to avoid confision like woocommerce/woocommerce-admin#7378 (comment).

Update snapshots respectively.
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.

legendPosition: 'hidden' warning on the report pages
4 participants