slide.test.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import { CLASS_ACTIVE, CLASS_NEXT, CLASS_PREV, CLASS_VISIBLE } from '../../../constants/classes';
  2. import {
  3. EVENT_ACTIVE,
  4. EVENT_CLICK,
  5. EVENT_HIDDEN,
  6. EVENT_INACTIVE,
  7. EVENT_SLIDE_KEYDOWN,
  8. EVENT_VISIBLE,
  9. } from '../../../constants/events';
  10. import { Splide } from '../../../core/Splide/Splide';
  11. import { fire, init, keydown } from '../../../test';
  12. import { format } from '../../../utils';
  13. import { SlideComponent } from '../Slide';
  14. describe( 'Slide', () => {
  15. test( 'can assign the unique ID to the slide element.', () => {
  16. const splide = init( { speed: 0 } );
  17. const { Slides } = splide.Components;
  18. const Slide = Slides.getAt( 0 );
  19. expect( Slide.slide.id.indexOf( splide.root.id ) ).toBe( 0 );
  20. } );
  21. test( 'can toggle the `is-active` class.', () => {
  22. const splide = init( { speed: 0 } );
  23. const { Slides } = splide.Components;
  24. const Slide0 = Slides.getAt( 0 );
  25. const Slide1 = Slides.getAt( 1 );
  26. expect( Slide0.slide.classList.contains( CLASS_ACTIVE ) ).toBe( true );
  27. expect( Slide1.slide.classList.contains( CLASS_ACTIVE ) ).toBe( false );
  28. splide.go( 1 );
  29. expect( Slide0.slide.classList.contains( CLASS_ACTIVE ) ).toBe( false );
  30. expect( Slide1.slide.classList.contains( CLASS_ACTIVE ) ).toBe( true );
  31. } );
  32. test( 'can emit an event when the slide becomes active.', () => {
  33. const splide = init( { speed: 0 } );
  34. const { Slides } = splide.Components;
  35. const Slide1 = Slides.getAt( 1 );
  36. const Slide2 = Slides.getAt( 2 );
  37. const callback = jest.fn();
  38. splide.on( EVENT_ACTIVE, callback );
  39. splide.go( 1 );
  40. expect( callback ).toHaveBeenCalledWith( Slide1 );
  41. splide.go( 2 );
  42. expect( callback ).toHaveBeenCalledWith( Slide2 );
  43. } );
  44. test( 'can emit an event when the slide becomes inactive.', () => {
  45. const splide = init( { speed: 0 } );
  46. const { Slides } = splide.Components;
  47. const Slide0 = Slides.getAt( 0 );
  48. const Slide1 = Slides.getAt( 1 );
  49. const Slide2 = Slides.getAt( 2 );
  50. const callback = jest.fn();
  51. splide.on( EVENT_INACTIVE, callback );
  52. splide.on( EVENT_INACTIVE, callback );
  53. splide.go( 1 );
  54. expect( callback ).toHaveBeenCalledWith( Slide0 );
  55. splide.go( 2 );
  56. expect( callback ).toHaveBeenCalledWith( Slide1 );
  57. splide.go( 1 );
  58. expect( callback ).toHaveBeenCalledWith( Slide2 );
  59. } );
  60. test( 'can toggle the `is-visible` class and the `aria-hidden` attribute.', () => {
  61. const splide = init( { speed: 0, perPage: 2 } );
  62. const { Slides } = splide.Components;
  63. const Slide0 = Slides.getAt( 0 );
  64. const Slide1 = Slides.getAt( 1 );
  65. const Slide2 = Slides.getAt( 2 );
  66. expect( Slide0.slide.classList.contains( CLASS_VISIBLE ) ).toBe( true );
  67. expect( Slide1.slide.classList.contains( CLASS_VISIBLE ) ).toBe( true );
  68. expect( Slide2.slide.classList.contains( CLASS_VISIBLE ) ).toBe( false );
  69. expect( Slide0.slide.getAttribute( 'aria-hidden' ) ).toBeNull();
  70. expect( Slide1.slide.getAttribute( 'aria-hidden' ) ).toBeNull();
  71. expect( Slide2.slide.getAttribute( 'aria-hidden' ) ).toBe( 'true' );
  72. splide.go( 1 );
  73. expect( Slide0.slide.classList.contains( CLASS_VISIBLE ) ).toBe( false );
  74. expect( Slide1.slide.classList.contains( CLASS_VISIBLE ) ).toBe( true );
  75. expect( Slide2.slide.classList.contains( CLASS_VISIBLE ) ).toBe( true );
  76. expect( Slide0.slide.getAttribute( 'aria-hidden' ) ).toBe( 'true' );
  77. expect( Slide1.slide.getAttribute( 'aria-hidden' ) ).toBeNull();
  78. expect( Slide2.slide.getAttribute( 'aria-hidden' ) ).toBeNull();
  79. } );
  80. test( 'can emit an event when the slide becomes visible.', () => {
  81. const splide = init( { speed: 0, perPage: 2 } );
  82. const { Slides } = splide.Components;
  83. const Slide0 = Slides.getAt( 0 );
  84. const Slide1 = Slides.getAt( 1 );
  85. const Slide2 = Slides.getAt( 2 );
  86. const Slide3 = Slides.getAt( 3 );
  87. const callback = jest.fn();
  88. const visibleSlides = [] as SlideComponent[];
  89. splide.on( EVENT_VISIBLE, Slide => {
  90. callback();
  91. visibleSlides.push( Slide );
  92. } );
  93. splide.go( '>' );
  94. expect( visibleSlides ).toEqual( [ Slide2, Slide3 ] );
  95. visibleSlides.length = 0;
  96. splide.go( '<' );
  97. expect( visibleSlides ).toEqual( [ Slide0, Slide1 ] );
  98. } );
  99. test( 'can disable focus of focusable descendants when the slide is hidden.', () => {
  100. const splide = init( { speed: 0 } );
  101. const { Slides } = splide.Components;
  102. const Slide0 = Slides.getAt( 0 );
  103. const a = document.createElement( 'a' );
  104. const button = document.createElement( 'button' );
  105. Slide0.slide.appendChild( a );
  106. Slide0.slide.appendChild( button );
  107. splide.go( 1 );
  108. expect( a.tabIndex ).toBe( -1 );
  109. expect( button.tabIndex ).toBe( -1 );
  110. splide.go( 0 );
  111. expect( a.tabIndex ).toBe( 0 );
  112. expect( button.tabIndex ).toBe( 0 );
  113. } );
  114. test( 'can emit an event when the slide gets hidden.', () => {
  115. const splide = init( { speed: 0, perPage: 2 } );
  116. const { Slides } = splide.Components;
  117. const Slide0 = Slides.getAt( 0 );
  118. const Slide1 = Slides.getAt( 1 );
  119. const Slide2 = Slides.getAt( 2 );
  120. const Slide3 = Slides.getAt( 3 );
  121. const callback = jest.fn();
  122. const hiddenSlides = [] as SlideComponent[];
  123. splide.on( EVENT_HIDDEN, Slide => {
  124. callback();
  125. hiddenSlides.push( Slide );
  126. } );
  127. splide.go( '>' );
  128. expect( hiddenSlides ).toEqual( [ Slide0, Slide1 ] );
  129. hiddenSlides.length = 0;
  130. splide.go( '<' );
  131. expect( hiddenSlides ).toEqual( [ Slide2, Slide3 ] );
  132. } );
  133. test( 'can toggle the `is-prev` and `is-next` classes.', () => {
  134. const splide = init( { type: 'loop', speed: 0 } );
  135. const { Slides } = splide.Components;
  136. const Clone1 = Slides.getAt( -1 );
  137. const Slide0 = Slides.getAt( 0 );
  138. const Slide1 = Slides.getAt( 1 );
  139. const Slide2 = Slides.getAt( 2 );
  140. expect( Clone1.slide.classList.contains( CLASS_PREV ) ).toBe( true );
  141. expect( Slide0.slide.classList.contains( CLASS_PREV ) ).toBe( false );
  142. expect( Slide0.slide.classList.contains( CLASS_NEXT ) ).toBe( false );
  143. expect( Slide1.slide.classList.contains( CLASS_NEXT ) ).toBe( true );
  144. splide.go( 1 );
  145. expect( Clone1.slide.classList.contains( CLASS_PREV ) ).toBe( false );
  146. expect( Slide0.slide.classList.contains( CLASS_PREV ) ).toBe( true );
  147. expect( Slide1.slide.classList.contains( CLASS_PREV ) ).toBe( false );
  148. expect( Slide1.slide.classList.contains( CLASS_NEXT ) ).toBe( false );
  149. expect( Slide2.slide.classList.contains( CLASS_NEXT ) ).toBe( true );
  150. } );
  151. test( 'can tell if the slide is within the specified range.', () => {
  152. const splide = init( { type: 'loop', speed: 0 } );
  153. const { Slides } = splide.Components;
  154. const Slide0 = Slides.getAt( 0 );
  155. const Slide1 = Slides.getAt( 1 );
  156. const Slide2 = Slides.getAt( 2 );
  157. const Clone = Slides.getAt( -1 );
  158. expect( Slide0.isWithin( 0, 1 ) ).toBe( true );
  159. expect( Slide1.isWithin( 0, 1 ) ).toBe( true );
  160. expect( Slide2.isWithin( 0, 1 ) ).toBe( false );
  161. expect( Clone.isWithin( 0, 1 ) ).toBe( true );
  162. } );
  163. test( 'can assign the role and aria attributes.', () => {
  164. const splide = init( { speed: 0, isNavigation: true } );
  165. const { Slides } = splide.Components;
  166. const Slide0 = Slides.getAt( 0 );
  167. const Slide1 = Slides.getAt( 1 );
  168. expect( Slide0.slide.getAttribute( 'role' ) ).toBe( 'menuitem' );
  169. expect( Slide0.slide.getAttribute( 'aria-label' ) ).toBe( format( splide.options.i18n.slideX, 1 ) );
  170. expect( Slide1.slide.getAttribute( 'role' ) ).toBe( 'menuitem' );
  171. expect( Slide1.slide.getAttribute( 'aria-label' ) ).toBe( format( splide.options.i18n.slideX, 2 ) );
  172. } );
  173. test( 'can emit the `click` event on click.', done => {
  174. const splide = init( { speed: 0 } );
  175. const { Slides } = splide.Components;
  176. const { slide } = Slides.getAt( 2 );
  177. splide.on( EVENT_CLICK, Slide => {
  178. expect( Slide.slide ).toBe( slide );
  179. done();
  180. } );
  181. fire( slide, 'click' );
  182. } );
  183. test( 'can emit the `slide:keydown` event on keydown.', done => {
  184. const splide = init( { speed: 0, isNavigation: true } );
  185. const { Slides } = splide.Components;
  186. const { slide } = Slides.getAt( 2 );
  187. splide.on( EVENT_SLIDE_KEYDOWN, ( Slide, e ) => {
  188. expect( Slide.slide ).toBe( slide );
  189. expect( e.key ).toBe( 'Enter' );
  190. done();
  191. } );
  192. keydown( 'Enter', slide );
  193. } );
  194. test( 'should remove status classes and added attributes.', () => {
  195. const splide = init( { speed: 0, isNavigation: true } );
  196. const { Slides } = splide.Components;
  197. const { slide } = Slides.getAt( 0 );
  198. splide.destroy();
  199. expect( slide.classList.contains( CLASS_ACTIVE ) ).toBe( false );
  200. expect( slide.classList.contains( CLASS_VISIBLE ) ).toBe( false );
  201. expect( slide.getAttribute( 'role' ) ).toBe( null );
  202. expect( slide.getAttribute( 'aria-label' ) ).toBe( null );
  203. } );
  204. test( 'can notify the active slide of other components on initialization.', () => {
  205. const splide = init( { start: 1 }, { mount: false } );
  206. const callback = jest.fn();
  207. const component = ( Splide: Splide ) => {
  208. return {
  209. setup() {
  210. Splide.on( EVENT_ACTIVE, Slide => {
  211. expect( Slide.index ).toBe( 1 );
  212. callback();
  213. } );
  214. },
  215. };
  216. };
  217. splide.mount( { component } );
  218. expect( callback ).toHaveBeenCalled();
  219. } );
  220. } );