mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-22 13:32:28 -05:00
Merge pull request #11 from fsih/fillStrokeColor
Add fill and stroke color state
This commit is contained in:
commit
1d9760a476
18 changed files with 339 additions and 59 deletions
37
src/components/fill-color-indicator.jsx
Normal file
37
src/components/fill-color-indicator.jsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||
import BufferedInputHOC from './forms/buffered-input-hoc.jsx';
|
||||
import Label from './forms/label.jsx';
|
||||
import Input from './forms/input.jsx';
|
||||
|
||||
import styles from './paint-editor.css';
|
||||
|
||||
const BufferedInput = BufferedInputHOC(Input);
|
||||
const messages = defineMessages({
|
||||
fill: {
|
||||
id: 'paint.paintEditor.fill',
|
||||
description: 'Label for the color picker for the fill color',
|
||||
defaultMessage: 'Fill'
|
||||
}
|
||||
});
|
||||
const FillColorIndicatorComponent = props => (
|
||||
<div className={styles.inputGroup}>
|
||||
<Label text={props.intl.formatMessage(messages.fill)}>
|
||||
<BufferedInput
|
||||
type="text"
|
||||
value={props.fillColor}
|
||||
onSubmit={props.onChangeFillColor}
|
||||
/>
|
||||
</Label>
|
||||
</div>
|
||||
);
|
||||
|
||||
FillColorIndicatorComponent.propTypes = {
|
||||
fillColor: PropTypes.string.isRequired,
|
||||
intl: intlShape,
|
||||
onChangeFillColor: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default injectIntl(FillColorIndicatorComponent);
|
|
@ -5,6 +5,8 @@ import BrushMode from '../containers/brush-mode.jsx';
|
|||
import EraserMode from '../containers/eraser-mode.jsx';
|
||||
import PropTypes from 'prop-types';
|
||||
import LineMode from '../containers/line-mode.jsx';
|
||||
import FillColorIndicatorComponent from '../containers/fill-color-indicator.jsx';
|
||||
import StrokeColorIndicatorComponent from '../containers/stroke-color-indicator.jsx';
|
||||
|
||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||
import BufferedInputHOC from './forms/buffered-input-hoc.jsx';
|
||||
|
@ -19,16 +21,6 @@ const messages = defineMessages({
|
|||
id: 'paint.paintEditor.costume',
|
||||
description: 'Label for the name of a sound',
|
||||
defaultMessage: 'Costume'
|
||||
},
|
||||
fill: {
|
||||
id: 'paint.paintEditor.fill',
|
||||
description: 'Label for the color picker for the fill color',
|
||||
defaultMessage: 'Fill'
|
||||
},
|
||||
outline: {
|
||||
id: 'paint.paintEditor.outline',
|
||||
description: 'Label for the color picker for the outline color',
|
||||
defaultMessage: 'Outline'
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -52,7 +44,6 @@ class PaintEditorComponent extends React.Component {
|
|||
<div className={styles.inputGroup}>
|
||||
<Label text={this.props.intl.formatMessage(messages.costume)}>
|
||||
<BufferedInput
|
||||
tabIndex="1"
|
||||
type="text"
|
||||
value="meow"
|
||||
/>
|
||||
|
@ -106,26 +97,10 @@ class PaintEditorComponent extends React.Component {
|
|||
|
||||
{/* Second Row */}
|
||||
<div className={styles.row}>
|
||||
{/* To be fill */}
|
||||
<div className={styles.inputGroup}>
|
||||
<Label text={this.props.intl.formatMessage(messages.fill)}>
|
||||
<BufferedInput
|
||||
tabIndex="1"
|
||||
type="text"
|
||||
value="meow"
|
||||
/>
|
||||
</Label>
|
||||
</div>
|
||||
{/* To be stroke */}
|
||||
<div className={styles.inputGroup}>
|
||||
<Label text={this.props.intl.formatMessage(messages.outline)}>
|
||||
<BufferedInput
|
||||
tabIndex="1"
|
||||
type="text"
|
||||
value="meow"
|
||||
/>
|
||||
</Label>
|
||||
</div>
|
||||
{/* fill */}
|
||||
<FillColorIndicatorComponent />
|
||||
{/* stroke */}
|
||||
<StrokeColorIndicatorComponent />
|
||||
|
||||
<div className={styles.inputGroup}>
|
||||
Mode tools
|
||||
|
|
37
src/components/stroke-color-indicator.jsx
Normal file
37
src/components/stroke-color-indicator.jsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||
import BufferedInputHOC from './forms/buffered-input-hoc.jsx';
|
||||
import Label from './forms/label.jsx';
|
||||
import Input from './forms/input.jsx';
|
||||
|
||||
import styles from './paint-editor.css';
|
||||
|
||||
const BufferedInput = BufferedInputHOC(Input);
|
||||
const messages = defineMessages({
|
||||
stroke: {
|
||||
id: 'paint.paintEditor.stroke',
|
||||
description: 'Label for the color picker for the outline color',
|
||||
defaultMessage: 'Outline'
|
||||
}
|
||||
});
|
||||
const StrokeColorIndicatorComponent = props => (
|
||||
<div className={styles.inputGroup}>
|
||||
<Label text={props.intl.formatMessage(messages.stroke)}>
|
||||
<BufferedInput
|
||||
type="text"
|
||||
value={props.strokeColor}
|
||||
onSubmit={props.onChangeStrokeColor}
|
||||
/>
|
||||
</Label>
|
||||
</div>
|
||||
);
|
||||
|
||||
StrokeColorIndicatorComponent.propTypes = {
|
||||
intl: intlShape,
|
||||
onChangeStrokeColor: PropTypes.func.isRequired,
|
||||
strokeColor: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default injectIntl(StrokeColorIndicatorComponent);
|
|
@ -39,6 +39,9 @@ class Blobbiness {
|
|||
* @param {!number} options.brushSize Width of blob marking made by mouse
|
||||
* @param {!boolean} options.isEraser Whether the stroke should be treated as an erase path. If false,
|
||||
* the stroke is an additive path.
|
||||
* @param {?string} options.fillColor Color of the brush stroke.
|
||||
* @param {?string} options.strokeColor Color of the brush outline.
|
||||
* @param {?number} options.strokeWidth Width of the brush outline.
|
||||
*/
|
||||
setOptions (options) {
|
||||
this.options = options;
|
||||
|
@ -51,6 +54,9 @@ class Blobbiness {
|
|||
* @param {!number} options.brushSize Width of blob marking made by mouse
|
||||
* @param {!boolean} options.isEraser Whether the stroke should be treated as an erase path. If false,
|
||||
* the stroke is an additive path.
|
||||
* @param {?string} options.fillColor Color of the brush stroke.
|
||||
* @param {?string} options.strokeColor Color of the brush outline.
|
||||
* @param {?number} options.strokeWidth Width of the brush outline.
|
||||
*/
|
||||
activateTool (options) {
|
||||
this.tool = new paper.Tool();
|
||||
|
@ -61,7 +67,7 @@ class Blobbiness {
|
|||
const blob = this;
|
||||
this.tool.onMouseMove = function (event) {
|
||||
blob.resizeCursorIfNeeded(event.point);
|
||||
styleCursorPreview(blob.cursorPreview, blob.options.isEraser);
|
||||
styleCursorPreview(blob.cursorPreview, blob.options);
|
||||
blob.cursorPreview.bringToFront();
|
||||
blob.cursorPreview.position = event.point;
|
||||
};
|
||||
|
@ -141,7 +147,10 @@ class Blobbiness {
|
|||
this.cursorPreviewLastPoint = point;
|
||||
}
|
||||
|
||||
if (this.cursorPreview && this.brushSize === this.options.brushSize) {
|
||||
if (this.cursorPreview &&
|
||||
this.brushSize === this.options.brushSize &&
|
||||
this.fillColor === this.options.fillColor &&
|
||||
this.strokeColor === this.options.strokeColor) {
|
||||
return;
|
||||
}
|
||||
const newPreview = new paper.Path.Circle({
|
||||
|
@ -149,13 +158,13 @@ class Blobbiness {
|
|||
radius: this.options.brushSize / 2
|
||||
});
|
||||
if (this.cursorPreview) {
|
||||
this.cursorPreview.segments = newPreview.segments;
|
||||
newPreview.remove();
|
||||
} else {
|
||||
this.cursorPreview = newPreview;
|
||||
styleCursorPreview(this.cursorPreview, this.options.isEraser);
|
||||
this.cursorPreview.remove();
|
||||
}
|
||||
this.brushSize = this.options.brushSize;
|
||||
this.fillColor = this.options.fillColor;
|
||||
this.strokeColor = this.options.strokeColor;
|
||||
this.cursorPreview = newPreview;
|
||||
styleCursorPreview(this.cursorPreview, this.options);
|
||||
}
|
||||
|
||||
mergeBrush (lastPath) {
|
||||
|
|
|
@ -25,7 +25,7 @@ class BroadBrushHelper {
|
|||
if (event.event.button > 0) return; // only first mouse button
|
||||
|
||||
this.finalPath = new paper.Path();
|
||||
stylePath(this.finalPath, options.isEraser);
|
||||
stylePath(this.finalPath, options);
|
||||
this.finalPath.add(event.point);
|
||||
this.lastPoint = this.secondLastPoint = event.point;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class BroadBrushHelper {
|
|||
center: event.point,
|
||||
radius: options.brushSize / 2
|
||||
});
|
||||
stylePath(this.finalPath, options.isEraser);
|
||||
stylePath(this.finalPath, options);
|
||||
} else {
|
||||
const step = (event.point.subtract(this.lastPoint)).normalize(options.brushSize / 2);
|
||||
step.angle += 90;
|
||||
|
|
|
@ -32,7 +32,7 @@ class SegmentBrushHelper {
|
|||
radius: options.brushSize / 2
|
||||
});
|
||||
this.finalPath = this.firstCircle;
|
||||
stylePath(this.finalPath, options.isEraser);
|
||||
stylePath(this.finalPath, options);
|
||||
this.lastPoint = event.point;
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,7 @@ class SegmentBrushHelper {
|
|||
|
||||
const path = new paper.Path();
|
||||
|
||||
// TODO: Add back brush styling
|
||||
// path = pg.stylebar.applyActiveToolbarStyle(path);
|
||||
path.fillColor = 'black';
|
||||
stylePath(path, options);
|
||||
|
||||
// Add handles to round the end caps
|
||||
path.add(new paper.Segment(this.lastPoint.subtract(step), handleVec.multiply(-1), handleVec));
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
const stylePath = function (path, isEraser) {
|
||||
if (isEraser) {
|
||||
const stylePath = function (path, options) {
|
||||
if (options.isEraser) {
|
||||
path.fillColor = 'white';
|
||||
} else {
|
||||
// TODO: Add back brush styling. Keep a separate active toolbar style for brush vs pen.
|
||||
// path = pg.stylebar.applyActiveToolbarStyle(path);
|
||||
path.fillColor = 'black';
|
||||
path.fillColor = options.fillColor;
|
||||
}
|
||||
};
|
||||
|
||||
const styleCursorPreview = function (path, isEraser) {
|
||||
if (isEraser) {
|
||||
const styleCursorPreview = function (path, options) {
|
||||
if (options.isEraser) {
|
||||
path.fillColor = 'white';
|
||||
path.strokeColor = 'cornflowerblue';
|
||||
path.strokeWidth = 1;
|
||||
} else {
|
||||
// TODO: Add back brush styling. Keep a separate active toolbar style for brush vs pen.
|
||||
// path = pg.stylebar.applyActiveToolbarStyle(path);
|
||||
path.fillColor = 'black';
|
||||
path.strokeColor = 'cornflowerblue';
|
||||
path.strokeWidth = 1;
|
||||
path.fillColor = options.fillColor;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,11 @@ class BrushMode extends React.Component {
|
|||
} else if (!nextProps.isBrushModeActive && this.props.isBrushModeActive) {
|
||||
this.deactivateTool();
|
||||
} else if (nextProps.isBrushModeActive && this.props.isBrushModeActive) {
|
||||
this.blob.setOptions({isEraser: false, ...nextProps.brushModeState});
|
||||
this.blob.setOptions({
|
||||
isEraser: false,
|
||||
...nextProps.colorState,
|
||||
...nextProps.brushModeState
|
||||
});
|
||||
}
|
||||
}
|
||||
shouldComponentUpdate () {
|
||||
|
@ -42,7 +46,11 @@ class BrushMode extends React.Component {
|
|||
|
||||
// TODO: This is temporary until a component that provides the brush size is hooked up
|
||||
this.props.canvas.addEventListener('mousewheel', this.onScroll);
|
||||
this.blob.activateTool({isEraser: false, ...this.props.brushModeState});
|
||||
this.blob.activateTool({
|
||||
isEraser: false,
|
||||
...this.props.colorState,
|
||||
...this.props.brushModeState
|
||||
});
|
||||
}
|
||||
deactivateTool () {
|
||||
this.props.canvas.removeEventListener('mousewheel', this.onScroll);
|
||||
|
@ -69,6 +77,10 @@ BrushMode.propTypes = {
|
|||
}),
|
||||
canvas: PropTypes.instanceOf(Element).isRequired,
|
||||
changeBrushSize: PropTypes.func.isRequired,
|
||||
colorState: PropTypes.shape({
|
||||
fillColor: PropTypes.string.isRequired,
|
||||
strokeColor: PropTypes.string.isRequired
|
||||
}).isRequired,
|
||||
handleMouseDown: PropTypes.func.isRequired,
|
||||
isBrushModeActive: PropTypes.bool.isRequired,
|
||||
onUpdateSvg: PropTypes.func.isRequired
|
||||
|
@ -76,6 +88,7 @@ BrushMode.propTypes = {
|
|||
|
||||
const mapStateToProps = state => ({
|
||||
brushModeState: state.scratchPaint.brushMode,
|
||||
colorState: state.scratchPaint.color,
|
||||
isBrushModeActive: state.scratchPaint.mode === Modes.BRUSH
|
||||
});
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
|
|
@ -29,7 +29,10 @@ class EraserMode extends React.Component {
|
|||
} else if (!nextProps.isEraserModeActive && this.props.isEraserModeActive) {
|
||||
this.deactivateTool();
|
||||
} else if (nextProps.isEraserModeActive && this.props.isEraserModeActive) {
|
||||
this.blob.setOptions({isEraser: true, ...nextProps.eraserModeState});
|
||||
this.blob.setOptions({
|
||||
isEraser: true,
|
||||
...nextProps.eraserModeState
|
||||
});
|
||||
}
|
||||
}
|
||||
shouldComponentUpdate () {
|
||||
|
|
17
src/containers/fill-color-indicator.jsx
Normal file
17
src/containers/fill-color-indicator.jsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {connect} from 'react-redux';
|
||||
import {changeFillColor} from '../reducers/fill-color';
|
||||
import FillColorIndicatorComponent from '../components/fill-color-indicator.jsx';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
fillColor: state.scratchPaint.color.fillColor
|
||||
});
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onChangeFillColor: fillColor => {
|
||||
dispatch(changeFillColor(fillColor));
|
||||
}
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(FillColorIndicatorComponent);
|
|
@ -100,9 +100,8 @@ class LineMode extends React.Component {
|
|||
if (!this.path) {
|
||||
this.path = new paper.Path();
|
||||
|
||||
// TODO add back style
|
||||
// this.path = pg.stylebar.applyActiveToolbarStyle(path);
|
||||
this.path.setStrokeColor('black');
|
||||
// TODO add back stroke width styling
|
||||
this.path.setStrokeColor(this.props.colorState.strokeColor);
|
||||
this.path.setStrokeWidth(this.props.lineModeState.lineWidth);
|
||||
|
||||
this.path.setSelected(true);
|
||||
|
@ -277,6 +276,10 @@ class LineMode extends React.Component {
|
|||
LineMode.propTypes = {
|
||||
canvas: PropTypes.instanceOf(Element).isRequired,
|
||||
changeLineWidth: PropTypes.func.isRequired,
|
||||
colorState: PropTypes.shape({
|
||||
fillColor: PropTypes.string.isRequired,
|
||||
strokeColor: PropTypes.string.isRequired
|
||||
}).isRequired,
|
||||
handleMouseDown: PropTypes.func.isRequired,
|
||||
isLineModeActive: PropTypes.bool.isRequired,
|
||||
lineModeState: PropTypes.shape({
|
||||
|
@ -286,6 +289,7 @@ LineMode.propTypes = {
|
|||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
colorState: state.scratchPaint.color,
|
||||
lineModeState: state.scratchPaint.lineMode,
|
||||
isLineModeActive: state.scratchPaint.mode === Modes.LINE
|
||||
});
|
||||
|
|
17
src/containers/stroke-color-indicator.jsx
Normal file
17
src/containers/stroke-color-indicator.jsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {connect} from 'react-redux';
|
||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||
import StrokeColorIndicatorComponent from '../components/stroke-color-indicator.jsx';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
strokeColor: state.scratchPaint.color.strokeColor
|
||||
});
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onChangeStrokeColor: strokeColor => {
|
||||
dispatch(changeStrokeColor(strokeColor));
|
||||
}
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(StrokeColorIndicatorComponent);
|
8
src/reducers/color.js
Normal file
8
src/reducers/color.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import {combineReducers} from 'redux';
|
||||
import fillColorReducer from './fill-color';
|
||||
import strokeColorReducer from './stroke-color';
|
||||
|
||||
export default combineReducers({
|
||||
fillColor: fillColorReducer,
|
||||
strokeColor: strokeColorReducer
|
||||
});
|
33
src/reducers/fill-color.js
Normal file
33
src/reducers/fill-color.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import log from '../log/log';
|
||||
|
||||
const CHANGE_FILL_COLOR = 'scratch-paint/fill-color/CHANGE_FILL_COLOR';
|
||||
const initialState = '#000';
|
||||
// Matches hex colors
|
||||
const regExp = /^#([0-9a-f]{3}){1,2}$/i;
|
||||
|
||||
const reducer = function (state, action) {
|
||||
if (typeof state === 'undefined') state = initialState;
|
||||
switch (action.type) {
|
||||
case CHANGE_FILL_COLOR:
|
||||
if (!regExp.test(action.fillColor)) {
|
||||
log.warn(`Invalid hex color code: ${action.fillColor}`);
|
||||
return state;
|
||||
}
|
||||
return action.fillColor;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Action creators ==================================
|
||||
const changeFillColor = function (fillColor) {
|
||||
return {
|
||||
type: CHANGE_FILL_COLOR,
|
||||
fillColor: fillColor
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
reducer as default,
|
||||
changeFillColor
|
||||
};
|
|
@ -3,10 +3,12 @@ import modeReducer from './modes';
|
|||
import brushModeReducer from './brush-mode';
|
||||
import eraserModeReducer from './eraser-mode';
|
||||
import lineModeReducer from './line-mode';
|
||||
import colorReducer from './color';
|
||||
|
||||
export default combineReducers({
|
||||
mode: modeReducer,
|
||||
brushMode: brushModeReducer,
|
||||
eraserMode: eraserModeReducer,
|
||||
lineMode: lineModeReducer
|
||||
lineMode: lineModeReducer,
|
||||
color: colorReducer
|
||||
});
|
||||
|
|
33
src/reducers/stroke-color.js
Normal file
33
src/reducers/stroke-color.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import log from '../log/log';
|
||||
|
||||
const CHANGE_STROKE_COLOR = 'scratch-paint/stroke-color/CHANGE_STROKE_COLOR';
|
||||
const initialState = '#000';
|
||||
// Matches hex colors
|
||||
const regExp = /^#([0-9a-f]{3}){1,2}$/i;
|
||||
|
||||
const reducer = function (state, action) {
|
||||
if (typeof state === 'undefined') state = initialState;
|
||||
switch (action.type) {
|
||||
case CHANGE_STROKE_COLOR:
|
||||
if (!regExp.test(action.strokeColor)) {
|
||||
log.warn(`Invalid hex color code: ${action.fillColor}`);
|
||||
return state;
|
||||
}
|
||||
return action.strokeColor;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Action creators ==================================
|
||||
const changeStrokeColor = function (strokeColor) {
|
||||
return {
|
||||
type: CHANGE_STROKE_COLOR,
|
||||
strokeColor: strokeColor
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
reducer as default,
|
||||
changeStrokeColor
|
||||
};
|
48
test/unit/fill-color-reducer.test.js
Normal file
48
test/unit/fill-color-reducer.test.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* eslint-env jest */
|
||||
import fillColorReducer from '../../src/reducers/fill-color';
|
||||
import {changeFillColor} from '../../src/reducers/fill-color';
|
||||
|
||||
test('initialState', () => {
|
||||
let defaultState;
|
||||
|
||||
expect(fillColorReducer(defaultState /* state */, {type: 'anything'} /* action */)).toBeDefined();
|
||||
});
|
||||
|
||||
test('changeFillColor', () => {
|
||||
let defaultState;
|
||||
|
||||
// 3 value hex code
|
||||
let newFillColor = '#fff';
|
||||
expect(fillColorReducer(defaultState /* state */, changeFillColor(newFillColor) /* action */))
|
||||
.toEqual(newFillColor);
|
||||
expect(fillColorReducer('#010' /* state */, changeFillColor(newFillColor) /* action */))
|
||||
.toEqual(newFillColor);
|
||||
|
||||
// 6 value hex code
|
||||
newFillColor = '#facade';
|
||||
expect(fillColorReducer(defaultState /* state */, changeFillColor(newFillColor) /* action */))
|
||||
.toEqual(newFillColor);
|
||||
expect(fillColorReducer('#010' /* state */, changeFillColor(newFillColor) /* action */))
|
||||
.toEqual(newFillColor);
|
||||
});
|
||||
|
||||
test('invalidChangeFillColor', () => {
|
||||
const origState = '#fff';
|
||||
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor() /* action */))
|
||||
.toBe(origState);
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor('#') /* action */))
|
||||
.toBe(origState);
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor('#1') /* action */))
|
||||
.toBe(origState);
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor('#12') /* action */))
|
||||
.toBe(origState);
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor('#1234') /* action */))
|
||||
.toBe(origState);
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor('#12345') /* action */))
|
||||
.toBe(origState);
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor('#1234567') /* action */))
|
||||
.toBe(origState);
|
||||
expect(fillColorReducer(origState /* state */, changeFillColor('invalid argument') /* action */))
|
||||
.toBe(origState);
|
||||
});
|
48
test/unit/stroke-color-reducer.test.js
Normal file
48
test/unit/stroke-color-reducer.test.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* eslint-env jest */
|
||||
import strokeColorReducer from '../../src/reducers/stroke-color';
|
||||
import {changeStrokeColor} from '../../src/reducers/stroke-color';
|
||||
|
||||
test('initialState', () => {
|
||||
let defaultState;
|
||||
|
||||
expect(strokeColorReducer(defaultState /* state */, {type: 'anything'} /* action */)).toBeDefined();
|
||||
});
|
||||
|
||||
test('changeStrokeColor', () => {
|
||||
let defaultState;
|
||||
|
||||
// 3 value hex code
|
||||
let newStrokeColor = '#fff';
|
||||
expect(strokeColorReducer(defaultState /* state */, changeStrokeColor(newStrokeColor) /* action */))
|
||||
.toEqual(newStrokeColor);
|
||||
expect(strokeColorReducer('#010' /* state */, changeStrokeColor(newStrokeColor) /* action */))
|
||||
.toEqual(newStrokeColor);
|
||||
|
||||
// 6 value hex code
|
||||
newStrokeColor = '#facade';
|
||||
expect(strokeColorReducer(defaultState /* state */, changeStrokeColor(newStrokeColor) /* action */))
|
||||
.toEqual(newStrokeColor);
|
||||
expect(strokeColorReducer('#010' /* state */, changeStrokeColor(newStrokeColor) /* action */))
|
||||
.toEqual(newStrokeColor);
|
||||
});
|
||||
|
||||
test('invalidChangeStrokeColor', () => {
|
||||
const origState = '#fff';
|
||||
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor() /* action */))
|
||||
.toBe(origState);
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor('#') /* action */))
|
||||
.toBe(origState);
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor('#1') /* action */))
|
||||
.toBe(origState);
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor('#12') /* action */))
|
||||
.toBe(origState);
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor('#1234') /* action */))
|
||||
.toBe(origState);
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor('#12345') /* action */))
|
||||
.toBe(origState);
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor('#1234567') /* action */))
|
||||
.toBe(origState);
|
||||
expect(strokeColorReducer(origState /* state */, changeStrokeColor('invalid argument') /* action */))
|
||||
.toBe(origState);
|
||||
});
|
Loading…
Reference in a new issue