Skip to content

Commit

Permalink
chore: add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alenaksu committed Dec 27, 2023
1 parent a3d01e4 commit 99eec5e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
18 changes: 11 additions & 7 deletions src/components/carousel/carousel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export default class SlCarousel extends ShoelaceElement {
}
}

handleMouseDragStart(event: MouseEvent) {
private handleMouseDragStart(event: MouseEvent) {
const canDrag = this.mouseDragging && event.button === 0;
if (canDrag) {
event.preventDefault();
Expand All @@ -229,35 +229,39 @@ export default class SlCarousel extends ShoelaceElement {
}
}

handleMouseDrag = (event: MouseEvent) => {
const hasMoved = !!event.movementX || !!event.movementY;
if (!this.dragging && hasMoved) {
private handleMouseDrag = (event: MouseEvent) => {
if (!this.dragging) {
// Start dragging if it hasn't yet
this.dragging = true;
this.scrollContainer.style.setProperty('scroll-snap-type', 'none');
} else {
this.dragging = true;
this.scrollContainer.scrollBy({
left: -event.movementX,
top: -event.movementY
});
}
};

handleMouseDragEnd = () => {
private handleMouseDragEnd = () => {
const scrollContainer = this.scrollContainer;

document.removeEventListener('mousemove', this.handleMouseDrag);

// get the current scroll position
const startLeft = scrollContainer.scrollLeft;
const startTop = scrollContainer.scrollTop;

// remove the scroll-snap-type property so that the browser will snap the slide to the correct position
scrollContainer.style.removeProperty('scroll-snap-type');

// fix(safari): forcing a style recalculation doesn't seem to immediately update the scroll
// position in Safari. Setting "overflow" to "hidden" should force this behavior.
scrollContainer.style.setProperty('overflow', 'hidden');

// get the final scroll position to the slide snapped by the browser
const finalLeft = scrollContainer.scrollLeft;
const finalTop = scrollContainer.scrollTop;

// restore the scroll position to the original one, so that it can be smoothly animated if needed
scrollContainer.style.removeProperty('overflow');
scrollContainer.style.setProperty('scroll-snap-type', 'none');
scrollContainer.scrollTo({ left: startLeft, top: startTop, behavior: 'instant' });
Expand Down
52 changes: 51 additions & 1 deletion src/components/carousel/carousel.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import '../../../dist/shoelace.js';
import { clickOnElement } from '../../internal/test.js';
import { clickOnElement, dragElement, moveMouseOnElement } from '../../internal/test.js';
import { expect, fixture, html, oneEvent } from '@open-wc/testing';
import { map } from 'lit/directives/map.js';
import { range } from 'lit/directives/range.js';
import { resetMouse, sendMouse } from '@web/test-runner-commands';

Check failure on line 6 in src/components/carousel/carousel.test.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'sendMouse' is defined but never used
import sinon from 'sinon';
import type SlCarousel from './carousel.js';

describe('<sl-carousel>', () => {
afterEach(async () => {
await resetMouse();
});

it('should render a carousel with default configuration', async () => {
// Arrange
const el = await fixture(html`
Expand Down Expand Up @@ -409,6 +414,51 @@ describe('<sl-carousel>', () => {
});
});

describe('when `mouse-dragging` attribute is provided', () => {
it.only('should be possible to drag the carousel using the mouse', async () => {
// Arrange
const el = await fixture<SlCarousel>(html`
<sl-carousel mouse-dragging>
<sl-carousel-item>Node 1</sl-carousel-item>
<sl-carousel-item>Node 2</sl-carousel-item>
<sl-carousel-item>Node 3</sl-carousel-item>
</sl-carousel>
`);
const carouselItem = el.querySelector('sl-carousel-item') as HTMLElement;

// Act
await dragElement(carouselItem, -Math.round(carouselItem.offsetWidth * 0.75));

await oneEvent(el.scrollContainer, 'scrollend');
await el.updateComplete;

// Assert
expect(el.activeSlide).to.be.equal(1);
});

it('should be possible to interact with clickable elements', async () => {
// Arrange
const el = await fixture<SlCarousel>(html`
<sl-carousel mouse-dragging>
<sl-carousel-item><button>click me</button></sl-carousel-item>
<sl-carousel-item>Node 2</sl-carousel-item>
<sl-carousel-item>Node 3</sl-carousel-item>
</sl-carousel>
`);
const button = el.querySelector('button')!;

const clickSpy = sinon.spy();
button.addEventListener('click', clickSpy);

// Act
await moveMouseOnElement(button);
await clickOnElement(button);

// Assert
expect(clickSpy).to.have.been.called;
});
});

describe('Navigation controls', () => {
describe('when the user clicks the next button', () => {
it('should scroll to the next slide', async () => {
Expand Down

0 comments on commit 99eec5e

Please sign in to comment.