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

toHaveStyleRule with @media rule breaks after styled-components update #430

Open
jkettmann opened this issue Jul 31, 2023 · 6 comments
Open

Comments

@jkettmann
Copy link

jkettmann commented Jul 31, 2023

We recently updated styled-components to v6 and something caused some of our tests to fail. I was able to reproduce the issue in this repository (you can also run it here on Replit). Here's the example test:

import 'jest-styled-components';
import { render, screen } from '@testing-library/react';
import { styled } from 'styled-components';

const StyledDiv = styled.div`
  @media (min-width: 400px) {
    color: red;
  }
`;

function MyComponent() {
  return <StyledDiv data-testid="styled-div" />;
}

describe('toHaveStyleRule media test', () => {
  test('has red color on larger devices', async () => {
    render(<MyComponent />);

    const styledDiv = screen.getByTestId('styled-div');
    expect(styledDiv).toHaveStyleRule('color', 'red', {
      media: '(min-width: 400px)',
    });
  });
});

This is the error I'm getting:

CleanShot 2023-07-31 at 17 34 29

The problem seems to be that this check in toHaveStyleRule rule[option] === options[option].replace(/:\s/g, ":") is not working anymore.

const getAtRules = (ast, options) => {
  return Object.keys(options)
    .map((option) =>
      ast.stylesheet.rules
        .filter((rule) => rule.type === option && rule[option] === options[option].replace(/:\s/g, ":"))
        .map((rule) => rule.rules)
        .reduce((acc, rules) => acc.concat(rules), [])
    )
    .reduce((acc, rules) => acc.concat(rules), []);
};

Before rule.option didn't have a whitespace. I'm not sure what changed but now it looks like this:

CleanShot 2023-07-31 at 17 28 58

I'm happy to create a PR but as I said, I'm not sure what the original cause of the whitespace not being removed is.

Edit: To run the tests in the Replit simply run npm run test.

@jkettmann
Copy link
Author

Removing the whitespace from the ast rule as well should be a simple and backwards compatible change:

const getAtRules = (ast, options) => {
  return Object.keys(options)
    .map((option) =>
      ast.stylesheet.rules
        .filter((rule) => rule.type === option && rule[option].replace(/:\s/g, ":") === options[option].replace(/:\s/g, ":"))
        .map((rule) => rule.rules)
        .reduce((acc, rules) => acc.concat(rules), [])
    )
    .reduce((acc, rules) => acc.concat(rules), []);
};

@jkettmann
Copy link
Author

If someone else encounters the same problem before this issue is closed a simple workaround is to add a second whitespace as in this example:

describe('toHaveStyleRule media test', () => {
  test('has red color on larger devices', async () => {
    render(<MyComponent />);

    const styledDiv = screen.getByTestId('styled-div');
    expect(styledDiv).toHaveStyleRule('color', 'red', {
      media: '(min-width:  400px)',
    });
  });
});

Note the two whitespaces in min-width: 400px

@hemerson-git
Copy link

If someone else encounters the same problem before this issue is closed a simple workaround is to add a second whitespace as in this example:

describe('toHaveStyleRule media test', () => {
  test('has red color on larger devices', async () => {
    render(<MyComponent />);

    const styledDiv = screen.getByTestId('styled-div');
    expect(styledDiv).toHaveStyleRule('color', 'red', {
      media: '(min-width:  400px)',
    });
  });
});

Note the two whitespaces in min-width: 400px

You saved my life, I'm about 2 days trying to fix that issue.
Thank you so much.

@jkettmann
Copy link
Author

@hemerson-git I'm glad this was helpful 🙂

@caribou-code
Copy link

Is there a plan to fix this in the package? In my case, media query strings are stored in a theme with a single whitespace after the colon, so this is a pain to manipulate the string every time I run a test like this.

@odanielsantana
Copy link

odanielsantana commented May 19, 2024

Same problem here.

If someone else encounters the same problem before this issue is closed a simple workaround is to add a second whitespace as in this example:

describe('toHaveStyleRule media test', () => {
  test('has red color on larger devices', async () => {
    render(<MyComponent />);

    const styledDiv = screen.getByTestId('styled-div');
    expect(styledDiv).toHaveStyleRule('color', 'red', {
      media: '(min-width:  400px)',
    });
  });
});

Note the two whitespaces in min-width: 400px

This helped so much broh! Thank you!

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

No branches or pull requests

4 participants