|
1 | | -import { createElement, ReactNode } from "react"; |
| 1 | +import { createElement } from "react"; |
2 | 2 | import { Carousel, CarouselProps } from "../Carousel"; |
3 | 3 | import { render } from "@testing-library/react"; |
4 | 4 | import { GUID } from "mendix"; |
5 | 5 |
|
6 | | -jest.mock("swiper/react", () => ({ |
7 | | - Swiper: ({ children }: { children: ReactNode }) => <div data-testid="swiper-testid">{children}</div>, |
8 | | - SwiperSlide: ({ children }: { children: ReactNode }) => <div data-testid="swiper-slide-testid">{children}</div> |
9 | | -})); |
| 6 | +jest.mock("swiper/css", () => ({})); |
| 7 | +jest.mock("swiper/css/bundle", () => ({})); |
10 | 8 |
|
11 | 9 | jest.mock("swiper/modules", () => ({ |
12 | | - Navigation: (_props: any) => null, |
13 | | - Pagination: (_props: any) => null, |
14 | | - Scrollbar: (_props: any) => null, |
15 | | - A11y: (_props: any) => null |
| 10 | + A11y: jest.fn(), |
| 11 | + Navigation: jest.fn(), |
| 12 | + Pagination: jest.fn(), |
| 13 | + EffectFade: jest.fn(), |
| 14 | + Autoplay: jest.fn() |
16 | 15 | })); |
17 | 16 |
|
18 | | -jest.mock("swiper/css", () => jest.fn()); |
19 | | -jest.mock("swiper/css/bundle", () => jest.fn()); |
| 17 | +jest.mock("swiper/react", () => ({ |
| 18 | + Swiper: ({ |
| 19 | + children, |
| 20 | + navigation, |
| 21 | + pagination, |
| 22 | + onClick, |
| 23 | + onSwiper, |
| 24 | + onActiveIndexChange, |
| 25 | + wrapperTag = "div", |
| 26 | + ...props |
| 27 | + }: any) => { |
| 28 | + if (onSwiper) { |
| 29 | + const mockSwiper = { realIndex: 0 }; |
| 30 | + onSwiper(mockSwiper); |
| 31 | + } |
| 32 | + if (onActiveIndexChange) { |
| 33 | + const mockSwiper = { realIndex: 0 }; |
| 34 | + onActiveIndexChange(mockSwiper); |
| 35 | + } |
| 36 | + |
| 37 | + const swiperClasses = [ |
| 38 | + "swiper", |
| 39 | + props.effect === "fade" ? "swiper-fade" : "", |
| 40 | + "swiper-initialized", |
| 41 | + "swiper-horizontal", |
| 42 | + "swiper-watch-progress" |
| 43 | + ] |
| 44 | + .filter(Boolean) |
| 45 | + .join(" "); |
| 46 | + |
| 47 | + const wrapperId = "swiper-wrapper-2222222222222222"; |
| 48 | + |
| 49 | + const navigationElements = navigation |
| 50 | + ? [ |
| 51 | + createElement("div", { |
| 52 | + key: "prev", |
| 53 | + className: "swiper-button-prev", |
| 54 | + role: "button", |
| 55 | + tabIndex: 0, |
| 56 | + "aria-controls": wrapperId, |
| 57 | + "aria-label": "Previous slide" |
| 58 | + }), |
| 59 | + createElement("div", { |
| 60 | + key: "next", |
| 61 | + className: "swiper-button-next", |
| 62 | + role: "button", |
| 63 | + tabIndex: 0, |
| 64 | + "aria-controls": wrapperId, |
| 65 | + "aria-label": "Next slide" |
| 66 | + }) |
| 67 | + ] |
| 68 | + : []; |
| 69 | + |
| 70 | + const paginationElement = pagination |
| 71 | + ? createElement( |
| 72 | + "div", |
| 73 | + { |
| 74 | + key: "pagination", |
| 75 | + className: |
| 76 | + "swiper-pagination swiper-pagination-clickable swiper-pagination-bullets swiper-pagination-horizontal" |
| 77 | + }, |
| 78 | + Array.isArray(children) |
| 79 | + ? children.map((_, index) => |
| 80 | + createElement("span", { |
| 81 | + key: index, |
| 82 | + className: `swiper-pagination-bullet ${ |
| 83 | + index === 0 ? "swiper-pagination-bullet-active" : "" |
| 84 | + }`, |
| 85 | + role: "button", |
| 86 | + tabIndex: 0, |
| 87 | + "aria-label": `Go to slide ${index}`, |
| 88 | + "aria-controls": `carousel-slide-Carousel-${index + 1}`, |
| 89 | + "aria-current": index === 0 ? "true" : undefined |
| 90 | + }) |
| 91 | + ) |
| 92 | + : [] |
| 93 | + ) |
| 94 | + : null; |
| 95 | + |
| 96 | + const notificationElement = createElement("span", { |
| 97 | + key: "notification", |
| 98 | + className: "swiper-notification", |
| 99 | + "aria-live": "assertive", |
| 100 | + "aria-atomic": "true" |
| 101 | + }); |
| 102 | + |
| 103 | + const WrapperTag = wrapperTag as any; |
| 104 | + |
| 105 | + return createElement( |
| 106 | + "div", |
| 107 | + { |
| 108 | + className: swiperClasses, |
| 109 | + onClick |
| 110 | + }, |
| 111 | + [ |
| 112 | + createElement( |
| 113 | + WrapperTag, |
| 114 | + { |
| 115 | + key: "wrapper", |
| 116 | + className: "swiper-wrapper", |
| 117 | + id: wrapperId, |
| 118 | + "aria-live": "off", |
| 119 | + style: { transitionDuration: "0ms" } |
| 120 | + }, |
| 121 | + children |
| 122 | + ), |
| 123 | + ...navigationElements, |
| 124 | + paginationElement, |
| 125 | + notificationElement |
| 126 | + ].filter(Boolean) |
| 127 | + ); |
| 128 | + }, |
| 129 | + SwiperSlide: ({ children, tag = "div", id }: any) => { |
| 130 | + let slideIndex = 0; |
| 131 | + const totalSlides = 2; |
| 132 | + |
| 133 | + if (id && id.includes("carousel-slide-Carousel-")) { |
| 134 | + const slideIdPart = id.split("carousel-slide-Carousel-")[1]; |
| 135 | + slideIndex = parseInt(slideIdPart, 10) - 1; |
| 136 | + } |
| 137 | + |
| 138 | + const SlideTag = tag as any; |
| 139 | + return createElement( |
| 140 | + SlideTag, |
| 141 | + { |
| 142 | + className: "swiper-slide", |
| 143 | + id, |
| 144 | + role: "listitem", |
| 145 | + "aria-hidden": slideIndex !== 0 ? "true" : "false", |
| 146 | + "aria-label": `${slideIndex + 1} / ${totalSlides}`, |
| 147 | + "data-swiper-slide-index": slideIndex |
| 148 | + }, |
| 149 | + children |
| 150 | + ); |
| 151 | + } |
| 152 | +})); |
20 | 153 |
|
21 | 154 | describe("Carousel", () => { |
22 | 155 | beforeEach(() => { |
@@ -54,6 +187,11 @@ describe("Carousel", () => { |
54 | 187 |
|
55 | 188 | expect(asFragment()).toMatchSnapshot(); |
56 | 189 | }); |
| 190 | + it("renders correctly with minimal setup", () => { |
| 191 | + const { asFragment } = render(<Carousel {...defaultCarouselProps} pagination={false} navigation={false} />); |
| 192 | + |
| 193 | + expect(asFragment()).toMatchSnapshot(); |
| 194 | + }); |
57 | 195 | afterEach(() => { |
58 | 196 | jest.restoreAllMocks(); |
59 | 197 | }); |
|
0 commit comments