Best JavaScript code snippet using playwright-internal
CarouselNormal.spec.js
Source:CarouselNormal.spec.js
1import testComponentHelper, {2 buildComponentRender,3 mountRender,4 withStore,5} from 'test/unit/helpers/test-component'6import CarouselNormal, { EMPTY_IMAGE } from '../CarouselNormal'7import CarouselImagesOverlay from '../CarouselImagesOverlay'8import KEYS from '../../../../constants/keyboardKeys'9import ResponsiveImage from '../../ResponsiveImage/ResponsiveImage'10import { compose } from 'ramda'11describe('<CarouselNormal />', () => {12 const initProps = {13 name: 'productDetail',14 carousel: {15 productDetail: {16 direction: 'right',17 previous: -1,18 current: 0,19 max: 6,20 zoom: 1,21 panX: 0,22 panY: 0,23 initialIndex: 0,24 },25 },26 assets: [27 {28 url: 'http://topshop.com/assets/demo_image_1.jpg',29 assetType: 'IMAGE_LARGE',30 },31 {32 url: 'http://topshop.com/assets/demo_image_2.jpg',33 assetType: 'IMAGE_LARGE',34 },35 {36 url: 'http://topshop.com/assets/demo_image_3.jpg',37 assetType: 'IMAGE_LARGE',38 },39 ],40 touchEnabled: false,41 isHidden: false,42 backCarousel: jest.fn(),43 forwardCarousel: jest.fn(),44 onClick: jest.fn(),45 }46 const CarouselRef = {47 addEventListener: jest.fn(),48 removeEventListener: jest.fn(),49 current: {50 querySelector: () => {51 return {52 offsetWidth: 1000,53 offsetHeight: 1000,54 style: {},55 }56 },57 offsetTop: 20,58 getBoundingClientRect: jest.fn(() => ({59 height: 4,60 width: 1000,61 left: 0,62 top: 0,63 })),64 },65 }66 const renderComponent = testComponentHelper(CarouselNormal, {67 disableLifecycleMethods: true,68 })69 const renderMountStore = compose(70 mountRender,71 withStore({72 features: { status: '' },73 config: {74 brandName: 'topman',75 brandCode: 'tm',76 },77 })78 )79 const mountRenderComponent = buildComponentRender(80 renderMountStore,81 CarouselNormal82 )83 describe('@renders', () => {84 it('in default state', () => {85 expect(renderComponent(initProps).getTree()).toMatchSnapshot()86 })87 it('with empty assets', () => {88 expect(89 renderComponent({90 ...initProps,91 assets: [],92 }).getTree()93 ).toMatchSnapshot()94 })95 it('with mode', () => {96 expect(97 renderComponent({98 ...initProps,99 mode: 'large',100 }).getTree()101 ).toMatchSnapshot()102 })103 it('with arrowColor', () => {104 expect(105 renderComponent({106 ...initProps,107 arrowColor: 'green',108 }).getTree()109 ).toMatchSnapshot()110 })111 it('with showcase as true', () => {112 expect(113 renderComponent({114 ...initProps,115 showcase: true,116 }).getTree()117 ).toMatchSnapshot()118 })119 it('with autoplay', () => {120 expect(121 renderComponent({122 ...initProps,123 autoplay: true,124 }).getTree()125 ).toMatchSnapshot()126 })127 it('when mobile and zoomed in', () => {128 expect(129 renderComponent({130 ...initProps,131 isMobile: true,132 carousel: {133 productDetail: {134 ...initProps.carousel.productDetail,135 zoom: 2,136 },137 },138 }).getTree()139 ).toMatchSnapshot()140 })141 it('when desktop and zoomed in', () => {142 expect(143 renderComponent({144 ...initProps,145 isMobile: false,146 carousel: {147 productDetail: {148 ...initProps.carousel.productDetail,149 zoom: 2,150 },151 },152 }).getTree()153 ).toMatchSnapshot()154 })155 it('with showZoomIcon', () => {156 expect(157 renderComponent({158 ...initProps,159 showZoomIcon: true,160 }).getTree()161 ).toMatchSnapshot()162 })163 it('should set initial item', () => {164 const { wrapper } = renderComponent({165 ...initProps,166 showZoomIcon: true,167 })168 expect(wrapper.find('.Carousel-initialItem')).toHaveLength(1)169 })170 it('should not hide carousel', () => {171 const { wrapper } = renderComponent({172 ...initProps,173 isHidden: false,174 })175 expect(wrapper.find('.Carousel--invisible')).toHaveLength(0)176 })177 it('should hide carousel', () => {178 const { wrapper } = renderComponent({179 ...initProps,180 isHidden: true,181 })182 expect(wrapper.find('.Carousel--invisible')).toHaveLength(1)183 })184 it('with responsive images and sizes', () => {185 const assets = [{ url: 'image 2 ' }, { url: 'image 2' }]186 const amplienceImages = ['url 1', 'url 2']187 const sizes = { mobile: 1, tablet: 2, desktop: 3 }188 const { wrapper } = renderComponent({189 ...initProps,190 sizes,191 assets,192 amplienceImages,193 })194 const responsiveImage = wrapper.find(ResponsiveImage)195 expect(responsiveImage).toHaveLength(assets.length)196 assets.forEach((asset, index) => {197 expect(responsiveImage.at(index).prop('sizes')).toBe(sizes)198 expect(responsiveImage.at(index).prop('amplienceUrl')).toBe(199 amplienceImages[index]200 )201 })202 })203 it('should adjust the initial carousel image according to the initial index', () => {204 expect(205 renderComponent({206 ...initProps,207 carousel: {208 ...initProps.carousel,209 productDetail: {210 ...initProps.carousel.productDetail,211 initialIndex: 2,212 },213 },214 }).getTree()215 ).toMatchSnapshot()216 })217 describe('zoom styles', () => {218 const { wrapper } = renderComponent({219 ...initProps,220 carousel: {221 ...initProps.carousel,222 productDetail: {223 ...initProps.carousel.productDetail,224 current: 2,225 zoom: 2.3,226 panX: '123',227 panY: '456',228 },229 },230 isMobile: true,231 })232 it('should only apply the zoom styles to the selected image', () => {233 expect(234 wrapper235 .find(ResponsiveImage)236 .first()237 .prop('style')238 ).toBe(null)239 expect(240 wrapper241 .find(ResponsiveImage)242 .last()243 .prop('style')244 ).toEqual({245 transform: 'scale(2.3)',246 WebkitTransform: 'scale(2.3)',247 transition: 'transform 0.3s ease',248 })249 })250 it('should only apply the pan styles to the div wrapping the selected image', () => {251 expect(252 wrapper253 .find(ResponsiveImage)254 .first()255 .parent()256 .prop('style')257 ).toBe(null)258 expect(259 wrapper260 .find(ResponsiveImage)261 .last()262 .parent()263 .prop('style')264 ).toEqual({265 transform: 'translate(123px, 456px)',266 WebkitTransform: 'translate(123px, 456px)',267 })268 })269 })270 it('renders CarouselImagesOverlay', () => {271 const { wrapper } = renderComponent({272 ...initProps,273 carousel: {274 ...initProps.carousel,275 productDetail: {276 ...initProps.carousel.productDetail,277 current: 2,278 zoom: 2.3,279 panX: '123',280 panY: '456',281 },282 },283 isMobile: true,284 })285 expect(wrapper.find(CarouselImagesOverlay).exists()).toBe(true)286 })287 })288 describe('Image sizing', () => {289 beforeEach(() => {290 jest.clearAllMocks()291 })292 it('measures the first image on click and sets the content height', (done) => {293 const assets = [{ url: 'image 2 ' }, { url: 'image 2' }]294 const amplienceImages = ['url 1', 'url 2']295 const sizes = { mobile: 1, tablet: 2, desktop: 3 }296 const componentProps = {297 ...initProps,298 sizes,299 assets,300 amplienceImages,301 }302 const { wrapper, instance } = renderComponent(componentProps)303 const mockFunc = {304 preventDefault: jest.fn(),305 callback: jest.fn(),306 }307 Object.defineProperty(global.document, 'querySelector', {308 writable: true,309 value: jest.fn(() => {310 return { height: 1000, src: '' }311 }),312 })313 const setStateSpy = jest.spyOn(instance, 'setState')314 wrapper.find('.Carousel-arrow--left').simulate('click', mockFunc)315 wrapper.update()316 setTimeout(() => {317 expect(setStateSpy).toHaveBeenCalledWith(318 { height: 1000 },319 expect.any(Function)320 )321 done()322 }, 0)323 })324 it('does not update measurements if image has not been changed', async () => {325 const assets = [{ url: 'image 2 ' }, { url: 'image 2' }]326 const amplienceImages = ['url 1', 'url 2']327 const sizes = { mobile: 1, tablet: 2, desktop: 3 }328 const { instance } = renderComponent({329 ...initProps,330 sizes,331 assets,332 amplienceImages,333 })334 const setStateSpy = jest.spyOn(instance, 'setState')335 expect(setStateSpy).toHaveBeenCalledTimes(0)336 })337 it('does not set height to zero', (done) => {338 const assets = [{ url: 'image 2 ' }, { url: 'image 2' }]339 const amplienceImages = ['url 1', 'url 2']340 const sizes = { mobile: 1, tablet: 2, desktop: 3 }341 const componentProps = {342 ...initProps,343 sizes,344 assets,345 amplienceImages,346 }347 const { wrapper, instance } = renderComponent(componentProps)348 const mockFunc = {349 preventDefault: jest.fn(),350 callback: jest.fn(),351 }352 const setStateSpy = jest.spyOn(instance, 'setState')353 Object.defineProperty(global.document, 'querySelector', {354 writable: true,355 value: jest.fn(() => {356 return { height: 0, src: '' }357 }),358 })359 wrapper.find('.Carousel-arrow--left').simulate('click', mockFunc)360 wrapper.update()361 setTimeout(() => {362 expect(setStateSpy).not.toHaveBeenCalled()363 done()364 }, 0)365 })366 it('does not update measurements if it is empty image', async () => {367 const assets = [{ url: EMPTY_IMAGE }, { url: EMPTY_IMAGE }]368 const amplienceImages = ['url 1', 'url 2']369 const sizes = { mobile: 1, tablet: 2, desktop: 3 }370 const { instance } = renderComponent({371 ...initProps,372 sizes,373 assets,374 amplienceImages,375 })376 const setStateSpy = jest.spyOn(instance, 'setState')377 expect(setStateSpy).not.toHaveBeenCalled()378 })379 it('updates the measurements if they become larger', (done) => {380 const assets = [{ url: 'image 2 ' }, { url: 'image 2' }]381 const amplienceImages = ['url 1', 'url 2']382 const sizes = { mobile: 1, tablet: 2, desktop: 3 }383 const componentProps = {384 ...initProps,385 sizes,386 assets,387 amplienceImages,388 }389 const { wrapper, instance } = renderComponent(componentProps)390 const mockFunc = {391 preventDefault: jest.fn(),392 callback: jest.fn(),393 }394 const setStateSpy = jest.spyOn(instance, 'setState')395 Object.defineProperty(global.document, 'querySelector', {396 writable: true,397 value: jest.fn(() => {398 return { height: 700, src: '' }399 }),400 })401 wrapper.find('.Carousel-arrow--left').simulate('click', mockFunc)402 wrapper.update()403 setTimeout(() => {404 expect(setStateSpy).toHaveBeenCalledWith(405 { height: 700 },406 expect.any(Function)407 )408 done()409 }, 0)410 })411 })412 describe('@lifecycle', () => {413 describe('on componentDidMount', () => {414 let renderedComponent415 beforeEach(() => {416 renderedComponent = renderComponent({417 ...initProps,418 handleSwipe: jest.fn(),419 carouselZoom: jest.fn(),420 isMobile: true,421 })422 jest.resetAllMocks()423 jest.useFakeTimers()424 })425 it('to call setInterval', () => {426 const { instance } = renderedComponent427 expect(setInterval).not.toHaveBeenCalled()428 instance.componentDidMount()429 expect(setInterval).toHaveBeenCalledWith(instance.autoplay, 4000)430 expect(setInterval).toHaveBeenCalledTimes(1)431 })432 it('to not call handleSwipe when autoplay is false', () => {433 const { instance } = renderedComponent434 instance.componentDidMount()435 jest.runTimersToTime(4000)436 expect(instance.props.handleSwipe).not.toHaveBeenCalled()437 })438 it('to call handleSwipe when autoplay is true and has more than 1 asset', () => {439 const { instance } = renderComponent({440 ...initProps,441 handleSwipe: jest.fn(),442 carouselZoom: jest.fn(),443 autoplay: true,444 isMobile: true,445 })446 expect(instance.props.handleSwipe).not.toHaveBeenCalled()447 instance.componentDidMount()448 jest.runTimersToTime(4000)449 expect(instance.props.handleSwipe).toHaveBeenCalledTimes(1)450 expect(instance.props.handleSwipe).toHaveBeenCalledWith({451 direction: 2,452 })453 })454 it('to not call handleSwipe when it has only 1 asset', () => {455 const { instance } = renderComponent({456 ...initProps,457 handleSwipe: jest.fn(),458 carouselZoom: jest.fn(),459 autoplay: true,460 isMobile: true,461 assets: [462 {463 url: 'http://topshop.com/assets/demo_image_1.jpg',464 },465 ],466 })467 instance.componentDidMount()468 jest.runTimersToTime(4000)469 expect(instance.props.handleSwipe).not.toHaveBeenCalled()470 })471 it('to call addEventListener on CarouselImage', () => {472 const { wrapper, instance } = mountRenderComponent({473 ...initProps,474 handleSwipe: jest.fn(),475 carouselZoom: jest.fn(),476 autoplay: true,477 isMobile: false,478 touchEnabled: false,479 assets: [480 {481 url: 'http://topshop.com/assets/demo_image_1.jpg',482 },483 ],484 })485 wrapper.find('.Carousel-images').getElement().ref.current = CarouselRef486 expect(487 instance.CarouselImageListRef.current.addEventListener488 ).not.toHaveBeenCalled()489 instance.componentDidMount()490 expect(491 instance.CarouselImageListRef.current.addEventListener492 ).toHaveBeenCalled()493 })494 it('to not call addEventListener on CarouselImage for mobile', () => {495 const { wrapper, instance } = mountRenderComponent({496 ...initProps,497 handleSwipe: jest.fn(),498 carouselZoom: jest.fn(),499 autoplay: true,500 isMobile: true,501 touchEnabled: true,502 assets: [503 {504 url: 'http://topshop.com/assets/demo_image_1.jpg',505 },506 ],507 })508 wrapper.find('.Carousel-images').getElement().ref.current = CarouselRef509 instance.componentDidMount()510 expect(511 instance.CarouselImageListRef.current.addEventListener512 ).not.toHaveBeenCalled()513 })514 })515 describe('on UNSAFE_componentWillReceiveProps', () => {516 beforeEach(() => {517 jest.resetAllMocks()518 })519 it('changing screen from mobile to desktop should call addEventListener on CarouselImage', () => {520 const { wrapper, instance } = mountRenderComponent({521 ...initProps,522 isMobile: true,523 })524 wrapper.find('.Carousel-images').getElement().ref.current = CarouselRef525 expect(526 instance.CarouselImageListRef.current.addEventListener527 ).not.toHaveBeenCalled()528 wrapper.setProps({ isMobile: false })529 expect(530 instance.CarouselImageListRef.current.addEventListener531 ).toHaveBeenCalledTimes(2)532 expect(533 instance.CarouselImageListRef.current.removeEventListener534 ).not.toHaveBeenCalled()535 })536 it('changing screen from desktop to mobile should call removeEventListener on CarouselImage', () => {537 const { wrapper, instance } = mountRenderComponent({538 ...initProps,539 isMobile: false,540 })541 wrapper.find('.Carousel-images').getElement().ref.current = CarouselRef542 expect(543 instance.CarouselImageListRef.current.removeEventListener544 ).not.toHaveBeenCalled()545 wrapper.setProps({ isMobile: true })546 expect(547 instance.CarouselImageListRef.current.removeEventListener548 ).toHaveBeenCalledTimes(2)549 expect(550 instance.CarouselImageListRef.current.addEventListener551 ).not.toHaveBeenCalled()552 })553 it('should enable animation when selected image is not equal to initial selected image', () => {554 const { wrapper } = mountRenderComponent({555 ...initProps,556 })557 expect(wrapper.find('.Carousel-initialItem')).toHaveLength(1)558 wrapper.setProps({559 carousel: { productDetail: { current: 1, direction: 'right' } },560 })561 expect(wrapper.state().shouldAnimate).toBe(true)562 expect(wrapper.find('.Carousel-initialItem')).toHaveLength(0)563 expect(wrapper.find('.Carousel-rightItem')).toHaveLength(3)564 })565 })566 describe('on componentWillUnmount', () => {567 let renderedComponent568 beforeEach(() => {569 renderedComponent = mountRenderComponent({570 ...initProps,571 carouselZoom: jest.fn(),572 carouselPan: jest.fn(),573 })574 renderedComponent.wrapper575 .find('.Carousel-images')576 .getElement().ref.current = CarouselRef577 jest.resetAllMocks()578 })579 it('should call carouselZoom', () => {580 const { wrapper, instance } = renderedComponent581 wrapper.unmount()582 expect(instance.props.carouselZoom).toHaveBeenCalledTimes(1)583 expect(instance.props.carouselZoom).toHaveBeenCalledWith(584 instance.props.name,585 1586 )587 })588 it('should call carouselPan', () => {589 const { wrapper, instance } = renderedComponent590 wrapper.unmount()591 expect(instance.props.carouselPan).toHaveBeenCalledTimes(1)592 expect(instance.props.carouselPan).toHaveBeenCalledWith(593 instance.props.name,594 0,595 0596 )597 })598 it('should call clearInterval', () => {599 const { wrapper } = renderedComponent600 expect(clearInterval).not.toHaveBeenCalled()601 wrapper.unmount()602 expect(clearInterval).toHaveBeenCalledTimes(1)603 })604 it('should call removeEventListener on CarouselImages is desktop', () => {605 const { instance } = renderedComponent606 instance.componentDidMount()607 expect(608 instance.CarouselImageListRef.current.removeEventListener609 ).not.toHaveBeenCalled()610 instance.componentWillUnmount()611 expect(612 instance.CarouselImageListRef.current.removeEventListener613 ).toHaveBeenCalledTimes(2)614 })615 it('should not call removeEventListener on CarouselImages if mobile', () => {616 const { wrapper, instance } = renderComponent({617 ...initProps,618 carouselZoom: jest.fn(),619 carouselPan: jest.fn(),620 isMobile: true,621 })622 wrapper.find('.Carousel-images').getElement().ref.current = CarouselRef623 instance.componentWillUnmount()624 expect(625 instance.CarouselImageListRef.current.removeEventListener626 ).not.toHaveBeenCalled()627 })628 })629 })630 describe('@events', () => {631 describe('Hammer double tap', () => {632 it('if desktop should not call carouselZoom', () => {633 const { wrapper, instance } = renderComponent({634 ...initProps,635 showcase: true,636 carouselZoom: jest.fn(),637 })638 instance.CarouselRef = CarouselRef639 wrapper.find('Hammer').simulate('tap')640 expect(instance.props.carouselZoom).not.toHaveBeenCalled()641 })642 it('if mobile and is zoomed out should call carouselZoom with zoom level 2.5', () => {643 const { wrapper, instance } = renderComponent({644 ...initProps,645 showcase: true,646 isMobile: true,647 carouselZoom: jest.fn(),648 carouselPan: jest.fn(),649 })650 instance.CarouselRef = CarouselRef651 expect(instance.props.carouselZoom).not.toHaveBeenCalled()652 wrapper.find('Hammer').simulate('tap')653 expect(instance.props.carouselZoom).toHaveBeenCalledWith(654 instance.props.name,655 2.5656 )657 expect(instance.props.carouselZoom).toHaveBeenCalledTimes(1)658 expect(instance.props.carouselPan).not.toHaveBeenCalled()659 })660 it('if mobile and is zoomed in should call carouselZoom with zoom level 1 and should also call carouselPan', () => {661 const { wrapper, instance } = renderComponent({662 ...initProps,663 showcase: true,664 isMobile: true,665 carouselZoom: jest.fn(),666 carouselPan: jest.fn(),667 carousel: {668 productDetail: {669 ...initProps.carousel.productDetail,670 zoom: 2,671 },672 },673 })674 instance.CarouselRef = CarouselRef675 expect(instance.props.carouselZoom).not.toHaveBeenCalled()676 expect(instance.props.carouselPan).not.toHaveBeenCalled()677 wrapper.find('Hammer').simulate('tap')678 expect(instance.props.carouselZoom).toHaveBeenCalledWith(679 instance.props.name,680 1681 )682 expect(instance.props.carouselZoom).toHaveBeenCalledTimes(1)683 expect(instance.props.carouselPan).toHaveBeenCalledWith(684 instance.props.name,685 0,686 0687 )688 expect(instance.props.carouselPan).toHaveBeenCalledTimes(1)689 })690 })691 describe('Hammer pan', () => {692 const panEventObject = {693 deltaX: 50,694 deltaY: 70,695 isFinal: true,696 }697 let renderedComponent698 beforeEach(() => {699 renderedComponent = renderComponent({700 ...initProps,701 showcase: true,702 isMobile: true,703 carouselPan: jest.fn(),704 carousel: {705 productDetail: {706 ...initProps.carousel.productDetail,707 zoom: 2,708 },709 },710 })711 renderedComponent.instance.originX = 0712 renderedComponent.instance.originY = 0713 renderedComponent.instance.diffX = 150714 renderedComponent.instance.diffY = 150715 })716 it('if mobile and zoomed in then call carouselPan', () => {717 const { wrapper, instance } = renderedComponent718 wrapper.find('Hammer').simulate('pan', panEventObject)719 expect(instance.props.carouselPan).toHaveBeenCalledWith(720 'productDetail',721 50,722 70723 )724 expect(instance.props.carouselPan.mock.calls).toMatchSnapshot()725 expect(instance.originX).toMatchSnapshot()726 expect(instance.originY).toMatchSnapshot()727 })728 it('if mobile and zoomed in then call carouselPan with is final as false', () => {729 const { wrapper, instance } = renderedComponent730 wrapper731 .find('Hammer')732 .simulate('pan', { ...panEventObject, isFinal: false })733 expect(instance.props.carouselPan.mock.calls).toMatchSnapshot()734 expect(instance.originX).toMatchSnapshot()735 expect(instance.originY).toMatchSnapshot()736 })737 it('if mobile and zoomed out then does not call carouselPan', () => {738 const { wrapper, instance } = renderComponent({739 ...initProps,740 showcase: true,741 isMobile: true,742 carouselPan: jest.fn(),743 })744 wrapper.find('Hammer').simulate('pan', panEventObject)745 expect(instance.props.carouselPan).not.toHaveBeenCalled()746 })747 })748 describe('Hammer swipe', () => {749 it('should call handleSwipe', () => {750 const { wrapper, instance } = renderComponent({751 ...initProps,752 showcase: true,753 handleSwipe: jest.fn(),754 })755 expect(instance.props.handleSwipe).not.toHaveBeenCalled()756 wrapper.find('Hammer').simulate('swipe')757 expect(instance.props.handleSwipe).toHaveBeenCalledTimes(1)758 })759 })760 describe('baseControls click', () => {761 let renderedComponent762 const mockFunc = {763 preventDefault: jest.fn(),764 callback: jest.fn(),765 }766 const componentProps = {767 ...initProps,768 forwardCarousel: jest.fn(),769 backCarousel: jest.fn(),770 }771 beforeEach(() => {772 jest.resetAllMocks()773 })774 it('should call handleBackAndForwardClickEvent on left arrow click', () => {775 renderedComponent = renderComponent(componentProps)776 const { wrapper, instance } = renderedComponent777 const setsSpy = jest.spyOn(instance, 'handleBackAndForwardClickEvent')778 wrapper.find('.Carousel-arrow--left').simulate('click', mockFunc)779 wrapper.update()780 expect(setsSpy).toHaveBeenCalledTimes(1)781 expect(setsSpy).toHaveBeenCalledWith(mockFunc, expect.any(Function))782 })783 it('should call handleBackAndForwardClickEvent on right arrow click', () => {784 renderedComponent = renderComponent(componentProps)785 const { wrapper, instance } = renderedComponent786 const setsSpy = jest.spyOn(instance, 'handleBackAndForwardClickEvent')787 wrapper.find('.Carousel-arrow--right').simulate('click', mockFunc)788 wrapper.update()789 expect(setsSpy).toHaveBeenCalledTimes(1)790 expect(setsSpy).toHaveBeenCalledWith(mockFunc, expect.any(Function))791 })792 })793 describe('selector click', () => {794 it('should call setCarouselIndex', () => {795 const { wrapper, instance } = renderComponent({796 ...initProps,797 showcase: true,798 setCarouselIndex: jest.fn(),799 })800 expect(instance.props.setCarouselIndex).not.toHaveBeenCalled()801 wrapper802 .find('.Carousel-selector')803 .at(1)804 .simulate('click')805 expect(instance.props.setCarouselIndex).toHaveBeenCalledTimes(1)806 expect(instance.props.setCarouselIndex).toHaveBeenCalledWith(807 instance.props.name,808 1809 )810 })811 })812 describe('zoomicon click', () => {813 it('should call onClick when zoomicon is clicked', () => {814 const { wrapper, instance } = renderComponent({815 ...initProps,816 enableImageOverlay: true,817 onClick: jest.fn(),818 })819 expect(instance.props.onClick).not.toHaveBeenCalled()820 wrapper.find('.Carousel-zoom').simulate('click')821 expect(instance.props.onClick).toHaveBeenCalledTimes(1)822 })823 })824 describe('CarouselItem click', () => {825 it('should call onClick() with the correct index', () => {826 const { wrapper, instance } = renderComponent({827 ...initProps,828 onClick: jest.fn(),829 })830 expect(instance.props.onClick).not.toHaveBeenCalled()831 wrapper832 .find('.Carousel-item')833 .at(1)834 .simulate('click')835 expect(instance.props.onClick).toHaveBeenCalledTimes(1)836 expect(instance.props.onClick).toHaveBeenCalledWith(1)837 })838 })839 describe('carousel keydown', () => {840 const keyEvent = {841 stopPropagation: jest.fn(),842 preventDefault: jest.fn(),843 }844 beforeEach(() => {845 jest.resetAllMocks()846 })847 it('should be able to pan when zoomed in', () => {848 const { wrapper, instance } = renderComponent({849 ...initProps,850 forwardCarousel: jest.fn(),851 carouselPan: jest.fn(),852 carouselZoom: jest.fn(),853 isMobile: true,854 carousel: {855 productDetail: {856 ...initProps.carousel.productDetail,857 zoom: 2,858 },859 },860 })861 instance.CarouselRef = CarouselRef862 instance.originX = 0863 instance.originY = 0864 instance.diffX = 150865 instance.diffY = 150866 expect(instance.props.forwardCarousel).not.toHaveBeenCalled()867 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.ENTER })868 expect(instance.props.carouselPan).not.toHaveBeenCalled()869 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.A })870 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.D })871 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.W })872 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.S })873 expect(instance.props.carouselZoom).not.toHaveBeenCalled()874 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.Z })875 expect(instance.props.forwardCarousel.mock.calls).toMatchSnapshot()876 expect(instance.props.carouselZoom.mock.calls).toMatchSnapshot()877 expect(instance.props.carouselPan.mock.calls).toMatchSnapshot()878 expect(keyEvent.preventDefault.mock.calls).toMatchSnapshot()879 expect(keyEvent.stopPropagation.mock.calls).toMatchSnapshot()880 })881 it('should be able to pan when not zoomed in', () => {882 const { wrapper, instance } = renderComponent({883 ...initProps,884 forwardCarousel: jest.fn(),885 backCarousel: jest.fn(),886 carouselPan: jest.fn(),887 carouselZoom: jest.fn(),888 isMobile: true,889 })890 instance.CarouselRef = CarouselRef891 expect(instance.props.forwardCarousel).not.toHaveBeenCalled()892 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.ENTER })893 expect(instance.props.forwardCarousel).toHaveBeenCalledTimes(1)894 expect(instance.props.forwardCarousel).toHaveBeenCalledWith(895 instance.props.name896 )897 expect(instance.props.backCarousel).not.toHaveBeenCalled()898 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.A })899 expect(instance.props.backCarousel).toHaveBeenLastCalledWith(900 instance.props.name901 )902 expect(instance.props.backCarousel).toHaveBeenCalledTimes(1)903 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.D })904 expect(instance.props.forwardCarousel).toHaveBeenCalledTimes(2)905 expect(instance.props.forwardCarousel).toHaveBeenLastCalledWith(906 instance.props.name907 )908 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.W })909 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.S })910 wrapper.simulate('keydown', { ...keyEvent, keyCode: KEYS.Z })911 expect(instance.props.carouselZoom).toHaveBeenCalledTimes(1)912 expect(instance.props.carouselZoom).toHaveBeenLastCalledWith(913 instance.props.name,914 2.5915 )916 expect(instance.props.carouselPan).not.toHaveBeenCalled()917 expect(keyEvent.preventDefault.mock.calls).toMatchSnapshot()918 expect(keyEvent.stopPropagation.mock.calls).toMatchSnapshot()919 })920 })921 })...
index.js
Source:index.js
1'use strict';2// Load modules3const Lab = require('lab');4const Code = require('code');5const Mocks = require('./mock-components');6const StrangeForms = require('../src');7// Test shortcuts8const lab = exports.lab = Lab.script();9const describe = lab.describe;10const it = lab.it;11const expect = Code.expect;12const internals = {};13describe('strange-forms', () => {14 const StrangeSansLifecycle = StrangeForms(Mocks.ComponentSansLifecycle);15 const StrangeLifecycle = StrangeForms(Mocks.ComponentWithLifecycle);16 describe('strangeForm()', () => {17 it('initializes state to match fields in props.', (done) => {18 const props = {19 name: 'MVX',20 age: 1321 };22 const Component = class extends StrangeSansLifecycle {23 constructor(initProps) {24 super(initProps);25 this.strangeForm({ get: null, fields: ['name', 'age'] });26 }27 };28 const component = new Component(props);29 expect(component.state).to.equal({30 _sf_name: 'MVX',31 _sf_age: '13'32 });33 done();34 });35 it('does not update state from prop when prop hasn\'t changed.', (done) => {36 const props = {37 name: 'MVX',38 age: 1339 };40 const Component = class extends StrangeSansLifecycle {41 constructor(initProps) {42 super(initProps);43 this.strangeForm({44 get: null,45 act: () => false,46 fields: ['name', 'age']47 });48 }49 };50 const component = new Component(props);51 expect(component.state).to.equal({52 _sf_name: 'MVX',53 _sf_age: '13'54 });55 component.proposeNew('name')({ target: { value: 'JRD' } });56 expect(component.state).to.equal({57 _sf_name: 'JRD',58 _sf_age: '13'59 });60 component.componentWillReceiveProps(props);61 component.props = props;62 // Local state has not been overwritten63 expect(component.state).to.equal({64 _sf_name: 'JRD',65 _sf_age: '13'66 });67 expect(component.setStates).to.equal([68 { _sf_name: 'JRD' },69 {}70 ]);71 done();72 });73 it('accepts string for field getter.', (done) => {74 const props = {75 person: {76 name: 'MVX',77 age: 13,78 bogus: true79 }80 };81 const Component = class extends StrangeSansLifecycle {82 constructor(initProps) {83 super(initProps);84 this.strangeForm({85 get: 'person',86 fields: ['name', 'age']87 });88 }89 };90 const component = new Component(props);91 expect(component.state).to.equal({92 _sf_name: 'MVX',93 _sf_age: '13'94 });95 done();96 });97 it('accepts object for per-field getter.', (done) => {98 const props = {99 person: {100 longName: 'MVX'101 },102 throughNull: null,103 color: 'blue'104 };105 const Component = class extends StrangeSansLifecycle {106 constructor(initProps) {107 super(initProps);108 this.strangeForm({109 get: {110 name: 'person.longName',111 color: 'color',112 empty: 'very.empty',113 null: 'throughNull.empty'114 },115 fields: ['name', 'color', 'empty', 'null']116 });117 }118 };119 const component = new Component(props);120 expect(component.state).to.equal({121 _sf_name: 'MVX',122 _sf_color: 'blue'123 });124 done();125 });126 it('accepts object for per-field getter with default (string).', (done) => {127 const props = {128 person: {129 name: 'MVX',130 age: 13131 },132 color: 'blue'133 };134 const Component = class extends StrangeSansLifecycle {135 constructor(initProps) {136 super(initProps);137 this.strangeForm({138 get: {139 color: 'color',140 '*': 'person'141 },142 fields: ['name', 'age', 'color']143 });144 }145 };146 const component = new Component(props);147 expect(component.state).to.equal({148 _sf_name: 'MVX',149 _sf_age: '13',150 _sf_color: 'blue'151 });152 done();153 });154 it('accepts object for per-field getter with default (func).', (done) => {155 const props = {156 person: {157 name: 'MVX',158 age: 13159 },160 color: 'blue'161 };162 const Component = class extends StrangeSansLifecycle {163 constructor(initProps) {164 super(initProps);165 this.strangeForm({166 get: {167 color: (currentProps) => currentProps.color,168 '*': (currentProps, field) => currentProps.person[field]169 },170 fields: ['name', 'age', 'color']171 });172 }173 };174 const component = new Component(props);175 expect(component.state).to.equal({176 _sf_name: 'MVX',177 _sf_age: 13, // No auto-casting when using function178 _sf_color: 'blue'179 });180 done();181 });182 it('accepts function for per-field getter.', (done) => {183 const props = {184 person: {185 name: 'MVX',186 age: 13187 }188 };189 const Component = class extends StrangeSansLifecycle {190 constructor(initProps) {191 super(initProps);192 this.strangeForm({193 get: (currentProps, field) => currentProps.person[field],194 fields: ['name', 'age']195 });196 }197 };198 const component = new Component(props);199 expect(component.state).to.equal({200 _sf_name: 'MVX',201 _sf_age: 13 // No auto-casting when using function202 });203 done();204 });205 it('defaults fields to empty array.', (done) => {206 const props = {207 name: 'MVX',208 age: 13209 };210 const Component = class extends StrangeSansLifecycle {211 constructor(initProps) {212 super(initProps);213 this.strangeForm({ get: null });214 }215 };216 const component = new Component(props);217 expect(component.state).to.equal({});218 done();219 });220 it('throws when props are empty.', (done) => {221 const props = {222 name: 'MVX',223 age: 13224 };225 const Component = class extends StrangeSansLifecycle {226 constructor() {227 super();228 this.strangeForm({ get: null });229 }230 };231 expect(() => new Component(props)).to.throw('You gotta pass props in constructor with super(props) when using strange-forms.');232 done();233 });234 it('maintains pre-existing state.', (done) => {235 const props = {236 name: 'MVX',237 age: 13238 };239 const Component = class extends StrangeSansLifecycle {240 constructor(initProps) {241 super(initProps);242 this.state = { original: 'state' };243 this.strangeForm({ get: null, fields: ['name', 'age'] });244 }245 };246 const component = new Component(props);247 expect(component.state).to.equal({248 original: 'state',249 _sf_name: 'MVX',250 _sf_age: '13'251 });252 done();253 });254 });255 describe('fieldValue()', () => {256 it('gets field value stored in component state.', (done) => {257 const props = {258 name: 'MVX',259 age: 13260 };261 const Component = class extends StrangeSansLifecycle {262 constructor(initProps) {263 super(initProps);264 this.strangeForm({ get: null, fields: ['name', 'age'] });265 }266 };267 const component = new Component(props);268 expect(component.fieldValue('name')).to.equal('MVX');269 expect(component.fieldValue('age')).to.equal('13');270 done();271 });272 it('throws when specifying a non-existent field.', (done) => {273 const props = {274 name: 'MVX',275 age: 13276 };277 const Component = class extends StrangeSansLifecycle {278 constructor(initProps) {279 super(initProps);280 this.strangeForm({ get: null, fields: ['name', 'age'] });281 }282 };283 const component = new Component(props);284 expect(() => component.fieldValue('badField')).to.throw('Field "badField" does not exist in this form.');285 done();286 });287 });288 describe('proposeNew()', () => {289 it('creates a function that will call act with field, form value, and any additional arguments (using defaults).', (done) => {290 const props = {291 name: 'MVX',292 age: 13293 };294 const Component = class extends StrangeSansLifecycle {295 constructor(initProps) {296 super(initProps);297 this.strangeForm({298 get: null,299 act: this.act.bind(this),300 fields: ['name', 'age']301 });302 }303 act(...args) {304 this.actedWith = args;305 }306 };307 const component = new Component(props);308 const proposer = component.proposeNew('name');309 const event = { target: { value: 'JRD' } };310 proposer(event, 'extras');311 // Updates local state312 expect(component.setStates).to.equal([313 { _sf_name: 'JRD' }314 ]);315 expect(component.state).to.equal({ _sf_name: 'JRD', _sf_age: '13' });316 // Acts317 expect(component.actedWith).to.equal([318 'name',319 'JRD',320 event,321 'extras'322 ]);323 done();324 });325 it('throws when specifying a non-existent field.', (done) => {326 const props = {327 name: 'MVX',328 age: 13329 };330 const Component = class extends StrangeSansLifecycle {331 constructor(initProps) {332 super(initProps);333 this.strangeForm({334 get: null,335 act: this.act.bind(this),336 fields: ['name', 'age']337 });338 }339 act(...args) {340 this.actedWith = args;341 }342 };343 const component = new Component(props);344 expect(() => component.proposeNew('badField')).to.throw('Field "badField" does not exist in this form.');345 done();346 });347 it('creates a proposer that calls act on a per-field basis, including a default act.', (done) => {348 const props = {349 name: 'MVX',350 age: 13351 };352 const Component = class extends StrangeSansLifecycle {353 constructor(initProps) {354 super(initProps);355 this.actedWith = {};356 this.strangeForm({357 get: null,358 act: {359 name: this.nameAct.bind(this),360 '*': this.defaultAct.bind(this)361 },362 fields: ['name', 'age']363 });364 }365 nameAct(...args) {366 this.actedWith.name = args;367 }368 defaultAct(...args) {369 this.actedWith.defaulted = args;370 }371 };372 const component = new Component(props);373 const nameProposer = component.proposeNew('name');374 const nameEvent = { target: { value: 'JRD' } };375 nameProposer(nameEvent);376 const ageProposer = component.proposeNew('age');377 const ageEvent = { target: { value: '45' } };378 ageProposer(ageEvent);379 // Updates local state380 expect(component.setStates).to.equal([381 { _sf_name: 'JRD' },382 { _sf_age: '45' }383 ]);384 expect(component.state).to.equal({ _sf_name: 'JRD', _sf_age: '45' });385 // Acts386 expect(component.actedWith).to.equal({387 name: ['name', 'JRD', nameEvent],388 defaulted: ['age', '45', ageEvent]389 });390 done();391 });392 it('uses getFormValue option.', (done) => {393 const props = {394 name: 'MVX',395 age: 13396 };397 const Component = class extends StrangeSansLifecycle {398 constructor(initProps) {399 super(initProps);400 this.strangeForm({401 get: null,402 act: this.act.bind(this),403 getFormValue: this.getFormValue.bind(this),404 fields: ['name', 'age']405 });406 }407 act(...args) {408 this.actedWith = args;409 }410 getFormValue(...args) {411 this.gotFormValue = args;412 return `${args[0].target.value} & MVX`;413 }414 };415 const component = new Component(props);416 const proposer = component.proposeNew('name');417 const event = { target: { value: 'JRD' } };418 proposer(event, 'extras');419 expect(component.gotFormValue).to.equal([event, 'extras']);420 expect(component.state).to.equal({ _sf_name: 'JRD & MVX', _sf_age: '13' });421 expect(component.actedWith).to.equal(['name', 'JRD & MVX', event, 'extras']);422 done();423 });424 it('uses getFormValue option when specified as per-field object.', (done) => {425 const props = {426 name: 'MVX',427 age: 13428 };429 const Component = class extends StrangeSansLifecycle {430 constructor(initProps) {431 super(initProps);432 this.strangeForm({433 get: null,434 act: this.act.bind(this),435 getFormValue: {436 name: this.getFormValueName.bind(this),437 '*': this.getFormValueDefault.bind(this)438 },439 fields: ['name', 'age']440 });441 }442 act(...args) {443 this.actedWith = args;444 }445 getFormValueName(...args) {446 this.gotFormValueName = args;447 return `${args[0].target.value} & MVX`;448 }449 getFormValueDefault(...args) {450 this.gotFormValueDefault = args;451 return String(args[0].target.value);452 }453 };454 const component = new Component(props);455 const nameProposer = component.proposeNew('name');456 const nameEvent = { target: { value: 'JRD' } };457 nameProposer(nameEvent, 'extras');458 expect(component.actedWith).to.equal(['name', 'JRD & MVX', nameEvent, 'extras']);459 const ageProposer = component.proposeNew('age');460 const ageEvent = { target: { value: 45 } };461 ageProposer(ageEvent, 'extras');462 expect(component.actedWith).to.equal(['age', '45', ageEvent, 'extras']);463 expect(component.gotFormValueDefault).to.equal([ageEvent, 'extras']);464 expect(component.state).to.equal({ _sf_name: 'JRD & MVX', _sf_age: '45' });465 done();466 });467 it('uses getFormValue option when passed as argument.', (done) => {468 const props = {469 name: 'MVX',470 age: 13471 };472 const Component = class extends StrangeSansLifecycle {473 constructor(initProps) {474 super(initProps);475 this.strangeForm({476 get: null,477 act: this.act.bind(this),478 getFormValue: () => false, // Shouldn't be used479 fields: ['name', 'age']480 });481 }482 act(...args) {483 this.actedWith = args;484 }485 };486 const component = new Component(props);487 let gotFormValue;488 const proposer = component.proposeNew('name', (...args) => {489 gotFormValue = args;490 return `${args[0].target.value} & MVX`;491 });492 const event = { target: { value: 'JRD' } };493 proposer(event, 'extras');494 expect(gotFormValue).to.equal([event, 'extras']);495 expect(component.state).to.equal({ _sf_name: 'JRD & MVX', _sf_age: '13' });496 expect(component.actedWith).to.equal(['name', 'JRD & MVX', event, 'extras']);497 done();498 });499 it('caches function when not using getFormValue argument.', (done) => {500 const props = {501 name: 'MVX',502 age: 13503 };504 const Component = class extends StrangeSansLifecycle {505 constructor(initProps) {506 super(initProps);507 this.strangeForm({508 get: null,509 act: () => false,510 getFormValue: () => false,511 fields: ['name', 'age']512 });513 }514 };515 const component = new Component(props);516 const proposeOne = component.proposeNew('name');517 const proposeTwo = component.proposeNew('name');518 expect(proposeOne).to.be.a.function();519 expect(proposeTwo).to.be.a.function();520 expect(proposeOne).to.shallow.equal(proposeTwo);521 done();522 });523 it('does not cache function when using getFormValue argument.', (done) => {524 const props = {525 name: 'MVX',526 age: 13527 };528 const Component = class extends StrangeSansLifecycle {529 constructor(initProps) {530 super(initProps);531 this.strangeForm({532 get: null,533 act: () => false,534 getFormValue: () => false,535 fields: ['name', 'age']536 });537 }538 };539 const component = new Component(props);540 const getFormValue = () => false;541 const proposeOne = component.proposeNew('name', getFormValue);542 const proposeTwo = component.proposeNew('name', getFormValue);543 expect(proposeOne).to.be.a.function();544 expect(proposeTwo).to.be.a.function();545 expect(proposeOne).to.not.shallow.equal(proposeTwo);546 done();547 });548 });549 describe('fieldError()', () => {550 it('returns error when state and props don\'t match.', (done) => {551 const props = {552 name: 'MVX',553 age: 13554 };555 const Component = class extends StrangeSansLifecycle {556 constructor(initProps) {557 super(initProps);558 this.strangeForm({559 get: null,560 act: () => false, // No-op561 fields: ['name', 'age']562 });563 }564 };565 const component = new Component(props);566 component.proposeNew('name')({ target: { value: 'JRD' } });567 expect(component.fieldError('name')).to.equal(true); // Default568 expect(component.fieldError('name', 'error!')).to.equal('error!');569 done();570 });571 it('throws when specifying a non-existent field.', (done) => {572 const props = {573 name: 'MVX',574 age: 13575 };576 const Component = class extends StrangeSansLifecycle {577 constructor(initProps) {578 super(initProps);579 this.strangeForm({580 get: null,581 act: () => false, // No-op582 fields: ['name', 'age']583 });584 }585 };586 const component = new Component(props);587 expect(() => component.fieldError('badField')).to.throw('Field "badField" does not exist in this form.');588 done();589 });590 it('returns evaluated error function when state and props don\'t match.', (done) => {591 const props = {592 name: 'MVX',593 age: 13594 };595 const Component = class extends StrangeSansLifecycle {596 constructor(initProps) {597 super(initProps);598 this.strangeForm({599 get: null,600 act: () => false, // No-op601 fields: ['name', 'age']602 });603 }604 };605 const component = new Component(props);606 component.proposeNew('name')({ target: { value: 'JRD' } });607 expect(component.fieldError('name', (...args) => args)).to.equal(['JRD', 'MVX']);608 done();609 });610 it('returns null when state and props do match.', (done) => {611 const props = {612 name: 'MVX',613 age: 13614 };615 const Component = class extends StrangeSansLifecycle {616 constructor(initProps) {617 super(initProps);618 this.strangeForm({ get: null, fields: ['name', 'age'] });619 }620 };621 const component = new Component(props);622 expect(component.fieldError('name', true)).to.equal(null);623 expect(component.fieldError('age', true)).to.equal(null);624 done();625 });626 });627 describe('componentWillReceiveProps()', () => {628 it('syncs state with field values in props.', (done) => {629 const Component = class extends StrangeSansLifecycle {630 constructor(initProps) {631 super(initProps);632 this.strangeForm({ get: null, fields: ['name', 'age'] });633 }634 };635 const component = new Component({});636 expect(component.state).to.equal({});637 const nextProps = [638 {639 name: 'MVX',640 age: 13641 },642 {643 name: 'JRD',644 age: 13645 }646 ];647 component.componentWillReceiveProps(nextProps[0]);648 component.props = nextProps[0];649 expect(component.state).to.equal({650 _sf_name: 'MVX',651 _sf_age: '13'652 });653 component.componentWillReceiveProps(nextProps[1]);654 component.props = nextProps[1];655 expect(component.state).to.equal({656 _sf_name: 'JRD',657 _sf_age: '13'658 });659 expect(component.setStates).to.equal([660 {661 _sf_name: 'MVX',662 _sf_age: '13'663 },664 {665 _sf_name: 'JRD'666 }667 ]);668 done();669 });670 it('calls super\'s method if it exists.', (done) => {671 const Component = class extends StrangeLifecycle {672 constructor(initProps) {673 super(initProps);674 this.strangeForm({ get: null, fields: ['name', 'age'] });675 }676 };677 const component = new Component({});678 const nextProps = {679 name: 'MVX',680 age: 13681 };682 component.componentWillReceiveProps(nextProps);683 expect(component.calledWillReceiveProps).to.shallow.equal(nextProps);684 done();685 });686 });...
HeaderContainer.spec.js
Source:HeaderContainer.spec.js
1import { shallow } from 'enzyme'2import React from 'react'3import testComponentHelper from 'test/unit/helpers/test-component'4import HeaderContainer from '../HeaderContainer'5import HeaderBig from '../HeaderBig'6import configureStore from 'redux-mock-store'7import { isMinViewPort } from '../../../../selectors/viewportSelectors'8import { shouldDisplayMobileHeaderIfSticky } from '../../../../selectors/pageHeaderSelectors'9import { WindowScroll } from '../../WindowEventProvider/WindowScroll'10jest.mock('../../../../selectors/viewportSelectors', () => ({11 isMinViewPort: jest.fn().mockReturnValue(() => false),12 isMobile: jest.fn().mockReturnValue(() => false),13}))14jest.mock('../../../../selectors/pageHeaderSelectors', () => ({15 shouldDisplayMobileHeaderIfSticky: jest.fn().mockReturnValue(false),16}))17const brandName = 'topshop'18const setSticky = jest.fn()19beforeEach(() => jest.clearAllMocks())20describe('<HeaderContainer />', () => {21 const initProps = {22 location: {23 pathname: '/product/',24 },25 isMinViewPort,26 isMobile: true,27 brandName: 'topshop',28 forceMobileHeaderIfSticky: false,29 sticky: false,30 setSticky,31 isStickyMobile: false,32 }33 const isResponsive = {34 featureResponsive: true,35 featureBigHeader: true,36 }37 describe('Connected component', () => {38 it('should receive the correct props', () => {39 const featureBigHeader = true40 const featureResponsive = true41 const initialState = {42 viewport: {43 media: 'mobile',44 },45 features: {46 status: {47 FEATURE_HEADER_BIG: featureBigHeader,48 FEATURE_RESPONSIVE: featureResponsive,49 },50 },51 pageHeader: {52 sticky: true,53 },54 config: {55 brandName,56 },57 }58 expect(shouldDisplayMobileHeaderIfSticky).toHaveBeenCalledTimes(0)59 const container = shallow(60 <HeaderContainer location={{}} store={configureStore()(initialState)} />61 )62 expect(shouldDisplayMobileHeaderIfSticky).toHaveBeenCalledTimes(1)63 expect(container).toBeTruthy()64 expect(container.prop('isMobile')).toBeTruthy()65 expect(container.prop('sticky')).toBe(true)66 expect(container.prop('brandName')).toBe(brandName)67 expect(container.prop('featureBigHeader')).toBe(featureBigHeader)68 expect(container.prop('featureResponsive')).toBe(featureResponsive)69 expect(container.prop('forceMobileHeaderIfSticky')).toBe(false)70 expect(container.prop('isMinViewPort')).toEqual(expect.any(Function))71 })72 })73 const renderComponent = testComponentHelper(HeaderContainer.WrappedComponent)74 describe('@renders', () => {75 describe('@mobile', () => {76 beforeEach(() => jest.clearAllMocks())77 it('in default state', () => {78 expect(renderComponent(initProps).getTree()).toMatchSnapshot()79 })80 it('does not render HeaderBig', () => {81 const { wrapper } = renderComponent(initProps)82 expect(wrapper.find(HeaderBig)).toHaveLength(0)83 })84 it('does not forceDisplay header by default', () => {85 const { wrapper } = renderComponent(initProps)86 expect(wrapper.find('Header').prop('forceDisplay')).toBe(false)87 })88 it('does not forceDisplay if sticky=true', () => {89 const { wrapper } = renderComponent({ ...initProps, sticky: true })90 expect(wrapper.find('Header').prop('forceDisplay')).toBe(false)91 })92 it('does not forceDisplay if forceMobileHeaderIfSticky=true', () => {93 const { wrapper } = renderComponent({94 ...initProps,95 forceMobileHeaderIfSticky: true,96 })97 expect(wrapper.find('Header').prop('forceDisplay')).toBe(false)98 })99 it('sets forceDisplay if forceMobileHeaderIfSticky=true', () => {100 const { wrapper } = renderComponent({101 ...initProps,102 sticky: true,103 forceMobileHeaderIfSticky: true,104 })105 expect(wrapper.find('Header').prop('forceDisplay')).toBe(true)106 })107 it('in login page', () => {108 expect(109 renderComponent({110 ...initProps,111 location: {112 pathname: '/login/',113 },114 }).getTree()115 ).toMatchSnapshot()116 })117 it('in summary page', () => {118 expect(119 renderComponent({120 ...initProps,121 location: {122 pathname: '/summary/',123 },124 }).getTree()125 ).toMatchSnapshot()126 })127 it('in checkout page', () => {128 expect(129 renderComponent({130 ...initProps,131 location: {132 pathname: '/checkout/',133 },134 }).getTree()135 ).toMatchSnapshot()136 })137 it('in checkout page and featureResponsive is enabled', () => {138 expect(139 renderComponent({140 ...initProps,141 ...isResponsive,142 location: {143 pathname: '/checkout/',144 },145 }).getTree()146 ).toMatchSnapshot()147 })148 it('in product page and featureResponsive is enabled', () => {149 expect(150 renderComponent({151 ...initProps,152 ...isResponsive,153 }).getTree()154 ).toMatchSnapshot()155 })156 })157 describe('@desktop', () => {158 it('in default state', () => {159 expect(160 renderComponent({ ...initProps, isMobile: false }).getTree()161 ).toMatchSnapshot()162 })163 it('does not render HeaderBig by default', () => {164 const { wrapper } = renderComponent({165 ...initProps,166 isMobile: false,167 })168 expect(wrapper.find(HeaderBig)).toHaveLength(0)169 })170 it('renders HeaderBig when responsive', () => {171 const { wrapper } = renderComponent({172 ...initProps,173 ...isResponsive,174 isMobile: false,175 })176 expect(wrapper.find(HeaderBig)).toHaveLength(1)177 })178 it('renders HeaderBig when sticky', () => {179 const { wrapper } = renderComponent({180 ...initProps,181 ...isResponsive,182 sticky: true,183 isMobile: false,184 })185 expect(wrapper.find(HeaderBig)).toHaveLength(1)186 })187 it('renders HeaderBig when forceMobileHeaderIfSticky=true', () => {188 const { wrapper } = renderComponent({189 ...initProps,190 ...isResponsive,191 forceMobileHeaderIfSticky: true,192 isMobile: false,193 })194 expect(wrapper.find(HeaderBig)).toHaveLength(1)195 })196 it('does not render HeaderBig when forceMobileHeaderIfSticky=true and sticky=true', () => {197 const { wrapper } = renderComponent({198 ...initProps,199 ...isResponsive,200 forceMobileHeaderIfSticky: true,201 sticky: true,202 isMobile: false,203 })204 expect(wrapper.find(HeaderBig)).toHaveLength(0)205 })206 it('in checkout page', () => {207 expect(208 renderComponent({209 ...initProps,210 location: {211 pathname: '/checkout/',212 },213 isMobile: false,214 }).getTree()215 ).toMatchSnapshot()216 })217 it('in product page and featureResponsive is enabled', () => {218 expect(219 renderComponent({220 ...initProps,221 ...isResponsive,222 isMobile: false,223 }).getTree()224 ).toMatchSnapshot()225 })226 it('in checkout page and featureResponsive is enabled', () => {227 expect(228 renderComponent({229 ...initProps,230 ...isResponsive,231 location: {232 pathname: '/checkout/',233 },234 isMobile: false,235 }).getTree()236 ).toMatchSnapshot()237 })238 it('wraps with WindowScroll when isMobile=false', () => {239 const { wrapper } = renderComponent({240 ...initProps,241 ...isResponsive,242 isFeatureStickyHeaderEnabled: true,243 isMobile: false,244 })245 expect(wrapper.find(WindowScroll)).toHaveLength(1)246 })247 it('does not wrap with WindowScroll when isMobile=true', () => {248 const { wrapper } = renderComponent({249 ...initProps,250 ...isResponsive,251 isFeatureStickyHeaderEnabled: true,252 isMobile: true,253 })254 expect(wrapper.find(WindowScroll).exists()).toEqual(false)255 })256 })257 })258 describe('@lifecycle', () => {259 describe('UNSAFE_componentWillReceiveProps', () => {260 it('calls setSticky(false) if sticky and new location is checkout', () => {261 const { instance, wrapper } = renderComponent({262 ...initProps,263 isInCheckout: false,264 sticky: true,265 })266 wrapper.update()267 instance.UNSAFE_componentWillReceiveProps({268 ...initProps,269 isInCheckout: true,270 })271 wrapper.update()272 expect(setSticky).toHaveBeenCalledTimes(1)273 expect(setSticky).toHaveBeenLastCalledWith(false)274 })275 it('calls setSticky(false) if new layout is mobile and current layout is not', () => {276 const { instance, wrapper } = renderComponent({277 ...initProps,278 isMobile: false,279 })280 wrapper.update()281 instance.UNSAFE_componentWillReceiveProps({282 ...initProps,283 isMobile: true,284 })285 wrapper.update()286 expect(setSticky).toHaveBeenCalledTimes(1)287 expect(setSticky).toHaveBeenLastCalledWith(false)288 })289 it('does not call setSticky if not sticky and new location is checkout and new layout is not mobile', () => {290 const { instance, wrapper } = renderComponent({291 ...initProps,292 isInCheckout: false,293 sticky: false,294 isMobile: true,295 })296 wrapper.update()297 instance.UNSAFE_componentWillReceiveProps({298 ...initProps,299 isInCheckout: true,300 isMobile: false,301 })302 wrapper.update()303 expect(setSticky).not.toHaveBeenCalled()304 })305 })306 })307 describe('@events', () => {308 beforeEach(() => {309 setSticky.mockReset()310 isMinViewPort.mockReset()311 })312 it('calls setSticky action on first scroll movement around y position', () => {313 const { wrapper } = renderComponent({314 ...initProps,315 isFeatureStickyHeaderEnabled: true,316 })317 const scrollPoint = 38318 wrapper.instance().ref = { current: { offsetTop: 0 } }319 expect(setSticky).toHaveBeenCalledTimes(0)320 wrapper.instance().onUpdateScrollPosition(scrollPoint)321 expect(setSticky).toHaveBeenCalledTimes(0)322 wrapper.instance().onUpdateScrollPosition(scrollPoint + 1)323 expect(setSticky).toHaveBeenLastCalledWith(true)324 wrapper.setProps({ sticky: true })325 setSticky.mockReset()326 wrapper.instance().onUpdateScrollPosition(scrollPoint + 2)327 expect(setSticky).toHaveBeenCalledTimes(0)328 wrapper.instance().onUpdateScrollPosition(scrollPoint + 1)329 expect(setSticky).toHaveBeenCalledTimes(0)330 wrapper.instance().onUpdateScrollPosition(scrollPoint)331 expect(setSticky).toHaveBeenLastCalledWith(false)332 wrapper.setProps({ sticky: false })333 setSticky.mockReset()334 wrapper.instance().onUpdateScrollPosition(scrollPoint - 1)335 expect(setSticky).toHaveBeenCalledTimes(0)336 })337 it('does not call setSticky action if isInCheckout is true', () => {338 const { wrapper } = renderComponent({339 ...initProps,340 isFeatureStickyHeaderEnabled: true,341 isInCheckout: true,342 })343 const scrollPoint = 38344 wrapper.instance().ref = { current: { offsetTop: 0 } }345 wrapper.instance().onUpdateScrollPosition(scrollPoint + 50)346 expect(setSticky).toHaveBeenCalledTimes(0)347 })348 it('does not call setSticky action if ref is not defined', () => {349 const { wrapper } = renderComponent({350 ...initProps,351 isFeatureStickyHeaderEnabled: true,352 })353 const scrollPoint = 38354 wrapper.instance().ref = null355 wrapper.instance().onUpdateScrollPosition(scrollPoint + 50)356 expect(setSticky).toHaveBeenCalledTimes(0)357 })358 it('dorothy perkins invokes sticky at breakpoint for >= laptop viewport', () => {359 const { wrapper } = renderComponent({360 ...initProps,361 isFeatureStickyHeaderEnabled: true,362 brandName: 'dorothyperkins',363 })364 isMinViewPort.mockImplementation(() => true)365 const scrollPoint = 87366 wrapper.instance().ref = { current: { offsetTop: 0 } }367 expect(setSticky).toHaveBeenCalledTimes(0)368 wrapper.instance().onUpdateScrollPosition(scrollPoint)369 expect(setSticky).toHaveBeenCalledTimes(0)370 wrapper.instance().onUpdateScrollPosition(scrollPoint + 1)371 expect(setSticky).toHaveBeenLastCalledWith(true)372 expect(isMinViewPort).toHaveBeenCalledTimes(2)373 })374 it('dorothy perkins invokes sticky at breakpoint for < laptop viewport', () => {375 const { wrapper } = renderComponent({376 ...initProps,377 isFeatureStickyHeaderEnabled: true,378 brandName: 'dorothyperkins',379 })380 isMinViewPort.mockImplementation(() => false)381 const scrollPoint = 42382 wrapper.instance().ref = { current: { offsetTop: 0 } }383 expect(setSticky).toHaveBeenCalledTimes(0)384 wrapper.instance().onUpdateScrollPosition(scrollPoint)385 expect(setSticky).toHaveBeenCalledTimes(0)386 wrapper.instance().onUpdateScrollPosition(scrollPoint + 1)387 expect(setSticky).toHaveBeenLastCalledWith(true)388 expect(isMinViewPort).toHaveBeenCalledTimes(2)389 })390 })391 describe('onScroll', () => {392 it('should call onUpdateScrollPosition on window scroll', () => {393 const mockEvent = { event: 'mockEvent' }394 const mockWindow = {395 scrollY: 10,396 pageYOffset: 10,397 }398 const { instance } = renderComponent(initProps)399 const onUpdateScrollPositionMock = jest.spyOn(400 instance,401 'onUpdateScrollPosition'402 )403 expect(onUpdateScrollPositionMock).toHaveBeenCalledTimes(0)404 instance.onScroll(mockEvent, mockWindow)405 expect(onUpdateScrollPositionMock).toHaveBeenCalledTimes(1)406 expect(onUpdateScrollPositionMock).toHaveBeenCalledWith(10)407 })408 })...
tests.spec.js
Source:tests.spec.js
1/* global describe, it, afterEach, beforeEach */2import {expect} from 'chai'3import {mapStateToProps, mapPropsOnChange, hasObjectTypeError, setPropTypes, setStateTypes, composeProps} from '../src/composeProps.js'4import {PropTypes} from 'react'5describe('compose-props', () => {6 describe('mapStateToProps()', () => {7 const initState = {set: [{ id: 1 }, { id: 2 }]}8 const initProps = {a: 1, b: {c: 2}}9 it('should call propMapper function with state and props', () => {10 const newPropsFunction = function (passedState, passedProps) {11 expect(passedState).to.deep.equal(initState)12 expect(passedProps).to.deep.equal(initProps)13 return {}14 }15 const statePropsFunc = mapStateToProps(newPropsFunction)16 statePropsFunc(initState, initProps)17 })18 it('should return new object with initial props spread first then returned propMapper object spread', () => {19 const newPropsFunction = function (passedState, passedProps) {20 return {b: 3}21 }22 const statePropsFunc = mapStateToProps(newPropsFunction)23 const newObject = statePropsFunc(initState, initProps)24 expect(newObject).to.deep.equal({a: 1, b: 3})25 })26 })27 describe('mapPropsOnChange()', () => {28 const initState = {set: [{ id: 1 }, { id: 2 }]}29 const initProps = {a: 1, b: {c: 2}}30 it('should call propMapper function with state and props', () => {31 const newPropsFunction = function (passedState, passedProps) {32 expect(passedState).to.deep.equal(initState)33 expect(passedProps).to.deep.equal(initProps)34 return {}35 }36 const statePropsFunc = mapPropsOnChange(['b'], newPropsFunction)37 statePropsFunc(initState, initProps)38 })39 it('should return new object with initial props(omiting watched keys) spread first then returned propMapper object spread', () => {40 const newPropsFunction = function (passedState, passedProps) {41 return {a: 3}42 }43 const statePropsFunc = mapPropsOnChange(['b'], newPropsFunction)44 const newObject = statePropsFunc(initState, initProps)45 expect(newObject).to.deep.equal({a: 3})46 })47 it('should only call propMapper once if watched props are unchanged', () => {48 let propMapperCalled = 049 const newPropsFunction = function (passedState, passedProps) {50 propMapperCalled += 151 return {}52 }53 const statePropsFunc = mapPropsOnChange(['b'], newPropsFunction)54 statePropsFunc(initState, initProps)55 statePropsFunc(initState, initProps)56 expect(propMapperCalled).to.equal(1)57 })58 it('should call propMapper again when watched props are changed', () => {59 let propMapperCalled = 060 const newPropsFunction = function (passedState, passedProps) {61 propMapperCalled += 162 return {}63 }64 const statePropsFunc = mapPropsOnChange(['b'], newPropsFunction)65 statePropsFunc(initState, initProps)66 statePropsFunc(initState, {a: 1, b: {c: 3}})67 expect(propMapperCalled).to.equal(2)68 })69 })70 describe('hasObjectTypeError() - used by setStateTypes and setPropTypes', () => {71 let oldConsoleWarn72 let testError = 'no errors'73 beforeEach(() => {74 // mocking console.warn for test purposes... gross...75 oldConsoleWarn = console.warn76 console.warn = (err) => {77 testError = err78 }79 })80 afterEach(() => {81 console.warn = oldConsoleWarn82 testError = 'no errors'83 })84 const dataObject = {a: 1, b: {c: 2}}85 const testObjectTypes = {86 a: PropTypes.number.isRequired,87 b: PropTypes.shape({c: PropTypes.number.isRequired}).isRequired88 }89 it('should return false when there are no error', () => {90 const hasErrors = hasObjectTypeError({}, dataObject)91 expect(hasErrors).to.deep.equal(false)92 })93 it('should return false and not console.warn any errors with passing propTypes', () => {94 const hasErrors = hasObjectTypeError(testObjectTypes, dataObject)95 expect(hasErrors).to.deep.equal(false)96 expect(testError).to.equal('no errors')97 })98 it('should return true and console.warn errors when there are errors in propTypes', () => {99 const hasErrors = hasObjectTypeError(testObjectTypes, {})100 expect(hasErrors).to.deep.equal(true)101 expect(testError).to.not.equal('no errors')102 })103 describe('hasObjectTypeError tests which NODE_ENV environment', () => {104 let oldEnv105 beforeEach(() => {106 oldEnv = process.env.NODE_ENV107 })108 afterEach(() => {109 process.env.NODE_ENV = oldEnv110 })111 it('should return false when NODE_ENV is \'production\'', () => {112 process.env.NODE_ENV = 'production'113 const hasErrors = hasObjectTypeError(testObjectTypes, {})114 expect(hasErrors).to.deep.equal(false)115 })116 })117 describe('hasObjectTypeError tests if running in React Native environment', () => {118 let oldEnv119 beforeEach(() => {120 oldEnv = process.env.NODE_ENV121 GLOBAL.navigator = {}122 Object.defineProperty(GLOBAL.navigator, 'product', {value: 'ReactNative'})123 })124 afterEach(() => {125 process.env.NODE_ENV = oldEnv126 delete GLOBAL.navigator127 })128 it('should run when in React Native, even when NODE_ENV is \'production\'', () => {129 process.env.NODE_ENV = 'production'130 const hasErrors = hasObjectTypeError(testObjectTypes, {})131 expect(hasErrors).to.deep.equal(true)132 })133 })134 })135 describe('setPropTypes()', () => {136 let oldConsoleWarn137 beforeEach(() => {138 // mocking console.warn for test purposes... gross...139 oldConsoleWarn = console.warn140 console.warn = () => {}141 })142 afterEach(() => {143 console.warn = oldConsoleWarn144 })145 it('should return props when there are no errors', () => {146 const initProps = {a: 1}147 const statePropsFunc = setPropTypes({})148 const outputProps = statePropsFunc({}, initProps)149 expect(outputProps).to.deep.equal(initProps)150 })151 it('should return null when there are errors', () => {152 const initProps = {a: '1'}153 const testObjectTypes = { a: PropTypes.number.isRequired }154 const statePropsFunc = setPropTypes(testObjectTypes)155 const outputProps = statePropsFunc({}, initProps)156 expect(outputProps).to.equal(null)157 })158 })159 describe('setStateTypes()', () => {160 let oldConsoleWarn161 beforeEach(() => {162 // mocking console.warn for test purposes... gross...163 oldConsoleWarn = console.warn164 console.warn = () => {}165 })166 afterEach(() => {167 console.warn = oldConsoleWarn168 })169 it('should return props when there are no errors', () => {170 const initProps = {a: 1}171 const statePropsFunc = setStateTypes({})172 const outputProps = statePropsFunc({}, initProps)173 expect(outputProps).to.deep.equal(initProps)174 })175 it('should return null when there are errors', () => {176 const initState = {a: '1'}177 const testObjectTypes = { a: PropTypes.number.isRequired }178 const statePropsFunc = setPropTypes(testObjectTypes)179 const outputProps = statePropsFunc(initState, {})180 expect(outputProps).to.equal(null)181 })182 })183 describe('composeProps()', () => {184 const initState = {set: [{ id: 1 }, { id: 2 }]}185 const initProps = {a: 1, b: {c: 2}}186 it('should default props to empty object and pass in state', () => {187 const statePropsFunc = composeProps(188 (passedState, passedProps) => {189 expect(passedProps).to.deep.equal({})190 expect(passedState).to.deep.equal(initState)191 }192 )193 statePropsFunc(initState)194 })195 it('should work with any function that takes in (state, props), and return last functions returned object', () => {196 let calledFuncCount = 0197 const statePropsFunc = composeProps(198 (state, props) => {199 calledFuncCount += 1200 expect(props).to.deep.equal(initProps)201 return {a: 1}202 },203 (state, props) => {204 calledFuncCount += 1205 expect(props).to.deep.equal({a: 1})206 return {c: 1}207 }208 )209 expect(calledFuncCount).to.equal(0)210 const finalProps = statePropsFunc(initState, initProps)211 expect(calledFuncCount).to.equal(2)212 expect(finalProps).to.deep.equal({c: 1})213 })214 describe('works with other compose-props methods', () => {215 let oldConsoleWarn216 let testError = 'no errors'217 beforeEach(() => {218 // mocking console.warn for test purposes... gross...219 oldConsoleWarn = console.warn220 console.warn = (err) => {221 testError = err222 }223 })224 afterEach(() => {225 console.warn = oldConsoleWarn226 testError = 'no errors'227 })228 it('should \'short circuit\' when a composed function returns null, and return an empty object({})', () => {229 const testStateProps = { set: PropTypes.arrayOf(PropTypes.number.isRequired).isRequired }230 let count = 0231 const initState = {set: ['a', 'b']}232 const statePropsFunc = composeProps(233 (s, p) => {234 count += 1235 return p236 },237 setStateTypes(testStateProps, 'compose setStateTypes'),238 (s, p) => {239 count += 1240 return p241 }242 )243 expect(count).to.equal(0)244 const firstRunProps = statePropsFunc(initState, initProps)245 expect(testError).to.not.equal('no errors')246 expect(count).to.equal(1)247 expect(firstRunProps).to.deep.equal({})248 })249 it('should work with mapStateToProps, setPropTypes, setStateTypes, and mapPropsOnChange', () => {250 const testStateProps = {251 set: PropTypes.arrayOf(PropTypes.shape({id: PropTypes.number.isRequired})).isRequired252 }253 const testPropTypes = {254 a: PropTypes.number.isRequired,255 b: PropTypes.shape({c: PropTypes.number.isRequired}).isRequired256 }257 let calledComposeCount = 0258 let calledOnChangeCount = 0259 const initState = {set: [{ id: 1 }, { id: 2 }]}260 const initProps = {a: 1, b: {c: 2}}261 const statePropsFunc = composeProps(262 (s, p) => {263 calledComposeCount += 1264 return p265 },266 setStateTypes(testStateProps, 'compose setStateTypes'),267 setPropTypes(testPropTypes, 'compose setPropTypes'),268 mapStateToProps((passedState, passedProps) => {269 expect(passedState).to.deep.equal(initState)270 expect(passedProps).to.deep.equal(initProps)271 return {d: 4}272 }),273 mapPropsOnChange(['b'], (passedState, passedProps) => {274 expect(passedState).to.deep.equal(initState)275 expect(passedProps).to.deep.equal({...initProps, d: 4})276 calledOnChangeCount += 1277 return {e: 5}278 })279 )280 expect(calledComposeCount).to.equal(0)281 expect(calledOnChangeCount).to.equal(0)282 const expectOutProps = {a: 1, d: 4, e: 5}283 const firstRunProps = statePropsFunc(initState, initProps)284 expect(testError).to.equal('no errors')285 expect(calledComposeCount).to.equal(1)286 expect(calledOnChangeCount).to.equal(1)287 expect(firstRunProps).to.deep.equal(expectOutProps)288 const secondRunProps = statePropsFunc(initState, initProps)289 expect(calledComposeCount).to.equal(2)290 expect(calledOnChangeCount).to.equal(1)291 expect(secondRunProps).to.deep.equal(expectOutProps)292 })293 })294 it('should \'compose\' other composeProps\'s output', () => {295 const state = {b: 1}296 const statePropsFunc = composeProps(297 (passedState, passedProps) => {298 expect(passedProps).to.deep.equal({})299 expect(passedState).to.deep.equal(state)300 return {a: 1}301 },302 composeProps(303 (passedState, passedProps) => {304 expect(passedProps).to.deep.equal({a: 1})305 expect(passedState).to.deep.equal(state)306 return {c: 1}307 }308 )309 )310 const finalProps = statePropsFunc(state)311 expect(finalProps).to.deep.equal({c: 1})312 })313 })...
CarouselThumbnail.spec.js
Source:CarouselThumbnail.spec.js
1import testComponentHelper from 'test/unit/helpers/test-component'2import CarouselThumbnail from '../CarouselThumbnail'3import ResponsiveImage from '../../ResponsiveImage/ResponsiveImage'4describe('<CarouselThumbnail />', () => {5 const initProps = {6 name: 'overlayThumbs',7 mode: 'thumbnail',8 carousel: {9 overlayThumbs: {10 direction: 'right',11 previous: -1,12 current: 0,13 max: 7,14 zoom: 1,15 panX: 0,16 panY: 0,17 },18 },19 assets: [20 {21 url: 'http://topshop.com/assets/demo_image_1.jpg',22 assetType: 'IMAGE_SMALL',23 },24 {25 url: 'http://topshop.com/assets/demo_image_2.jpg',26 assetType: 'IMAGE_SMALL',27 },28 {29 url: 'http://topshop.com/assets/demo_image_3.jpg',30 assetType: 'IMAGE_SMALL',31 },32 ],33 className: '',34 touchEnabled: false,35 isMobile: false,36 backCarousel: jest.fn(),37 forwardCarousel: jest.fn(),38 onClick: jest.fn(),39 }40 const newAssets = [41 {42 url: 'http://topshop.com/assets/demo_image_4.jpg',43 assetType: 'IMAGE_SMALL',44 },45 {46 url: 'http://topshop.com/assets/demo_image_5.jpg',47 assetType: 'IMAGE_SMALL',48 },49 ]50 const renderComponent = testComponentHelper(CarouselThumbnail)51 describe('@renders', () => {52 it('with a default state', () => {53 expect(renderComponent(initProps).getTree()).toMatchSnapshot()54 })55 it('with empty assets', () => {56 expect(57 renderComponent({58 ...initProps,59 assets: [],60 }).getTree()61 ).toMatchSnapshot()62 })63 it('with mode thumbnail', () => {64 expect(65 renderComponent({66 ...initProps,67 mode: 'thumbnail',68 }).getTree()69 ).toMatchSnapshot()70 })71 it('when desktop and zoomed in', () => {72 expect(73 renderComponent({74 ...initProps,75 isMobile: false,76 carousel: {77 overlayThumbs: {78 ...initProps.carousel.overlayThumbs,79 zoom: 2,80 },81 },82 }).getTree()83 ).toMatchSnapshot()84 })85 it('without carousel arrow buttons if assets is less than 5', () => {86 const { wrapper } = renderComponent(initProps)87 expect(wrapper.find('.Carousel-arrow')).toHaveLength(0)88 })89 it('with carousel arrow buttons if assets is greater than 4', () => {90 const { wrapper } = renderComponent({91 ...initProps,92 assets: initProps.assets.concat(newAssets),93 })94 expect(wrapper.find('.Carousel-arrow')).toHaveLength(2)95 })96 it('with padding when assets is greater than 4', () => {97 const { instance } = renderComponent(initProps)98 expect(99 instance.addClassNamesToCarouselImages(100 initProps.assets.concat(newAssets),101 4102 )103 ).toBe('Carousel-images Carousel-images--padding')104 })105 it('without padding when assets is less than 5', () => {106 const { instance } = renderComponent(initProps)107 expect(instance.addClassNamesToCarouselImages(initProps.assets, 4)).toBe(108 'Carousel-images'109 )110 })111 it('should be centered if assets is more than 5', () => {112 const { instance } = renderComponent(initProps)113 expect(114 instance.centerThumbnails(initProps.assets.concat(newAssets), 4)115 ).toEqual({ justifyContent: 'center' })116 })117 it('with responsive images and sizes', () => {118 const assets = [{ url: 'image 2 ' }, { url: 'image 2' }]119 const amplienceImages = ['url 1', 'url 2']120 const sizes = { mobile: 1, tablet: 2, desktop: 3 }121 const { wrapper } = renderComponent({122 ...initProps,123 sizes,124 assets,125 amplienceImages,126 })127 const responsiveImage = wrapper.find(ResponsiveImage)128 expect(responsiveImage).toHaveLength(assets.length)129 assets.forEach((asset, index) => {130 expect(responsiveImage.at(index).prop('sizes')).toBe(sizes)131 expect(responsiveImage.at(index).prop('amplienceUrl')).toBe(132 amplienceImages[index]133 )134 })135 })136 })...
AddToBagConfirm.spec.js
Source:AddToBagConfirm.spec.js
1import testComponentHelper from 'test/unit/helpers/test-component'2import AddToBagConfirm from '../AddToBagConfirm'3import { browserHistory } from 'react-router'4import { GTM_TRIGGER, GTM_EVENT } from '../../../../analytics'5jest.mock('react-router', () => ({6 browserHistory: {7 push: jest.fn(),8 },9}))10describe('<AddToBagConfirm /> ', () => {11 const initProps = {12 openMiniBag: jest.fn(),13 onClose: jest.fn(),14 sendAnalyticsDisplayEvent: jest.fn(),15 closeModal: jest.fn(),16 pageType: 'pdp',17 }18 const mockedEvent = {19 stopPropagation: jest.fn(),20 }21 const renderComponent = testComponentHelper(AddToBagConfirm.WrappedComponent)22 describe('@renders', () => {23 it('with default props', () => {24 expect(renderComponent(initProps).getTree()).toMatchSnapshot()25 })26 })27 describe('@events', () => {28 describe('on click viewBag', () => {29 beforeEach(() => {30 jest.clearAllMocks()31 })32 it('should call openMiniBag and onClose', () => {33 const { wrapper } = renderComponent(initProps)34 wrapper35 .find('.AddToBagConfirm-viewBag')36 .props()37 .clickHandler(mockedEvent)38 expect(initProps.onClose).toHaveBeenCalledTimes(1)39 expect(initProps.openMiniBag).toHaveBeenCalledTimes(1)40 expect(initProps.sendAnalyticsDisplayEvent).toHaveBeenCalledWith(41 {42 bagDrawerTrigger: GTM_TRIGGER.PRODUCT_VIEW_BAG,43 openFrom: 'pdp',44 },45 GTM_EVENT.BAG_DRAWER_DISPLAYED46 )47 })48 it('should call evt.stopPropagation if evt is defined', () => {49 const { wrapper } = renderComponent(initProps)50 wrapper51 .find('.AddToBagConfirm-viewBag')52 .props()53 .clickHandler(mockedEvent)54 expect(mockedEvent.stopPropagation).toHaveBeenCalledTimes(1)55 })56 })57 describe('onclick goToCheckout', () => {58 beforeEach(() => {59 jest.clearAllMocks()60 })61 it('should call browserHistory.push and onClose', () => {62 const { wrapper, instance } = renderComponent(initProps)63 wrapper64 .find('.AddToBagConfirm-goToCheckout')65 .props()66 .clickHandler(mockedEvent)67 expect(instance.props.onClose).toHaveBeenCalledTimes(1)68 expect(browserHistory.push).toHaveBeenCalledTimes(1)69 expect(browserHistory.push).toHaveBeenLastCalledWith('/checkout')70 })71 it('should call evt.stopPropagation if evt is defined', () => {72 const { wrapper } = renderComponent(initProps)73 wrapper74 .find('.AddToBagConfirm-goToCheckout')75 .props()76 .clickHandler(mockedEvent)77 expect(mockedEvent.stopPropagation).toHaveBeenCalledTimes(1)78 })79 it('should call closeModal if modal is open', () => {80 const { wrapper } = renderComponent({81 ...initProps,82 modalOpen: true,83 })84 wrapper85 .find('.AddToBagConfirm-goToCheckout')86 .props()87 .clickHandler(mockedEvent)88 expect(initProps.closeModal).toHaveBeenCalledTimes(1)89 })90 it('should not call closeModal if modal is not open', () => {91 const { wrapper } = renderComponent({92 ...initProps,93 modalOpen: false,94 })95 wrapper96 .find('.AddToBagConfirm-goToCheckout')97 .props()98 .clickHandler(mockedEvent)99 expect(initProps.closeModal).not.toHaveBeenCalled()100 })101 })102 })...
Page.test.js
Source:Page.test.js
1import Page from "../index";2const initProps = {3 description: "hi",4 head: {5 title: "Alias Dirs",6 url: "/alias-dirs",7 description: "Automatically creates aliased import directories for babel.",8 },9 filedetails: {10 active: false,11 status: "Decommissioned",12 location: "https://example.com",13 source: "https://github.com/mattcarlotta/alias-dirs",14 },15 snapshotdirectory: "aliasdirs",16 snapshots: [17 {18 src: "aliasLogo",19 alt: "logo-preview",20 title: "Logo",21 },22 ],23 tech: ["Babel", "Enzyme", "Javascript", "Jest", "RollupJS"],24};25let wrapper = mount(<Page {...initProps} />);26describe("Page", () => {27 it("renders without errors", () => {28 expect(wrapper.find("Page")).toExist();29 });30 it("populates the head with a title, url, description, and type", () => {31 const head = wrapper.find("Header");32 expect(head.props().title).toEqual(initProps.head.title);33 expect(head.props().url).toEqual(initProps.head.url);34 expect(head.props().description).toEqual(initProps.head.description);35 });36 it("populates the panel title", () => {37 expect(wrapper.find("PanelTitle").text()).toEqual(initProps.head.title);38 });39 it("renders the solar system", () => {40 expect(wrapper.find("[data-testid='solar-system']")).toExist();41 });42 it("populates the file details", () => {43 expect(wrapper.find("[data-testid='status']").first().text()).toEqual(44 initProps.filedetails.status,45 );46 expect(wrapper.find("[data-testid='filename']").first().text()).toEqual(47 initProps.head.title,48 );49 expect(wrapper.find("[data-testid='location']").first().text()).toEqual(50 initProps.filedetails.location,51 );52 expect(wrapper.find("[data-testid='source']").first().text()).toEqual(53 initProps.filedetails.source,54 );55 });56 it("populates the description details", () => {57 expect(wrapper.find("[data-testid='description']").first().text()).toEqual(58 initProps.description,59 );60 });61 it("populates the tech details", () => {62 expect(wrapper.find("[data-testid='tech']").first().text()).toEqual(63 initProps.tech.map(t => t).join(""),64 );65 });66 it("populates the snapshots", () => {67 const { snapshotdirectory, snapshots } = initProps;68 const snapshot = wrapper.find("[data-testid='snapshots']").first();69 expect(snapshot.find("CardTitle").first().text()).toEqual(70 snapshots[0].title,71 );72 expect(snapshot.find("Image").first().props().src).toEqual(73 `projects/${snapshotdirectory}/${snapshots[0].src}Min`,74 );75 expect(snapshot.find("Image").first().props().alt).toEqual(76 snapshots[0].alt,77 );78 });79 it("displays a modal", () => {80 wrapper.find("PreviewCard").first().simulate("click");81 expect(wrapper.find("Modal").first().props().isOpen).toBeTruthy();82 });83 it("populates the file details with active project", () => {84 const status = "In Orbit";85 const activeProps = {86 ...initProps,87 filedetails: {88 ...initProps.filedetails,89 active: true,90 status,91 },92 };93 wrapper = mount(<Page {...activeProps} />);94 expect(wrapper.find("[data-testid='status']").first().text()).toEqual(95 status,96 );97 expect(wrapper.find("BsFillCircleFill").first()).toHaveStyle(98 "color",99 "limegreen",100 );101 });...
propLoaders.js
Source:propLoaders.js
1/**2 * Load the app's properties by contacting the parent window3 *4 * @param {string} widgetId5 * @param {{ send: Function }} postRobot6 * @return {function(): Promise<Object, Error>}7 */8export function fromParentWindow(widgetId, postRobot) {9 /**10 * @return {Promise<Object, Error>}11 */12 function fromParentWindowAction() {13 return postRobot14 .send(15 postRobot.parent,16 `urn:deskpro:apps.widget.onready?widgetId=${widgetId}`,17 {},18 )19 .then(event => event.data);20 }21 return fromParentWindowAction;22}23/**24 * Loads the app's properties from the initialization properties25 *26 * @param {string} widgetId27 * @param {InitPropertiesBag} initProps28 * @return {function(): Promise<Object, Error>}29 */30export function fromInitProps(widgetId, initProps) {31 function fromInitPropsAction() {32 return Promise.resolve({33 isPreRender: initProps.getProperty('dpRender') === 'static',34 instanceProps: {35 appId: initProps.getProperty('dpInstanceAppId'),36 appTitle: initProps.getProperty('dpInstanceAppTitle'),37 appPackageName: initProps.getProperty('dpInstanceAppPackageName'),38 instanceId: initProps.getProperty('dpInstanceInstanceId'),39 },40 contextProps: {41 type: initProps.getProperty('dpContextType'),42 entityId: initProps.getProperty('dpContextEntityId'),43 locationId: initProps.getProperty('dpContextLocationId'),44 tabId: initProps.getProperty('dpContextTabId'),45 tabUrl: initProps.getProperty('dpContextTabUrl'),46 },47 });48 }49 return fromInitPropsAction;...
Using AI Code Generation
1const playwright = require('playwright');2(async () => {3 const browser = await playwright.chromium.launch();4 const page = await browser.newPage();5 await page.screenshot({ path: 'example.png' });6 await browser.close();7})();
Using AI Code Generation
1const playwright = require('playwright');2const { initProps } = require('playwright/lib/server/chromium/crBrowser');3(async () => {4 const browser = await playwright.chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const crBrowser = page._delegate._browserContext._browser;8 const { targetId } = crBrowser._targets.get(page._delegate);9 const { browserContextId } = crBrowser._targets.get(page._delegate._browserContext);10 const { viewportSize } = await crBrowser._connection.send('Browser.getWindowForTarget', { targetId });11 const { deviceScaleFactor, isMobile } = await crBrowser._connection.send('Browser.getBrowserContextForTarget', { targetId, browserContextId });12 const { isHeadless } = crBrowser._options;13 const { isMobile: isMobileBrowser } = crBrowser._options;14 const { isTouch } = crBrowser._options;15 const { deviceScaleFactor: deviceScaleFactorBrowser } = crBrowser._options;16 const { viewportSize: viewportSizeBrowser } = crBrowser._options;17 const props = await initProps(crBrowser._connection, targetId, browserContextId, viewportSize, deviceScaleFactor, isMobile, isHeadless, isMobileBrowser, isTouch, deviceScaleFactorBrowser, viewportSizeBrowser);18 console.log(props);19 await browser.close();20})();21const { assert } = require('console');22const { BrowserContext } = require('playwright/lib/server/browserContext');23const { Browser } = require('playwright/lib/server/chromium/browser');24const { Page } = require('playwright/lib/server/page');25const { assertMaxArguments } = require('playwright/lib/utils/utils');26const { convertProtocolError } = require('playwright/lib/server/crProtocolHelper');27const { assertType } = require('playwright/lib/server/common/assert');28const { BrowserContextOptions } = require('playwright/lib/server/browserContext');29const { BrowserOptions } = require('playwright/lib/server/browser');30const { PageOptions } = require('playwright/lib/server/page');31const { ViewportSize } = require('playwright/lib/server/chromium/crTypes');32const { BrowserContext
Using AI Code Generation
1const { initProps } = require('playwright/lib/client/initializer');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const props = await page.evaluate(() => {8 const { document } = window;9 const element = document.querySelector('body');10 return initProps(element);11 });12 console.log(props);13 await browser.close();14})();15{ nodeName: 'BODY',16 { nodeName: '#document',17 contentType: 'text/html; charset=UTF-8',18 contentType: 'text/html; charset=UTF-8',
Using AI Code Generation
1const playwright = require('playwright');2const { initProps } = require('playwright/lib/server/chromium/crBrowser');3const browser = await playwright.chromium.launch();4const context = await browser.newContext();5const page = await context.newPage();6await initProps(page);7await page.screenshot({ path: 'example.png' });8await browser.close();9const playwright = require('playwright');10const { initProps } = require('playwright/lib/server/chromium/crBrowser');11const browser = await playwright.chromium.launch();12const context = await browser.newContext();13const page = await context.newPage();14await initProps(page);15await page.screenshot({ path: 'example.png' });16await browser.close();17const playwright = require('playwright');18const { initProps } = require('playwright/lib/server/chromium/crBrowser');19const browser = await playwright.chromium.launch();20const context = await browser.newContext();21const page = await context.newPage();22await initProps(page);23await page.screenshot({ path: 'example.png' });24await browser.close();25const playwright = require('playwright');26const { initProps } = require('playwright/lib/server/chromium/crBrowser');27const browser = await playwright.chromium.launch();28const context = await browser.newContext();29const page = await context.newPage();30await initProps(page);31await page.screenshot({ path: 'example.png' });32await browser.close();33const playwright = require('playwright');34const { initProps } = require('playwright/lib/server/chromium/crBrowser');35const browser = await playwright.chromium.launch();36const context = await browser.newContext();37const page = await context.newPage();38await initProps(page);39await page.screenshot({ path: 'example.png' });40await browser.close();
Using AI Code Generation
1const { initProps } = require('playwright/lib/server/chromium/crBrowser');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const page = await browser.newPage();6 await page.screenshot({ path: 'example.png' });7 initProps(page, { name: 'Hello' });8 console.log(page.name);9 await browser.close();10})();11const { initProps } = require('playwright/lib/server/chromium/crBrowser');12const { chromium } = require('playwright');13(async () => {14 const browser = await chromium.launch({ headless: false });15 const page = await browser.newPage();16 await page.screenshot({ path: 'example.png' });17 initProps(page, { name: 'Hello' });18 console.log(page.name);19 await browser.close();20})();21page.name = 'hello';22const { chromium } = require('playwright');23(async () => {24 const browser = await chromium.launch({ headless: false });25 const page = await browser.newPage();
Using AI Code Generation
1const { initProps } = require('playwright/lib/client/transport');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 await page.screenshot({ path: 'example.png' });7 await browser.close();8})();9initProps({10 launchOptions: {11 },12 contextOptions: {13 viewport: {14 },15 },16});
Using AI Code Generation
1const playwright = require('playwright');2const { initProps } = playwright;3const { chromium } = playwright;4const { webkit } = playwright;5const { firefox } = playwright;6const { devices } = playwright;7const { selectors } = playwright;8(async () => {9 const browser = await chromium.launch();10 const context = await browser.newContext();11 const page = await context.newPage();12 initProps(page, 'test');13 await page.waitForTimeout(1000);14 await browser.close();15})();16const playwright = require('playwright');17const { initProps } = playwright;18const { chromium } = playwright;19const { webkit } = playwright;20const { firefox } = playwright;21const { devices } = playwright;22const { selectors } = playwright;23(async () => {24 const browser = await chromium.launch();25 const context = await browser.newContext();26 const page = await context.newPage();27 initProps(page, 'test');28 await page.waitForTimeout(1000);29 await browser.close();30})();31const playwright = require('playwright');32const { initProps } = playwright;33const { chromium } = playwright;34const { webkit } = playwright;35const { firefox } = playwright;36const { devices } = playwright;37const { selectors } = playwright;38(async () => {39 const browser = await chromium.launch();40 const context = await browser.newContext();41 const page = await context.newPage();42 initProps(page, 'test');43 await page.waitForTimeout(1000);44 await browser.close();45})();46const playwright = require('playwright');47const { initProps } = playwright;48const { chromium } = playwright;49const { webkit } = playwright;50const { firefox } = playwright;51const { devices } = playwright;52const { selectors } =
Using AI Code Generation
1const { initProps } = require('@playwright/test/lib/test');2const test = initProps({3});4test('test', async ({ page }) => {5});6const { test } = require('@playwright/test');7test.use({8});9test('test', async ({ page }) => {10});11const { test } = require('@playwright/test');12test.describe('My test suite', () => {13 test('test', async ({ page }) => {14 });15});16const { test } = require('@playwright/test');17test.beforeAll(async () => {18});19test.afterAll(async () => {20});21const { test } = require('@playwright/test');22test.beforeEach(async () => {23});24test.afterEach(async () => {25});26const { test } = require('@playwright/test');27test.skip('test', async ({ page }) => {28});29const { test } = require('@playwright/test');30test.only('test', async ({ page }) => {31});32const { test } = require('@playwright/test');33test('test', async ({ page }) => {34 test.expect(true).toBe(true);35});36const {
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!