|
@@ -1,79 +1,140 @@
|
|
|
-import {render, screen} from 'sentry-test/reactTestingLibrary';
|
|
|
+import {act, render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
|
|
|
|
|
|
import Carousel from 'sentry/components/carousel';
|
|
|
-import Placeholder from 'sentry/components/placeholder';
|
|
|
-
|
|
|
-export function setIntersectionObserver(
|
|
|
- entries: {isIntersecting: boolean; target: {id: string}}[]
|
|
|
-) {
|
|
|
- (() => {
|
|
|
- return (global.IntersectionObserver = class IntersectionObserver {
|
|
|
- [x: string]: any;
|
|
|
- constructor(cb: any) {
|
|
|
- this.cb = cb;
|
|
|
- }
|
|
|
- observe() {
|
|
|
- this.cb(entries);
|
|
|
- }
|
|
|
- unobserve() {}
|
|
|
- disconnect() {}
|
|
|
- } as any);
|
|
|
- })();
|
|
|
-}
|
|
|
|
|
|
describe('Carousel', function () {
|
|
|
- beforeEach(() => {});
|
|
|
- it('hides arrows if content does not overflow in x', function () {
|
|
|
- setIntersectionObserver([
|
|
|
- {target: {id: 'left-anchor'}, isIntersecting: true},
|
|
|
- {target: {id: 'right-anchor'}, isIntersecting: true},
|
|
|
- ]);
|
|
|
+ let intersectionOnbserverCb: (entries: Partial<IntersectionObserverEntry>[]) => void =
|
|
|
+ jest.fn();
|
|
|
+
|
|
|
+ window.IntersectionObserver = class IntersectionObserver {
|
|
|
+ root = null;
|
|
|
+ rootMargin = '';
|
|
|
+ thresholds = [];
|
|
|
+ takeRecords = jest.fn();
|
|
|
|
|
|
+ constructor(cb: IntersectionObserverCallback) {
|
|
|
+ // @ts-expect-error The callback wants just way too much stuff for our simple mock
|
|
|
+ intersectionOnbserverCb = cb;
|
|
|
+ }
|
|
|
+ observe() {}
|
|
|
+ unobserve() {}
|
|
|
+ disconnect() {}
|
|
|
+ };
|
|
|
+
|
|
|
+ it('hides arrows if content does not overflow in x', function () {
|
|
|
render(
|
|
|
- <Placeholder width="200px" height="100px">
|
|
|
- <Carousel>
|
|
|
- <Placeholder width="50px" height="50px" />
|
|
|
- </Carousel>
|
|
|
- </Placeholder>
|
|
|
+ <Carousel>
|
|
|
+ <div data-test-id="child-1" />
|
|
|
+ </Carousel>
|
|
|
);
|
|
|
|
|
|
- expect(screen.queryByLabelText('Scroll left')).not.toBeInTheDocument();
|
|
|
- expect(screen.queryByLabelText('Scroll right')).not.toBeInTheDocument();
|
|
|
- });
|
|
|
+ // Child is visible
|
|
|
+ act(() =>
|
|
|
+ intersectionOnbserverCb([
|
|
|
+ {target: screen.getByTestId('child-1'), intersectionRatio: 1},
|
|
|
+ ])
|
|
|
+ );
|
|
|
|
|
|
- it('does not show left arrow if all the way to the left', function () {
|
|
|
- setIntersectionObserver([
|
|
|
- {target: {id: 'left-anchor'}, isIntersecting: true},
|
|
|
- {target: {id: 'right-anchor'}, isIntersecting: false},
|
|
|
- ]);
|
|
|
+ expect(screen.queryByRole('button', {name: 'Scroll left'})).not.toBeInTheDocument();
|
|
|
+ expect(screen.queryByRole('button', {name: 'Scroll right'})).not.toBeInTheDocument();
|
|
|
+ });
|
|
|
|
|
|
+ it('shows right arrow when elements exist to the right', async function () {
|
|
|
render(
|
|
|
<Carousel>
|
|
|
- <Placeholder />
|
|
|
- <Placeholder />
|
|
|
- <Placeholder />
|
|
|
+ <div data-test-id="child-1" />
|
|
|
+ <div data-test-id="child-2" />
|
|
|
+ <div data-test-id="child-3" />
|
|
|
</Carousel>
|
|
|
);
|
|
|
|
|
|
- expect(screen.queryByLabelText('Scroll left')).not.toBeInTheDocument();
|
|
|
- expect(screen.queryByLabelText('Scroll right')).toBeInTheDocument();
|
|
|
- });
|
|
|
+ const elements = [
|
|
|
+ screen.getByTestId('child-1'),
|
|
|
+ screen.getByTestId('child-2'),
|
|
|
+ screen.getByTestId('child-3'),
|
|
|
+ ];
|
|
|
|
|
|
- it('does not show right arrow if all the way to the right', async function () {
|
|
|
- setIntersectionObserver([
|
|
|
- {target: {id: 'left-anchor'}, isIntersecting: false},
|
|
|
- {target: {id: 'right-anchor'}, isIntersecting: true},
|
|
|
- ]);
|
|
|
+ // Element on the right is not visible
|
|
|
+ act(() =>
|
|
|
+ intersectionOnbserverCb([
|
|
|
+ {target: elements[0], intersectionRatio: 1},
|
|
|
+ {target: elements[1], intersectionRatio: 0.5},
|
|
|
+ {target: elements[2], intersectionRatio: 0},
|
|
|
+ ])
|
|
|
+ );
|
|
|
+
|
|
|
+ const rightButton = screen.getByRole('button', {name: 'Scroll right'});
|
|
|
+ expect(screen.queryByRole('button', {name: 'Scroll left'})).not.toBeInTheDocument();
|
|
|
+
|
|
|
+ // Test scroll into view, the 2nd element should have it's 'scrollIntoView' called
|
|
|
+ elements[1].scrollIntoView = jest.fn();
|
|
|
+ await userEvent.click(rightButton);
|
|
|
+ expect(elements[1].scrollIntoView).toHaveBeenCalled();
|
|
|
+ });
|
|
|
|
|
|
+ it('shows left arrow when elements exist to the left', async function () {
|
|
|
render(
|
|
|
<Carousel>
|
|
|
- <Placeholder />
|
|
|
- <Placeholder />
|
|
|
- <Placeholder />
|
|
|
+ <div data-test-id="child-1" />
|
|
|
+ <div data-test-id="child-2" />
|
|
|
+ <div data-test-id="child-3" />
|
|
|
</Carousel>
|
|
|
);
|
|
|
|
|
|
- expect(await screen.findByLabelText('Scroll left')).toBeInTheDocument();
|
|
|
- expect(screen.queryByLabelText('Scroll right')).not.toBeInTheDocument();
|
|
|
+ const elements = [
|
|
|
+ screen.getByTestId('child-1'),
|
|
|
+ screen.getByTestId('child-2'),
|
|
|
+ screen.getByTestId('child-3'),
|
|
|
+ ];
|
|
|
+
|
|
|
+ // Element on the left is not visible
|
|
|
+ act(() =>
|
|
|
+ intersectionOnbserverCb([
|
|
|
+ {target: elements[0], intersectionRatio: 0},
|
|
|
+ {target: elements[1], intersectionRatio: 1},
|
|
|
+ {target: elements[2], intersectionRatio: 1},
|
|
|
+ ])
|
|
|
+ );
|
|
|
+
|
|
|
+ const leftButton = screen.getByRole('button', {name: 'Scroll left'});
|
|
|
+ expect(screen.queryByRole('button', {name: 'Scroll right'})).not.toBeInTheDocument();
|
|
|
+
|
|
|
+ // Test scroll into view, the 1st element should have it's 'scrollIntoView' called
|
|
|
+ elements[0].scrollIntoView = jest.fn();
|
|
|
+ await userEvent.click(leftButton);
|
|
|
+ expect(elements[0].scrollIntoView).toHaveBeenCalled();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('skips an element when it is past the visibleRatio', async function () {
|
|
|
+ render(
|
|
|
+ <Carousel visibleRatio={0.9}>
|
|
|
+ <div data-test-id="child-1" />
|
|
|
+ <div data-test-id="child-2" />
|
|
|
+ <div data-test-id="child-3" />
|
|
|
+ </Carousel>
|
|
|
+ );
|
|
|
+
|
|
|
+ const elements = [
|
|
|
+ screen.getByTestId('child-1'),
|
|
|
+ screen.getByTestId('child-2'),
|
|
|
+ screen.getByTestId('child-3'),
|
|
|
+ ];
|
|
|
+
|
|
|
+ // Second element is MOSTLY visibile, past the
|
|
|
+ act(() =>
|
|
|
+ intersectionOnbserverCb([
|
|
|
+ {target: elements[0], intersectionRatio: 1},
|
|
|
+ {target: elements[1], intersectionRatio: 0.95},
|
|
|
+ {target: elements[2], intersectionRatio: 0},
|
|
|
+ ])
|
|
|
+ );
|
|
|
+
|
|
|
+ const rightButton = screen.getByRole('button', {name: 'Scroll right'});
|
|
|
+ expect(screen.queryByRole('button', {name: 'Scroll left'})).not.toBeInTheDocument();
|
|
|
+
|
|
|
+ // Test scroll into view, the 2nd element should have it's 'scrollIntoView' called
|
|
|
+ elements[2].scrollIntoView = jest.fn();
|
|
|
+ await userEvent.click(rightButton);
|
|
|
+ expect(elements[2].scrollIntoView).toHaveBeenCalled();
|
|
|
});
|
|
|
});
|