Skip to content

Commit

Permalink
Add "similar" debugging to toHaveCompiledCss (#1619)
Browse files Browse the repository at this point in the history
* Add "similar" debugging to `toHaveCompiledCss`

I found it difficult to debug with `toHaveCompiledCss`, particularly in the case of local css variables being resolved by jest-dom (I think that's how it works), as the error for "could not find `padding: 8px`" doesn't tell you if it was wrong or just doesn't exist.

```tsx
expect(element).toHaveCompiledCss({ paddingInlineEdit: '8px' });
```
```sh
    Could not find "padding-inline-end:8px" on <a data-testid="test-link" class="css-1mufnsm">…</a> element.
```

Now this should have a a clearer error:
```tsx
    Could not find "padding-inline-end:8px" on <a data-testid="test-link" class="css-1mufnsm">…</a> element.

    Found similar styles:
    padding-inline-end:var(--ds-space-0, 0px)
    padding-inline-end:var(--ds-space-100, 8px)
```

This could go a step further and show all css properties or have a debug mode I couldn't find, but that could get quite spammy…

* chore: changeset
  • Loading branch information
kylorhall-atlassian authored Feb 2, 2024
1 parent da6fc56 commit 749994b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-worms-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@compiled/jest': patch
---

Add "found similar styles" to assist debugging to the `toHaveCompiledCss` matcher.
64 changes: 47 additions & 17 deletions packages/jest/src/matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,29 @@ const getRules = (ast: CSS.Stylesheet, filter: MatchFilter, className: string) =

const findStylesInRules = (styles: string[], rules: CSS.Rule[] | undefined) => {
const found: string[] = [];

if (!rules) return found;

styles.forEach((s) => {
rules?.forEach((r) => {
if ('declarations' in r) {
r.declarations?.forEach((d) => {
if ('property' in d) {
if (s === `${d.property}:${d.value}`) found.push(s);
}
});
}
const similar: string[] = [];

if (rules) {
styles.forEach((s) => {
rules?.forEach((r) => {
if ('declarations' in r) {
r.declarations?.forEach((d) => {
if ('property' in d) {
if (s === `${d.property}:${d.value}`) {
// We found this exact match, eg. `color:#fff`
found.push(s);
} else if (s.split(':')[0] === d.property) {
// We found something similar by property, eg. `color:#fff` vs. `color:#333`
similar.push(`${d.property}:${d.value}`);
}
}
});
}
});
});
});
return found;
}

return { found, similar };
};

export function toHaveCompiledCss(
Expand All @@ -107,6 +115,7 @@ export function toHaveCompiledCss(

const stylesToFind = mapProperties(properties);
const foundStyles: string[] = [];
const similarStyles: string[] = [];
const classNames = element.className.split(' ');

for (const styleElement of styleElements) {
Expand All @@ -129,13 +138,15 @@ export function toHaveCompiledCss(
const ast = CSS.parse(css);
classNames.forEach((c) => {
const rules = getRules(ast, matchFilter, c);
foundStyles.push(...findStylesInRules(stylesToFind, rules));
const search = findStylesInRules(stylesToFind, rules);

foundStyles.push(...search.found);
similarStyles.push(...search.similar);
});
}

const notFoundStyles = stylesToFind.filter((style) => !foundStyles.includes(style));
const foundFormatted = stylesToFind.join(', ');
const notFoundFormatted = notFoundStyles.join(', ');

if (foundStyles.length > 0 && notFoundStyles.length === 0) {
return {
Expand All @@ -146,8 +157,27 @@ export function toHaveCompiledCss(
};
}

const notFoundFormatted = notFoundStyles.join(', ');
const notFoundProperties = notFoundStyles.map((style) => style.split(':')[0]);
const similarStylesFormatted = similarStyles
.reduce<string[]>((acc, keyValue) => {
const property = keyValue.split(':')[0];

if (notFoundProperties.includes(property)) {
acc.push(keyValue);
}
return acc;
}, [])
.join('\r\n');
const similarStylesMessage = !similarStylesFormatted
? 'Found 0 styles with matching properties.'
: `Found similar styles:
${similarStylesFormatted}`;

return {
pass: false,
message: () => `Could not find "${notFoundFormatted}" on ${element.outerHTML} element.`,
message: () => `Could not find "${notFoundFormatted}" on ${element.outerHTML} element.
${similarStylesMessage}`,
};
}

0 comments on commit 749994b

Please sign in to comment.