Skip to content

Commit

Permalink
Fix screen measurement when scrollWidth is a float
Browse files Browse the repository at this point in the history
  • Loading branch information
carbonrobot committed Apr 8, 2024
1 parent b8edcae commit 16cd0dd
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-doors-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'nuka-carousel': patch
---

Fix screen measurement when scrollWidth is a float
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dist
types
yarn-error.log*
package-lock.json
coverage

cypress/screenshots
cypress/videos
Expand Down
2 changes: 0 additions & 2 deletions packages/nuka/.gitignore

This file was deleted.

2 changes: 2 additions & 0 deletions packages/nuka/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
module.exports = {
collectCoverage: true,
collectCoverageFrom: ['./src/**'],
moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
},
Expand Down
2 changes: 1 addition & 1 deletion packages/nuka/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"preversion": "pnpm run check",
"test": "pnpm run test:unit",
"test:ci": "pnpm run test:unit:ci",
"test:unit": "jest --testPathIgnorePatterns=\\(/es /lib\\)",
"test:unit": "jest",
"test:unit:ci": "pnpm run test:unit",
"test:unit:watch": "pnpm run test:unit --watchAll",
"test:storybook": "test-storybook",
Expand Down
140 changes: 140 additions & 0 deletions packages/nuka/src/hooks/use-measurement.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { renderHook } from '@testing-library/react';

import { useMeasurement } from './use-measurement';
import * as hooks from './use-resize-observer';

const domElement = {} as any;
jest.spyOn(hooks, 'useResizeObserver').mockImplementation(() => domElement);

describe('useMeasurement', () => {
it('return the default values', () => {
const { result } = renderHook(() =>
useMeasurement({
element: { current: null },
scrollDistance: 'screen',
}),
);

const { totalPages, scrollOffset } = result.current;

expect(totalPages).toBe(0);
expect(scrollOffset).toEqual([]);
});

it('should return measurements for screen', () => {
const element = {
current: {
// this test covers a specific rounding error that can
// occur when the scrollWidth/offsetWidth returns a float
scrollWidth: 900,
offsetWidth: 500,
querySelector: () => ({
children: [
{ offsetWidth: 200 },
{ offsetWidth: 300 },
{ offsetWidth: 400 },
],
}),
},
} as any;

const { result } = renderHook(() =>
useMeasurement({
element,
scrollDistance: 'screen',
}),
);

const { totalPages, scrollOffset } = result.current;

expect(totalPages).toBe(2);
expect(scrollOffset).toEqual([0, 500]);
});

it('should return measurements for screen with fractional pixels', () => {
const element = {
current: {
// this test covers a specific rounding error that can
// occur when the scrollWidth/offsetWidth returns a float
scrollWidth: 1720,
offsetWidth: 573,
querySelector: () => ({
children: [
{ offsetWidth: 573 },
{ offsetWidth: 573 },
{ offsetWidth: 573 },
],
}),
},
} as any;

const { result } = renderHook(() =>
useMeasurement({
element,
scrollDistance: 'screen',
}),
);

const { totalPages, scrollOffset } = result.current;

expect(totalPages).toBe(3);
expect(scrollOffset).toEqual([0, 573, 1146]);
});

it('should return measurements for slide distance', () => {
const element = {
current: {
scrollWidth: 900,
offsetWidth: 500,
querySelector: () => ({
children: [
{ offsetWidth: 200 },
{ offsetWidth: 300 },
{ offsetWidth: 400 },
],
}),
},
} as any;

const { result } = renderHook(() =>
useMeasurement({
element,
scrollDistance: 'slide',
}),
);

const { totalPages, scrollOffset } = result.current;

expect(totalPages).toBe(3);
expect(scrollOffset).toEqual([0, 200, 500]);
});

it('should return measurements for numbered distance', () => {
const element = {
current: {
scrollWidth: 900,
offsetWidth: 500,
querySelector: () => ({
children: [
{ offsetWidth: 200 },
{ offsetWidth: 300 },
{ offsetWidth: 400 },
],
}),
},
} as any;

const { result } = renderHook(() =>
useMeasurement({
element,
scrollDistance: 200,
}),
);

const { totalPages, scrollOffset } = result.current;

expect(totalPages).toBe(3);
expect(scrollOffset).toEqual([0, 200, 400]);
});
});
4 changes: 2 additions & 2 deletions packages/nuka/src/hooks/use-measurement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function useMeasurement({ element, scrollDistance }: MeasurementProps) {

switch (scrollDistance) {
case 'screen': {
const pageCount = Math.ceil(scrollWidth / visibleWidth);
const pageCount = Math.round(scrollWidth / visibleWidth);

setTotalPages(pageCount);
setScrollOffset(arraySeq(pageCount, visibleWidth));
Expand Down Expand Up @@ -56,7 +56,7 @@ export function useMeasurement({ element, scrollDistance }: MeasurementProps) {
}
default: {
if (typeof scrollDistance === 'number') {
// find the number of pages required to scroll the all slides
// find the number of pages required to scroll all the slides
// to the end of the container
const pageCount = Math.ceil(remainder / scrollDistance) + 1;

Expand Down

0 comments on commit 16cd0dd

Please sign in to comment.