styled-components / jest-styled-components

🔧 💅 Jest utilities for Styled Components
MIT License
1.59k stars 144 forks source link

Snapshot with different ordering of classes #289

Open ArTiSTiX opened 4 years ago

ArTiSTiX commented 4 years ago

I have this strange issue when execution snapshot testing of components in different environments (local). I have multiple environments which runs the same tests, and produce the same snapshots, but on CircleCI, one of the snapshots differs, only in the order of the generated classes.

I checked all the version, locked with yarn.lock:

All environments are exactly the same and run with BABEL_ENV=test jest --ci --maxWorkers=2, i even cleared out dependencies cache of CircleCI to ensure we are locked to yarn.lock.

Here is the snapshot difference given by CI:

expect(received).toMatchSnapshot()

    Snapshot name: `<Component /> Simple should render without a problem 1`

    - Snapshot
    + Received

    @@ -7,11 +7,11 @@

      .c11 {
        padding-right: 0.8rem;
      }

    - .c13 {
    + .c12 {
        display: flex;
      }

    - .c13:hover {
    + .c12:hover {
        background: blue;
      }

    - .c12 {
    + .c12,
    + .c12:hover {
    +   background: transparent;
    +   color: blue;
    + }
    + 
    + .c13 {
        display: flex;
      }

    - .c12:hover {
    + .c13:hover {
        background: red;
    - }
    - 
    - .c12,
    - .c12:hover {
    -   background: transparent;
    -   color: blue;
      }

      .c14 {
        display: -webkit-box;
        display: -webkit-flex;

      34 |       const { container } = render(<Component defaultValue={value} />);
      35 | 
    > 36 |       expect(container.firstChild).toMatchSnapshot();
         |                                    ^
      37 |     });

Looks like c12 and c13 are inverted, Local snapshotting presents a .c13 class before .c12, but CircleCI presents .c12 then .c13 with inverted logic.

If i understand correctly, the classes are generated depending on the order of appearance/usage ? This component test ensures classes appear in the same order (DOM snapshot has no difference). I tried multiple solutions, like changing the style order, etc... it only changed the content of styles, not this ordering issue.

Here is the style responsible:

export const Content = styled.div`
  display: flex;

  &:hover {
    background: blue;
  }

  &,
  &:hover {
    ${({ someProp }) =>
      someProp &&
      css`
        background: transparent;
        color: blue;
      `};
  }
`;

NOTE: code cleaned out of unnecessary data.

Any clue ?

ArTiSTiX commented 4 years ago

I tried snapshotting only the atom component separately, with all variants found when included. Thing is, this test passes, and have no issue with order: test.js

  test('should render multiple days without a problem', () => {
    const { container } = render(
      <>
        <Day shadowed>10</Day>
        <Day isSelected>11</Day>
        <Day isStartEdge>12</Day>
        <Day isInPath>13</Day>
        <Day isEndEdge>14</Day>
        <Day>15</Day>
        <Day shadowed>16</Day>
        <Day disabled>17</Day>
      </>,
    );
Snapshot (sorry no clean) ``` exports[`Day should render multiple days without a problem 1`] = ` .c0 { margin-top: 0.8rem; font-size: 1.4rem; color: hsl(213,17%,20%); cursor: pointer; } .c0:not(:nth-child(7n)) { padding-right: 0.8rem; } .c3 { margin-top: 0.8rem; font-size: 1.4rem; color: hsl(213,17%,20%); border-top-left-radius: 2.8rem; border-bottom-left-radius: 2.8rem; cursor: pointer; } .c3:not(:nth-child(7n)) { padding-right: 0.8rem; } .c5 { margin-top: 0.8rem; font-size: 1.4rem; color: hsl(213,17%,20%); background: rgba(30,146,204,0.14); cursor: pointer; } .c5:not(:nth-child(7n)) { padding-right: 0.8rem; } .c7 { margin-top: 0.8rem; font-size: 1.4rem; color: hsl(213,17%,20%); border-top-right-radius: 2.8rem; border-bottom-right-radius: 2.8rem; cursor: pointer; } .c7:not(:nth-child(7n)) { padding-right: 0.8rem; } .c7:not(:nth-child(7n)) { padding-right: 0; margin-right: 0.8rem; } .c6 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-flex-basis: 2.8rem; -ms-flex-preferred-size: 2.8rem; flex-basis: 2.8rem; width: 2.8rem; height: 2.8rem; max-width: 2.8rem; border-radius: 2.8rem; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .c6:hover { background: rgba(30,146,204,0.14); } .c1 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-flex-basis: 2.8rem; -ms-flex-preferred-size: 2.8rem; flex-basis: 2.8rem; width: 2.8rem; height: 2.8rem; max-width: 2.8rem; border-radius: 2.8rem; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .c1:hover { background: rgba(30,146,204,0.14); } .c1, .c1:hover { background: transparent; color: hsl(206,23%,69%); } .c2 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-flex-basis: 2.8rem; -ms-flex-preferred-size: 2.8rem; flex-basis: 2.8rem; width: 2.8rem; height: 2.8rem; max-width: 2.8rem; border-radius: 2.8rem; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .c2:hover { background: rgba(30,146,204,0.14); } .c2, .c2:hover { color: hsl(0,100%,100%); background: hsl(200,74%,46%); } .c4 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-flex-basis: 2.8rem; -ms-flex-preferred-size: 2.8rem; flex-basis: 2.8rem; width: 2.8rem; height: 2.8rem; max-width: 2.8rem; border-radius: 2.8rem; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border-top-right-radius: 0; border-bottom-right-radius: 0; } .c4:hover { background: rgba(30,146,204,0.14); } .c4, .c4:hover { color: hsl(0,100%,100%); background: hsl(200,74%,46%); } .c8 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-flex-basis: 2.8rem; -ms-flex-preferred-size: 2.8rem; flex-basis: 2.8rem; width: 2.8rem; height: 2.8rem; max-width: 2.8rem; border-radius: 2.8rem; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border-top-left-radius: 0; border-bottom-left-radius: 0; } .c8:hover { background: rgba(30,146,204,0.14); } .c8, .c8:hover { color: hsl(0,100%,100%); background: hsl(200,74%,46%); } .c9 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-flex-basis: 2.8rem; -ms-flex-preferred-size: 2.8rem; flex-basis: 2.8rem; width: 2.8rem; height: 2.8rem; max-width: 2.8rem; border-radius: 2.8rem; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .c9:hover { background: rgba(30,146,204,0.14); } .c9, .c9:hover { cursor: not-allowed; background: transparent; color: hsl(207,22%,90%); }
10
11
12
13
14
15
16
17
`; ```

So why when including this component in a parent one, class order could differ when snapshotting ?

What could explain this class swap while all package versions are locked ?

The only difference i KNOW, is that CircleCi environment is a Linux 92ac78610905 4.15.0-1052-aws #54-Ubuntu SMP Tue Oct 1 15:43:26 UTC 2019 x86_64 Linux while snapshots were written on MacOS Mojave / Catalina.

-- EDIT: the best solution I found :disappointed: :

const { CIRCLECI } = process.env;
const ignoreCircleCiTest = CIRCLECI === 'true' ? xit : test;

ignoreCircleCiTest('should render without a problem', () => { ... }
IlyaCherkasov commented 4 years ago

I don't think that's the best idea to skip tests in remote repo Hope someone can help with it In my case only names of classes changes. I'm running tests localy on Linux and remote in Linux container but have the same issue... UPD. In my case using styled() was the reason of bug. So I needed to import only styled variable or to make sure that I don't need to modify that component

Polarisation commented 4 years ago

I'm seeing what looks like the same issue.

I am creating snapshots on macOS, and running tests on Ubuntu using a GitHub action. The macOS snapshot contains className="testing c0" but the GitHub action generates className="c0 testing". So maybe

I also had a className order issue before installing jest-styled-components - I was hoping it would fix any className issues. Before installing it, macOS was generating className="testing sc-bdVaJa OXYu" but the GitHub action was generating className="sc-bdVaJa OXYu testing". This suggests the bug is not with jest-styled-components, but perhaps styled-components itself.