Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jest-emotion

Package Overview
Dependencies
Maintainers
2
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jest-emotion - npm Package Compare versions

Comparing version 9.1.3 to 9.2.0

lib/matchers.js

105

lib/index.js
'use strict';
exports.__esModule = true;
exports.createMatchers = undefined;
var _matchers = require('./matchers');
Object.defineProperty(exports, 'createMatchers', {
enumerable: true,
get: function get() {
return _matchers.createMatchers;
}
});
exports.getStyles = getStyles;

@@ -13,2 +23,4 @@ exports.createSerializer = createSerializer;

var _utils = require('./utils');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

@@ -45,29 +57,2 @@

function getSelectorsFromClasses(selectors, classes) {
return classes ? selectors.concat(classes.split(' ').map(function (c) {
return '.' + c;
})) : selectors;
}
function getSelectorsFromProps(selectors, props) {
return getSelectorsFromClasses(selectors, props.className || props.class);
}
function getSelectorsForDOMElement(selectors, node) {
return getSelectorsFromClasses(selectors, node.getAttribute('class'));
}
function getSelectors(nodes) {
return nodes.reduce(function (selectors, node) {
return isReactElement(node) ? getSelectorsFromProps(selectors, node.props) : getSelectorsForDOMElement(selectors, node);
}, []);
}
function filterChildSelector(baseSelector) {
if (baseSelector.slice(-1) === '>') {
return baseSelector.slice(0, -1);
}
return baseSelector;
}
function getStyles(emotion) {

@@ -82,12 +67,2 @@ return Object.keys(emotion.caches.inserted).reduce(function (style, current) {

function isReactElement(val) {
return val.$$typeof === Symbol.for('react.test.json');
}
var domElementPattern = /^((HTML|SVG)\w*)?Element$/;
function isDOMElement(val) {
return val.nodeType === 1 && val.constructor && val.constructor.name && domElementPattern.test(val.constructor.name);
}
function createSerializer(emotion) {

@@ -102,10 +77,10 @@ var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},

markNodes(nodes);
var selectors = getSelectors(nodes);
var styles = getStylesFromSelectors(selectors);
var classNames = (0, _utils.getClassNamesFromNodes)(nodes);
var styles = getStylesFromClassNames(classNames);
var printedVal = printer(val);
return (0, _replaceClassNames.replaceClassNames)(selectors, styles, printedVal, emotion.caches.key, classNameReplacer);
return (0, _replaceClassNames.replaceClassNames)(classNames, styles, printedVal, emotion.caches.key, classNameReplacer);
}
function test(val) {
return val && !val.withEmotionStyles && (DOMElements ? isReactElement(val) || isDOMElement(val) : isReactElement(val));
return val && !val.withEmotionStyles && (DOMElements ? (0, _utils.isReactElement)(val) || (0, _utils.isDOMElement)(val) : (0, _utils.isReactElement)(val));
}

@@ -119,37 +94,23 @@

function getStylesFromSelectors(nodeSelectors) {
var styles = getStyles(emotion);
var ast = void 0;
function getStylesFromClassNames(classNames) {
var styles = '';
// This could be done in a more efficient way
// but it would be a breaking change to do so
// because it would change the ordering of styles
Object.keys(emotion.caches.registered).forEach(function (className) {
var indexOfClassName = classNames.indexOf(className);
if (indexOfClassName !== -1) {
var nameWithoutKey = classNames[indexOfClassName].substring(emotion.caches.key.length + 1);
// $FlowFixMe
styles += emotion.caches.inserted[nameWithoutKey];
}
});
var prettyStyles = void 0;
try {
ast = css.parse(styles);
prettyStyles = css.stringify(css.parse(styles));
} catch (e) {
console.error(e);
throw new Error('There was an error parsing css in jest-emotion-react: "' + styles + '"');
throw new Error('There was an error parsing css in jest-emotion: "' + styles + '"');
}
ast.stylesheet.rules = ast.stylesheet.rules.reduce(reduceRules, []);
var ret = css.stringify(ast);
return ret;
function reduceRules(rules, rule) {
var shouldIncludeRule = false;
if (rule.type === 'rule') {
shouldIncludeRule = rule.selectors.some(function (selector) {
var baseSelector = filterChildSelector(selector.split(/:| |\./).filter(function (s) {
return !!s;
})[0]);
return nodeSelectors.some(function (sel) {
return sel === baseSelector || sel === '.' + baseSelector;
});
});
}
if (rule.type === 'media' || rule.type === 'supports') {
rule.rules = rule.rules.reduce(reduceRules, []);
if (rule.rules.length) {
shouldIncludeRule = true;
}
}
return shouldIncludeRule ? rules.concat(rule) : rules;
}
return prettyStyles;
}

@@ -156,0 +117,0 @@

@@ -8,13 +8,12 @@ 'use strict';

var componentSelectorClassNamePattern = /\.e[a-zA-Z0-9-]+[0-9]+/;
var componentSelectorClassNamePattern = /e[a-zA-Z0-9-]+[0-9]+/;
var replaceClassNames = exports.replaceClassNames = function replaceClassNames(selectors, styles, code, key) {
var replaceClassNames = exports.replaceClassNames = function replaceClassNames(classNames, styles, code, key) {
var replacer = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : defaultClassNameReplacer;
var index = 0;
var classRegex = new RegExp('^\\.' + key + '-([a-zA-Z0-9-]+)');
return selectors.reduce(function (acc, className) {
if (classRegex.test(className) || componentSelectorClassNamePattern.test(className)) {
var escapedRegex = new RegExp(className.replace('.', '').replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'), 'g');
return classNames.reduce(function (acc, className) {
if (className.indexOf(key + '-') === 0 || componentSelectorClassNamePattern.test(className)) {
var escapedRegex = new RegExp(className.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'), 'g');
return acc.replace(escapedRegex, replacer(className, index++));

@@ -21,0 +20,0 @@ }

{
"name": "jest-emotion",
"version": "9.1.3",
"version": "9.2.0",
"description": "Jest utilities for emotion",

@@ -17,2 +17,3 @@ "main": "lib/index.js",

"dependencies": {
"chalk": "^2.4.1",
"css": "^2.2.1"

@@ -19,0 +20,0 @@ },

@@ -92,4 +92,32 @@ # jest-emotion

# Custom matchers
## toHaveStyleRule
To make more explicit assertions when testing your styled components you can use the `toHaveStyleRule` matcher.
```jsx
import React from 'react'
import renderer from 'react-test-renderer'
import { createMatchers } from 'jest-emotion'
import * as emotion from 'emotion'
import styled from 'react-emotion'
// Add the custom matchers provided by 'jest-emotion'
expect.extend(createMatchers(emotion))
test('renders with correct styles', () => {
const H1 = styled.h1`
float: left;
`
const tree = renderer.create(<H1>hello world</H1>).toJSON()
expect(tree).toHaveStyleRule('float', 'left')
expect(tree).not.toHaveStyleRule('color', 'hotpink')
})
```
## Thanks
Thanks to [Kent C. Dodds](https://twitter.com/kentcdodds) who wrote [jest-glamor-react](https://github.com/kentcdodds/jest-glamor-react) which this library is largely based on.

@@ -7,4 +7,7 @@ // @flow

} from './replace-class-names'
import { getClassNamesFromNodes, isReactElement, isDOMElement } from './utils'
import type { Emotion } from 'create-emotion'
export { createMatchers } from './matchers'
type Options = {

@@ -29,33 +32,2 @@ classNameReplacer: ClassNameReplacer,

function getSelectorsFromClasses(selectors, classes) {
return classes
? selectors.concat(classes.split(' ').map(c => `.${c}`))
: selectors
}
function getSelectorsFromProps(selectors, props) {
return getSelectorsFromClasses(selectors, props.className || props.class)
}
function getSelectorsForDOMElement(selectors, node) {
return getSelectorsFromClasses(selectors, node.getAttribute('class'))
}
function getSelectors(nodes) {
return nodes.reduce(
(selectors, node) =>
isReactElement(node)
? getSelectorsFromProps(selectors, node.props)
: getSelectorsForDOMElement(selectors, node),
[]
)
}
function filterChildSelector(baseSelector) {
if (baseSelector.slice(-1) === '>') {
return baseSelector.slice(0, -1)
}
return baseSelector
}
export function getStyles(emotion: Emotion) {

@@ -70,17 +42,2 @@ return Object.keys(emotion.caches.inserted).reduce((style, current) => {

function isReactElement(val) {
return val.$$typeof === Symbol.for('react.test.json')
}
const domElementPattern = /^((HTML|SVG)\w*)?Element$/
function isDOMElement(val) {
return (
val.nodeType === 1 &&
val.constructor &&
val.constructor.name &&
domElementPattern.test(val.constructor.name)
)
}
export function createSerializer(

@@ -93,7 +50,7 @@ emotion: Emotion,

markNodes(nodes)
const selectors = getSelectors(nodes)
const styles = getStylesFromSelectors(selectors)
const classNames = getClassNamesFromNodes(nodes)
const styles = getStylesFromClassNames(classNames)
const printedVal = printer(val)
return replaceClassNames(
selectors,
classNames,
styles,

@@ -122,39 +79,27 @@ printedVal,

function getStylesFromSelectors(nodeSelectors) {
const styles = getStyles(emotion)
let ast
function getStylesFromClassNames(classNames: Array<string>) {
let styles = ''
// This could be done in a more efficient way
// but it would be a breaking change to do so
// because it would change the ordering of styles
Object.keys(emotion.caches.registered).forEach(className => {
let indexOfClassName = classNames.indexOf(className)
if (indexOfClassName !== -1) {
let nameWithoutKey = classNames[indexOfClassName].substring(
emotion.caches.key.length + 1
)
// $FlowFixMe
styles += emotion.caches.inserted[nameWithoutKey]
}
})
let prettyStyles
try {
ast = css.parse(styles)
prettyStyles = css.stringify(css.parse(styles))
} catch (e) {
console.error(e)
throw new Error(
`There was an error parsing css in jest-emotion-react: "${styles}"`
`There was an error parsing css in jest-emotion: "${styles}"`
)
}
ast.stylesheet.rules = ast.stylesheet.rules.reduce(reduceRules, [])
const ret = css.stringify(ast)
return ret
function reduceRules(rules, rule) {
let shouldIncludeRule = false
if (rule.type === 'rule') {
shouldIncludeRule = rule.selectors.some(selector => {
const baseSelector = filterChildSelector(
selector.split(/:| |\./).filter(s => !!s)[0]
)
return nodeSelectors.some(
sel => sel === baseSelector || sel === `.${baseSelector}`
)
})
}
if (rule.type === 'media' || rule.type === 'supports') {
rule.rules = rule.rules.reduce(reduceRules, [])
if (rule.rules.length) {
shouldIncludeRule = true
}
}
return shouldIncludeRule ? rules.concat(rule) : rules
}
return prettyStyles
}

@@ -161,0 +106,0 @@

@@ -8,6 +8,6 @@ // @flow

const componentSelectorClassNamePattern = /\.e[a-zA-Z0-9-]+[0-9]+/
const componentSelectorClassNamePattern = /e[a-zA-Z0-9-]+[0-9]+/
export const replaceClassNames = (
selectors: Array<string>,
classNames: Array<string>,
styles: string,

@@ -19,11 +19,10 @@ code: string,

let index = 0
const classRegex = new RegExp(`^\\.${key}-([a-zA-Z0-9-]+)`)
return selectors.reduce((acc, className) => {
return classNames.reduce((acc, className) => {
if (
classRegex.test(className) ||
className.indexOf(`${key}-`) === 0 ||
componentSelectorClassNamePattern.test(className)
) {
const escapedRegex = new RegExp(
className.replace('.', '').replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'),
className.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'),
'g'

@@ -30,0 +29,0 @@ )

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc