diff --git a/README.md b/README.md
index 4721800..02e006d 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ React CSS Modules implement automatic mapping of CSS modules. Every CSS class is
- [Decorator](#decorator)
- [Options](#options)
- [`allowMultiple`](#allowmultiple)
- - [`errorWhenNotFound`](#errorwhennotfound)
+ - [`handleNotFoundStyleName`](#handlenotfoundstylename)
- [SASS, SCSS, LESS and other CSS Preprocessors](#sass-scss-less-and-other-css-preprocessors)
- [Enable Sourcemaps](#enable-sourcemaps)
- [Class Composition](#class-composition)
@@ -127,7 +127,7 @@ Using `react-css-modules`:
```
-* You are warned when `styleName` refers to an undefined CSS Module ([`errorWhenNotFound`](#errorwhennotfound) option).
+* You are warned when `styleName` refers to an undefined CSS Module ([`handleNotFoundStyleName`](#handlenotfoundstylename) option).
* You can enforce use of a single CSS module per `ReactElement` ([`allowMultiple`](#allowmultiple) option).
## The Implementation
@@ -408,7 +408,7 @@ export default CSSModules(CustomList, styles);
* @typedef CSSModules~Options
* @see {@link https://github.com/gajus/react-css-modules#options}
* @property {Boolean} allowMultiple
- * @property {Boolean} errorWhenNotFound
+ * @property {String} handleNotFoundStyleName
*/
/**
@@ -492,11 +492,17 @@ When `false`, the following will cause an error:
```
-#### `errorWhenNotFound`
+#### `handleNotFoundStyleName`
-Default: `true`.
+Default: `throw`.
-Throws an error when `styleName` cannot be mapped to an existing CSS Module.
+Defines the desired action when `styleName` cannot be mapped to an existing CSS Module.
+
+Available options:
+
+* `throw` throws an error
+* `log` logs a warning using `console.warn`
+* `ignore` silently ignores the missing style name
## SASS, SCSS, LESS and other CSS Preprocessors
diff --git a/package.json b/package.json
index 3253cc6..e276aa4 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"babel-preset-stage-0": "^6.16.0",
"babel-register": "^6.18.0",
"chai": "^4.0.0-canary.1",
+ "chai-spies": "^0.7.1",
"eslint": "^3.10.0",
"eslint-config-canonical": "^5.5.0",
"husky": "^0.11.9",
diff --git a/src/generateAppendClassName.js b/src/generateAppendClassName.js
index 9479698..127aa2a 100644
--- a/src/generateAppendClassName.js
+++ b/src/generateAppendClassName.js
@@ -4,7 +4,7 @@ const CustomMap = typeof Map === 'undefined' ? SimpleMap : Map;
const stylesIndex = new CustomMap();
-export default (styles, styleNames: Array, errorWhenNotFound: boolean): string => {
+export default (styles, styleNames: Array, handleNotFoundStyleName: "throw" | "log" | "ignore"): string => {
let appendClassName;
let stylesIndexMap;
@@ -29,8 +29,14 @@ export default (styles, styleNames: Array, errorWhenNotFound: boolean):
if (className) {
appendClassName += ' ' + className;
- } else if (errorWhenNotFound === true) {
- throw new Error('"' + styleNames[styleName] + '" CSS module is undefined.');
+ } else {
+ if (handleNotFoundStyleName === 'throw') {
+ throw new Error('"' + styleNames[styleName] + '" CSS module is undefined.');
+ }
+ if (handleNotFoundStyleName === 'log') {
+ // eslint-disable-next-line no-console
+ console.warn('"' + styleNames[styleName] + '" CSS module is undefined.');
+ }
}
}
}
diff --git a/src/linkClass.js b/src/linkClass.js
index 1a05878..959d599 100644
--- a/src/linkClass.js
+++ b/src/linkClass.js
@@ -68,7 +68,7 @@ const linkElement = (element: ReactElement, styles: Object, configuration: Objec
});
if (styleNames.length) {
- appendClassName = generateAppendClassName(styles, styleNames, configuration.errorWhenNotFound);
+ appendClassName = generateAppendClassName(styles, styleNames, configuration.handleNotFoundStyleName);
if (appendClassName) {
if (elementShallowCopy.props.className) {
diff --git a/src/makeConfiguration.js b/src/makeConfiguration.js
index 0eae15f..2e3a2d6 100644
--- a/src/makeConfiguration.js
+++ b/src/makeConfiguration.js
@@ -4,7 +4,7 @@ import _ from 'lodash';
* @typedef CSSModules~Options
* @see {@link https://github.com/gajus/react-css-modules#options}
* @property {boolean} allowMultiple
- * @property {boolean} errorWhenNotFound
+ * @property {string} handleNotFoundStyleName
*/
/**
@@ -14,7 +14,7 @@ import _ from 'lodash';
export default (userConfiguration = {}) => {
const configuration = {
allowMultiple: false,
- errorWhenNotFound: true
+ handleNotFoundStyleName: 'throw'
};
_.forEach(userConfiguration, (value, name) => {
@@ -22,8 +22,12 @@ export default (userConfiguration = {}) => {
throw new Error('Unknown configuration property "' + name + '".');
}
- if (!_.isBoolean(value)) {
- throw new Error('"' + name + '" property value must be a boolean.');
+ if (name === 'allowMultiple' && !_.isBoolean(value)) {
+ throw new Error('"allowMultiple" property value must be a boolean.');
+ }
+
+ if (name === 'handleNotFoundStyleName' && !['throw', 'log', 'ignore'].includes(value)) {
+ throw new Error('"handleNotFoundStyleName" property value must be "throw", "log" or "ignore".');
}
configuration[name] = value;
diff --git a/tests/linkClass.js b/tests/linkClass.js
index 0475563..fdda06b 100644
--- a/tests/linkClass.js
+++ b/tests/linkClass.js
@@ -1,13 +1,16 @@
-/* eslint-disable max-nested-callbacks, react/prefer-stateless-function, class-methods-use-this */
+/* eslint-disable max-nested-callbacks, react/prefer-stateless-function, class-methods-use-this, no-console */
-import {
+import chai, {
expect
} from 'chai';
+import spies from 'chai-spies';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import jsdom from 'jsdom';
import linkClass from './../src/linkClass';
+chai.use(spies);
+
describe('linkClass', () => {
context('ReactElement does not define styleName', () => {
it('does not affect element properties', () => {
@@ -264,24 +267,37 @@ describe('linkClass', () => {
});
});
- describe('options.errorWhenNotFound', () => {
+ describe('options.handleNotFoundStyleName', () => {
context('when styleName does not match an existing CSS module', () => {
- context('when false', () => {
- it('ignores the missing CSS module', () => {
- let subject;
-
- subject = ;
-
- subject = linkClass(subject, {}, {errorWhenNotFound: false});
+ context('when throw', () => {
+ it('throws an error', () => {
+ expect(() => {
+ linkClass(, {}, {handleNotFoundStyleName: 'throw'});
+ }).to.throw(Error, '"foo" CSS module is undefined.');
+ });
+ });
+ context('when log', () => {
+ it('logs a warning to the console', () => {
+ const warnSpy = chai.spy(() => {});
- expect(subject.props.className).to.be.an('undefined');
+ console.warn = warnSpy;
+ linkClass(, {}, {handleNotFoundStyleName: 'log'});
+ expect(warnSpy).to.have.been.called();
});
});
- context('when is true', () => {
- it('throws an error', () => {
+ context('when ignore', () => {
+ it('does not log a warning', () => {
+ const warnSpy = chai.spy(() => {});
+
+ console.warn = warnSpy;
+ linkClass(, {}, {handleNotFoundStyleName: 'ignore'});
+ expect(warnSpy).to.not.have.been.called();
+ });
+
+ it('does not throw an error', () => {
expect(() => {
- linkClass(, {}, {errorWhenNotFound: true});
- }).to.throw(Error, '"foo" CSS module is undefined.');
+ linkClass(, {}, {handleNotFoundStyleName: 'ignore'});
+ }).to.not.throw(Error, '"foo" CSS module is undefined.');
});
});
});
diff --git a/tests/makeConfiguration.js b/tests/makeConfiguration.js
index 94129fc..4193311 100644
--- a/tests/makeConfiguration.js
+++ b/tests/makeConfiguration.js
@@ -17,9 +17,9 @@ describe('makeConfiguration', () => {
expect(configuration.allowMultiple).to.equal(false);
});
});
- describe('errorWhenNotFound property', () => {
- it('defaults to true', () => {
- expect(configuration.errorWhenNotFound).to.equal(true);
+ describe('handleNotFoundStyleName property', () => {
+ it('defaults to "throw"', () => {
+ expect(configuration.handleNotFoundStyleName).to.equal('throw');
});
});
});