diff --git a/js/Marquee.jsx b/js/Marquee.jsx
index 92727062..2176e742 100644
--- a/js/Marquee.jsx
+++ b/js/Marquee.jsx
@@ -28,17 +28,22 @@ const getDoubleSizeModeText = (enabled) => {
return `${enabled ? 'Disable' : 'Enable'} doublesize mode`;
};
-const wrapForMarquee = (text, step) => {
- if (text.length <= 30) {
- return text;
+const isLong = (text) => text.length > 30;
+
+// Given text and step, how many pixels should it be shifted?
+const stepOffset = (text, step) => {
+ if (!isLong(text)) {
+ return 0;
}
- step = step % (text.length + 1);
- const chars = text.split('');
- const start = chars.slice(step);
- const end = chars.slice(0, step);
- return [...start, ' ', ...end].slice(0, 30).join('');
+ return (step % text.length) * 5;
};
+// Format an int as negative pixels
+const negativePixels = (pixels) => `-${pixels}px`;
+
+// If text is wider than the marquee, it needs to loop
+const loopText = (text) => isLong(text) ? text + text : text;
+
import CharacterString from './CharacterString.jsx';
class Marquee extends React.Component {
@@ -91,10 +96,13 @@ class Marquee extends React.Component {
}
render() {
- const text = wrapForMarquee(this.getText(), this.props.display.marqueeStep);
- return
- {text}
- ;
+ const text = this.getText();
+ const offset = stepOffset(text, this.props.display.marqueeStep);
+ return
+
+ {loopText(text)}
+
+
;
}
}
@@ -104,7 +112,9 @@ export {
getPositionText,
getMediaText,
getDoubleSizeModeText,
- wrapForMarquee,
+ negativePixels,
+ stepOffset,
+ loopText,
Marquee
};
export default connect(state => state)(Marquee);
diff --git a/js/__tests__/Marquee-test.jsx b/js/__tests__/Marquee-test.js
similarity index 59%
rename from js/__tests__/Marquee-test.jsx
rename to js/__tests__/Marquee-test.js
index a00139a6..c1f28f85 100644
--- a/js/__tests__/Marquee-test.jsx
+++ b/js/__tests__/Marquee-test.js
@@ -1,3 +1,4 @@
+jest.unmock('../Marquee.jsx');
jest.unmock('../utils');
import {
@@ -6,7 +7,9 @@ import {
getPositionText,
getMediaText,
getDoubleSizeModeText,
- wrapForMarquee
+ stepOffset,
+ negativePixels,
+ loopText
} from '../Marquee.jsx';
describe('getBalanceText', () => {
@@ -55,35 +58,62 @@ describe('getMediaText', () => {
});
});
-describe('wrapForMarquee', () => {
+describe('stepOffset', () => {
const long = 'This is a long string. Longer than 30 characters!';
- it('truncates to 30 characters', () => {
- const actual = wrapForMarquee(long, 0);
- const expected = 'This is a long string. Longer ';
+ it('starts at 0', () => {
+ const actual = stepOffset(long, 0);
+ const expected = 0;
expect(actual).toEqual(expected);
});
- it('offsets by the number of steps', () => {
- const actual = wrapForMarquee(long, 8);
- const expected = 'a long string. Longer than 30 ';
+ it('first step offsets by one character', () => {
+ const actual = stepOffset(long, 1);
+ const expected = 5;
expect(actual).toEqual(expected);
});
- it('wraps around when step > text length', () => {
- const actual = wrapForMarquee(long, 51);
- const expected = 'his is a long string. Longer t';
+ it('resets to 0 when step === string.length', () => {
+ const actual = stepOffset(long, long.length);
+ const expected = 0;
expect(actual).toEqual(expected);
});
- it('wraps text when it gets to the end', () => {
- const actual = wrapForMarquee(long, 30);
- const expected = 'than 30 characters! This is a ';
+ it('offsets by one char when step = string.length + 1', () => {
+ const actual = stepOffset(long, long.length + 1);
+ const expected = 5;
expect(actual).toEqual(expected);
});
- it('does not step through short strings', () => {
- const actual = wrapForMarquee('Short string', 30);
- const expected = 'Short string';
+ xit('does not try to offset strings shorter than 30 characters', () => {
+ const actual = stepOffset('hello', 15);
+ const expected = 0;
expect(actual).toEqual(expected);
});
});
+describe('negativePixels', () => {
+ it('converts an integer into a CSS offset', () => {
+ const actual = negativePixels(1);
+ const expected = '-1px';
+ expect(actual).toEqual(expected);
+ });
+ it('handles 0', () => {
+ const actual = negativePixels(0);
+ const expected = '-0px';
+ expect(actual).toEqual(expected);
+ });
+});
+
+describe('loopText', () => {
+ const long = 'This is a long string. Longer than 30 characters!';
+ const short = 'This is a short string.';
+ it('loops long string', () => {
+ const actual = loopText(long);
+ const expected = long + long;
+ expect(actual).toEqual(expected);
+ });
+ it('does not loop sort strings', () => {
+ const actual = loopText(short);
+ const expected = short;
+ expect(actual).toEqual(expected);
+ });
+});
describe('getDoubleSizeModeText', () => {
it('prompts to enable when disabled', () => {
const actual = getDoubleSizeModeText(true);
diff --git a/package.json b/package.json
index 50b391fe..7ec7aa15 100644
--- a/package.json
+++ b/package.json
@@ -56,5 +56,11 @@
"react-redux": "^4.4.5",
"redux": "^3.5.2",
"redux-thunk": "^2.1.0"
+ },
+ "jest": {
+ "unmockedModulePathPatterns": [
+ "/node_modules/react/",
+ "/node_modules/react-redux/"
+ ]
}
}