jest-styled-components
Advanced tools
Comparing version 6.3.1 to 6.3.2
@@ -7,2 +7,6 @@ # Changelog | ||
## [6.3.1](https://github.com/styled-components/jest-styled-components/compare/v6.3.0...v6.3.1) - 2018-11-11 | ||
### Fixed | ||
- [toHaveStyleRule] Fix `.not undefinded` edge-case introduced in [#206](https://github.com/styled-components/jest-styled-components/pull/206) (see [#210](https://github.com/styled-components/jest-styled-components/pull/210)). | ||
## [6.3.0](https://github.com/styled-components/jest-styled-components/compare/v6.2.2...v6.3.0) - 2018-11-10 | ||
@@ -9,0 +13,0 @@ ### Added |
{ | ||
"name": "jest-styled-components", | ||
"version": "6.3.1", | ||
"version": "6.3.2", | ||
"description": "Jest utilities for Styled Components", | ||
@@ -17,3 +17,2 @@ "main": "./src/index.js", | ||
"scripts": { | ||
"precommit": "lint-staged", | ||
"test": "yarn test:web && yarn test:native && yarn test:preact && yarn test:ts", | ||
@@ -27,31 +26,29 @@ "test:web": "jest", | ||
"devDependencies": { | ||
"babel-core": "^6.26.0", | ||
"babel-jest": "^23.4.2", | ||
"babel-plugin-transform-class-properties": "^6.24.1", | ||
"babel-plugin-transform-object-rest-spread": "^6.26.0", | ||
"babel-preset-es2015": "^6.24.1", | ||
"babel-preset-react": "^6.24.1", | ||
"@babel/core": "^7.0.0", | ||
"@babel/plugin-proposal-class-properties": "^7.0.0", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0", | ||
"@babel/preset-env": "^7.0.0", | ||
"@babel/preset-react": "^7.0.0", | ||
"@testing-library/react": "^8.0.1", | ||
"babel-core": "^7.0.0-bridge.0", | ||
"babel-eslint": "^10.0.1", | ||
"babel-jest": "^24.8.0", | ||
"enzyme": "^3.6.0", | ||
"enzyme-adapter-react-16": "^1.5.0", | ||
"enzyme-to-json": "^3.3.1", | ||
"eslint": "^3.17.1", | ||
"eslint-config-airbnb": "^14.1.0", | ||
"eslint-config-prettier": "^2.9.0", | ||
"eslint-plugin-import": "^2.14.0", | ||
"eslint-plugin-jsx-a11y": "^4.0.0", | ||
"eslint-plugin-prettier": "^2.1.2", | ||
"eslint-plugin-react": "^6.10.0", | ||
"husky": "^0.14.3", | ||
"jest": "^23.5.0", | ||
"lint-staged": "^7.2.2", | ||
"eslint": "^5.16.0", | ||
"eslint-config-prettier": "^4.3.0", | ||
"husky": "^2.4.0", | ||
"jest": "^24.8.0", | ||
"lint-staged": "^8.2.0", | ||
"preact": "^8.3.1", | ||
"preact-compat": "^3.18.4", | ||
"preact-render-to-json": "^3.6.6", | ||
"prettier": "^1.14.2", | ||
"react": "^16.5.0", | ||
"react-dom": "^16.5.0", | ||
"react-native": "^0.53.3", | ||
"react-test-renderer": "^16.5.0", | ||
"react-testing-library": "^5.0.1", | ||
"styled-components": "^3.4.5", | ||
"prettier": "^1.18.2", | ||
"react": "^16.8.0", | ||
"react-dom": "^16.8.0", | ||
"react-is": "^16.8.6", | ||
"react-native": "^0.59.9", | ||
"react-test-renderer": "^16.8.0", | ||
"styled-components": "^3", | ||
"typescript": "^3.0.3" | ||
@@ -63,4 +60,9 @@ }, | ||
"peerDependencies": { | ||
"styled-components": "^2.0.0 || ^3.0.2" | ||
"styled-components": ">= 2" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
}, | ||
"lint-staged": { | ||
@@ -76,3 +78,5 @@ "*.js": [ | ||
], | ||
"setupTestFrameworkScriptFile": "<rootDir>/test/setup.js", | ||
"setupFilesAfterEnv": [ | ||
"<rootDir>/test/setup.js" | ||
], | ||
"snapshotSerializers": [ | ||
@@ -79,0 +83,0 @@ "enzyme-to-json/serializer" |
@@ -1,34 +0,31 @@ | ||
const { getCSS, matcherTest, buildReturnMessage } = require('./utils') | ||
const { getCSS, matcherTest, buildReturnMessage } = require('./utils'); | ||
const shouldDive = node => | ||
typeof node.dive === 'function' && typeof node.type() !== 'string' | ||
const shouldDive = node => typeof node.dive === 'function' && typeof node.type() !== 'string'; | ||
const isTagWithClassName = node => | ||
node.exists() && node.prop('className') && typeof node.type() === 'string' | ||
const isTagWithClassName = node => node.exists() && node.prop('className') && typeof node.type() === 'string'; | ||
const getClassNames = received => { | ||
let className | ||
let className; | ||
if (received) { | ||
if (received.$$typeof === Symbol.for('react.test.json')) { | ||
className = received.props.className || received.props.class | ||
className = received.props.className || received.props.class; | ||
} else if (typeof received.exists === 'function' && received.exists()) { | ||
const tree = shouldDive(received) ? received.dive() : received | ||
const components = tree.findWhere(isTagWithClassName) | ||
const tree = shouldDive(received) ? received.dive() : received; | ||
const components = tree.findWhere(isTagWithClassName); | ||
if (components.length) { | ||
className = components.first().prop('className') | ||
className = components.first().prop('className'); | ||
} | ||
} else if (global.Element && received instanceof global.Element) { | ||
className = Array.from(received.classList).join(' ') | ||
className = Array.from(received.classList).join(' '); | ||
} | ||
} | ||
return className ? className.split(/\s/) : [] | ||
} | ||
return className ? className.split(/\s/) : []; | ||
}; | ||
const hasAtRule = options => | ||
Object.keys(options).some(option => ['media', 'supports'].includes(option)) | ||
const hasAtRule = options => Object.keys(options).some(option => ['media', 'supports'].includes(option)); | ||
const getAtRules = (ast, options) => { | ||
const mediaRegex = /(\([a-z-]+:)\s?([a-z0-9.]+\))/g | ||
const mediaRegex = /(\([a-z-]+:)\s?([a-z0-9.]+\))/g; | ||
@@ -38,46 +35,35 @@ return Object.keys(options) | ||
ast.stylesheet.rules | ||
.filter( | ||
rule => | ||
rule.type === option && | ||
rule[option] === options[option].replace(mediaRegex, '$1$2') | ||
) | ||
.filter(rule => rule.type === option && rule[option] === options[option].replace(mediaRegex, '$1$2')) | ||
.map(rule => rule.rules) | ||
.reduce((acc, rules) => acc.concat(rules), []) | ||
) | ||
.reduce((acc, rules) => acc.concat(rules), []) | ||
} | ||
.reduce((acc, rules) => acc.concat(rules), []); | ||
}; | ||
const getModifiedClassName = (className, modifier = '') => { | ||
const classNameSelector = `.${className}` | ||
let prefix = '' | ||
const classNameSelector = `.${className}`; | ||
let prefix = ''; | ||
modifier = modifier.trim() | ||
modifier = modifier.trim(); | ||
if (modifier.includes('&')) { | ||
modifier = modifier.replace(/&/g, classNameSelector) | ||
modifier = modifier.replace(/&/g, classNameSelector); | ||
} else { | ||
prefix += classNameSelector | ||
prefix += classNameSelector; | ||
} | ||
const first = modifier[0] | ||
const first = modifier[0]; | ||
if (first !== ':' && first !== '[') { | ||
prefix += ' ' | ||
prefix += ' '; | ||
} | ||
return `${prefix}${modifier}`.trim() | ||
} | ||
return `${prefix}${modifier}`.trim(); | ||
}; | ||
const hasClassNames = (classNames, selectors, options) => | ||
classNames.some(className => | ||
selectors.includes(getModifiedClassName(className, options.modifier)) | ||
) | ||
classNames.some(className => selectors.includes(getModifiedClassName(className, options.modifier))); | ||
const getRules = (ast, classNames, options) => { | ||
const rules = hasAtRule(options) | ||
? getAtRules(ast, options) | ||
: ast.stylesheet.rules | ||
const rules = hasAtRule(options) ? getAtRules(ast, options) : ast.stylesheet.rules; | ||
return rules.filter( | ||
rule => | ||
rule.type === 'rule' && hasClassNames(classNames, rule.selectors, options) | ||
) | ||
} | ||
return rules.filter(rule => rule.type === 'rule' && hasClassNames(classNames, rule.selectors, options)); | ||
}; | ||
@@ -88,18 +74,12 @@ const handleMissingRules = options => ({ | ||
`No style rules found on passed Component${ | ||
Object.keys(options).length | ||
? ` using options:\n${JSON.stringify(options)}` | ||
: '' | ||
Object.keys(options).length ? ` using options:\n${JSON.stringify(options)}` : '' | ||
}`, | ||
}) | ||
}); | ||
const getDeclaration = (rule, property) => | ||
rule.declarations | ||
.filter( | ||
declaration => | ||
declaration.type === 'declaration' && declaration.property === property | ||
) | ||
.pop() | ||
.filter(declaration => declaration.type === 'declaration' && declaration.property === property) | ||
.pop(); | ||
const getDeclarations = (rules, property) => | ||
rules.map(rule => getDeclaration(rule, property)).filter(Boolean) | ||
const getDeclarations = (rules, property) => rules.map(rule => getDeclaration(rule, property)).filter(Boolean); | ||
@@ -109,25 +89,20 @@ const normalizeOptions = options => | ||
? Object.assign({}, options, { | ||
modifier: Array.isArray(options.modifier) | ||
? options.modifier.join('') | ||
: options.modifier, | ||
modifier: Array.isArray(options.modifier) ? options.modifier.join('') : options.modifier, | ||
}) | ||
: options | ||
: options; | ||
function toHaveStyleRule(component, property, expected, options = {}) { | ||
const classNames = getClassNames(component) | ||
const ast = getCSS() | ||
const normalizedOptions = normalizeOptions(options) | ||
const rules = getRules(ast, classNames, normalizedOptions) | ||
const classNames = getClassNames(component); | ||
const ast = getCSS(); | ||
const normalizedOptions = normalizeOptions(options); | ||
const rules = getRules(ast, classNames, normalizedOptions); | ||
if (!rules.length) { | ||
return handleMissingRules(normalizedOptions) | ||
return handleMissingRules(normalizedOptions); | ||
} | ||
const declarations = getDeclarations(rules, property) | ||
const declaration = declarations.pop() || {} | ||
const received = declaration.value | ||
const pass = | ||
!received && !expected && this.isNot | ||
? false | ||
: matcherTest(received, expected) | ||
const declarations = getDeclarations(rules, property); | ||
const declaration = declarations.pop() || {}; | ||
const received = declaration.value; | ||
const pass = !received && !expected && this.isNot ? false : matcherTest(received, expected); | ||
@@ -137,5 +112,5 @@ return { | ||
message: buildReturnMessage(this.utils, pass, property, received, expected), | ||
} | ||
}; | ||
} | ||
module.exports = toHaveStyleRule | ||
module.exports = toHaveStyleRule; |
@@ -1,16 +0,15 @@ | ||
interface AsymmetricMatcher { | ||
$$typeof: Symbol; | ||
sample?: string | RegExp | object | Array<any> | Function; | ||
} | ||
declare namespace jest { | ||
interface AsymmetricMatcher { | ||
$$typeof: Symbol; | ||
sample?: string | RegExp | object | Array<any> | Function; | ||
} | ||
type Value = string | number | RegExp | AsymmetricMatcher | undefined; | ||
type Value = string | number | RegExp | AsymmetricMatcher | undefined; | ||
interface Options { | ||
media?: string; | ||
modifier?: string; | ||
supports?: string; | ||
} | ||
interface Options { | ||
media?: string; | ||
modifier?: string; | ||
supports?: string; | ||
} | ||
declare namespace jest { | ||
interface Matchers<R> { | ||
@@ -17,0 +16,0 @@ toHaveStyleRule(property: string, value?: Value, options?: Options): R; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36439
28
329