Skip to content

Commit

Permalink
feat: Add a swipe threshold as per the upstream implementation
Browse files Browse the repository at this point in the history
also re-organize the structure of the touch events test for
Carousel, and add an additional test to check for the swipe
threshold behavior.
  • Loading branch information
bpas247 committed Jul 12, 2019
1 parent 085f862 commit 3fc2ce5
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
9 changes: 9 additions & 0 deletions src/Carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { createBootstrapComponent } from './ThemeProvider';
const countChildren = c =>
React.Children.toArray(c).filter(React.isValidElement).length;

const SWIPE_THRESHOLD = 40;

// TODO: `slide` should be `animate`.

const propTypes = {
Expand Down Expand Up @@ -235,6 +237,13 @@ class Carousel extends React.Component {
handleTouchEnd = e => {
const lastPossibleIndex = countChildren(this.props.children) - 1;

// If the swipe is under the threshold, don't do anything.
if (
Math.abs(e.changedTouches[0].screenX - this.state.touchStartX) <
SWIPE_THRESHOLD
)
return;

// Going left
if (e.changedTouches[0].screenX < this.state.touchStartX) {
this.to(
Expand Down
69 changes: 49 additions & 20 deletions test/CarouselSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,34 +287,63 @@ describe('<Carousel>', () => {
clock.restore();
}
});
it('should handle touch events', () => {
const clock = sinon.useFakeTimers();

try {
const onSelectSpy = sinon.spy();
const wrapper = mount(
describe('touch events', () => {
// const clock = sinon.useFakeTimers();
let clock, wrapper, onSelectSpy;

beforeEach(() => {
onSelectSpy = sinon.spy();
wrapper = mount(
<Carousel interval={0} onSelect={onSelectSpy} touch>
{items}
</Carousel>,
);

wrapper.simulate('touchStart', { changedTouches: [{ screenX: 50 }] });
wrapper.simulate('touchEnd', { changedTouches: [{ screenX: 0 }] });

clock.tick(50);
expect(onSelectSpy).to.have.been.calledOnce;
expect(onSelectSpy.getCall(0).args[0]).to.equal(1);

clock = sinon.useFakeTimers();
});
afterEach(() => {
clock.tick(150);
});
it('should swipe left', () => {
try {
wrapper.simulate('touchStart', { changedTouches: [{ screenX: 50 }] });
wrapper.simulate('touchEnd', { changedTouches: [{ screenX: 0 }] });

clock.tick(50);
expect(onSelectSpy).to.have.been.calledOnce;
expect(onSelectSpy.getCall(0).args[0]).to.equal(1);
} finally {
clock.restore();
}
});

wrapper.simulate('touchStart', { changedTouches: [{ screenX: 0 }] });
wrapper.simulate('touchEnd', { changedTouches: [{ screenX: 50 }] });
it('should swipe right', () => {
try {
wrapper.simulate('touchStart', { changedTouches: [{ screenX: 0 }] });
wrapper.simulate('touchEnd', { changedTouches: [{ screenX: 50 }] });

clock.tick(50);
expect(onSelectSpy).to.have.been.calledOnce;
expect(onSelectSpy.getCall(0).args[0]).to.equal(1);
} finally {
clock.restore();
}
});

clock.tick(50);
expect(onSelectSpy).to.have.been.calledTwice;
expect(onSelectSpy.getCall(1).args[0]).to.equal(0);
} finally {
clock.restore();
}
it('should not swipe if swipe detected is under the swipe threshold', () => {
const SWIPE_THRESHOLD = 40;
try {
wrapper.simulate('touchStart', { changedTouches: [{ screenX: 0 }] });
wrapper.simulate('touchEnd', {
changedTouches: [{ screenX: SWIPE_THRESHOLD - 5 }],
});

clock.tick(50);
expect(onSelectSpy).to.not.have.been.called;
} finally {
clock.restore();
}
});
});
});

0 comments on commit 3fc2ce5

Please sign in to comment.