diff --git a/package-lock.json b/package-lock.json index 759db0d..000e39b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-inner-image-zoom", - "version": "1.0.6", + "version": "1.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/tests/constants.js b/tests/constants.js deleted file mode 100644 index 5c7e34d..0000000 --- a/tests/constants.js +++ /dev/null @@ -1,18 +0,0 @@ -export const TEST_PROPS = { - src: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=500', - zoomSrc: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1000', - className: 'custom', - sources: [{ - srcSet: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=750, https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1500 2x', - media: '(min-width: 768px)' - }, { - srcSet: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1000, https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=2000 2x', - media: '(min-width: 1024px)' - }], - invalidSources: [{ - srcSet: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=750, https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1500 2x', - media: '(min-width: 768px)' - }, { - media: '(min-width: 1024px)' - }] -}; \ No newline at end of file diff --git a/tests/constants/srcs.js b/tests/constants/srcs.js new file mode 100644 index 0000000..d0fc72a --- /dev/null +++ b/tests/constants/srcs.js @@ -0,0 +1,21 @@ +export const SRCS = { + default: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=500', + zoom: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1000', + sources: [ + { + srcSet: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=750, https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1500 2x', + media: '(min-width: 768px)' + }, { + srcSet: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1000, https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=2000 2x', + media: '(min-width: 1024px)' + } + ], + invalidSources: [ + { + srcSet: 'https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=750, https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1500 2x', + media: '(min-width: 768px)' + }, { + media: '(min-width: 1024px)' + } + ] +}; \ No newline at end of file diff --git a/tests/index-test.js b/tests/index-test.js deleted file mode 100644 index 5c0e7da..0000000 --- a/tests/index-test.js +++ /dev/null @@ -1,232 +0,0 @@ -import expect from 'expect' -import React from 'react'; -import ReactTestUtils from 'react-dom/test-utils'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { TEST_PROPS } from './constants'; -import InnerImageZoom from 'src/'; -import 'src/InnerImageZoom/styles.css'; - -describe('InnerImageZoom', () => { - let node; - let src = TEST_PROPS.src; - - beforeEach(() => { - node = document.createElement('div'); - }); - - afterEach(() => { - unmountComponentAtNode(node); - }); - - const innerImageZoom = (props = {}) => { - return render(, node); - } - - describe('mount', () => { - describe('container', () => { - it('renders a figure', () => { - const component = innerImageZoom(); - const figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - - expect(figure).toExist(); - }); - - it('renders a figure with a custom classname', () => { - const component = innerImageZoom({ className: TEST_PROPS.className }); - const figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - const hasClass = figure.classList.contains('custom'); - - expect(hasClass).toBe(true); - }); - }); - - describe('original image', () => { - it('renders the original image', () => { - const component = innerImageZoom(); - const img = ReactTestUtils.findRenderedDOMComponentWithClass(component, 'iiz__img'); - - expect(img).toExist(); - }); - - it('renders the original image with sources', () => { - const component = innerImageZoom({ sources: TEST_PROPS.sources }); - const sources = ReactTestUtils.scryRenderedDOMComponentsWithTag(component, 'source'); - - expect(sources.length).toEqual(2); - }); - - it('only renders sources that have srcSet set', () => { - const component = innerImageZoom({ sources: TEST_PROPS.invalidSources }); - const sources = ReactTestUtils.scryRenderedDOMComponentsWithTag(component, 'source'); - - expect(sources.length).toEqual(1); - }); - }); - }); - - describe('zoom in', () => { - describe('render', () => { - it('renders the zoomed image on mouse enter', () => { - const component = innerImageZoom(); - const figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - ReactTestUtils.Simulate.mouseEnter(figure); - const zoomImg = figure.querySelector('.iiz__zoom-img'); - - expect(zoomImg).toExist(); - }); - - it('renders the zoomed image with unique src if set', () => { - const component = innerImageZoom({ zoomSrc: TEST_PROPS.zoomSrc }); - const figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - ReactTestUtils.Simulate.mouseEnter(figure); - const zoomImg = figure.querySelector('.iiz__zoom-img'); - const src = zoomImg.getAttribute('src'); - - expect(src).toEqual('https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1000'); - }); - }); - - describe('show', () => { - beforeEach(() => { - document.body.appendChild(node); - }); - - afterEach(() => { - document.body.removeChild(node); - }); - - it('makes the zoomed image visible on click', (done) => { - const component = innerImageZoom(); - const figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - const zoomImg = figure.querySelector('.iiz__zoom-img'); - - zoomImg.onload = () => { - const visibleZoomImg = figure.querySelector('.iiz__zoom-img--visible'); - - expect(visibleZoomImg).toExist(); - done(); - } - }); - - it('renders the zoomed image in a fullscreen portal if fullscreenOnMobile is set', () => { - global.innerWidth = 500; - global.window.matchMedia = () => { return { matches: true }}; - const component = innerImageZoom({ fullscreenOnMobile: true }); - const figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - ReactTestUtils.Simulate.touchStart(figure); - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - const zoomPortal = document.querySelector('.iiz__zoom-portal'); - - expect(zoomPortal).toExist(); - }); - }); - }); - - describe('move', () => { - let figure = null; - let zoomImg = null; - - beforeEach(() => { - document.body.appendChild(node); - const component = innerImageZoom({ zoomSrc: TEST_PROPS.zoomSrc }); - figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - zoomImg = figure.querySelector('.iiz__zoom-img'); - }); - - afterEach(() => { - document.body.removeChild(node); - }); - - it('pans the zoomed image on mouse move', (done) => { - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - const zoomImg = figure.querySelector('.iiz__zoom-img'); - - zoomImg.onload = () => { - const topPos = zoomImg.style.top; - ReactTestUtils.Simulate.mouseMove(figure, { pageX: 150, pageY: 150 }); - const updatedTopPos = zoomImg.style.top; - - expect(parseInt(topPos, 10)).toNotEqual(parseInt(updatedTopPos, 10)); - done(); - } - }); - }); - - describe('zoom out', () => { - let figure = null; - - beforeEach(() => { - document.body.appendChild(node); - const component = innerImageZoom(); - figure = ReactTestUtils.findRenderedDOMComponentWithTag(component, 'figure'); - }); - - afterEach(() => { - document.body.removeChild(node); - }); - - it('hides the zoomed image on toggle click', () => { - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - const visibleZoomImg = figure.querySelector('.iiz__zoom-img--visible'); - - expect(visibleZoomImg).toBe(null); - }); - - it('hides the zoomed image on mouse leave', () => { - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - ReactTestUtils.Simulate.mouseLeave(figure); - const visibleZoomImg = figure.querySelector('.iiz__zoom-img--visible'); - - expect(visibleZoomImg).toBe(null); - }); - - it('hides the zoomed image on close button click on touch devices', (done) => { - ReactTestUtils.Simulate.touchStart(figure); - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - const closeButton = figure.querySelector('.iiz__close'); - ReactTestUtils.Simulate.click(closeButton, { pageX: 0, pageY: 0 }); - const visibleZoomImg = figure.querySelector('.iiz__zoom-img--visible'); - - setTimeout(() => { - expect(visibleZoomImg).toBe(null); - done(); - }, 150); - }); - - it('removes the zoomed image after fade transition', (done) => { - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - ReactTestUtils.Simulate.mouseLeave(figure); - - setTimeout(() => { - const zoomImg = figure.querySelector('.iiz__zoom-img'); - - expect(zoomImg).toBe(null); - done(); - }, 150); - }); - - it('removes the zoomed image after fade transition on touch devices', (done) => { - ReactTestUtils.Simulate.touchStart(figure); - ReactTestUtils.Simulate.mouseEnter(figure); - ReactTestUtils.Simulate.click(figure, { pageX: 100, pageY: 100 }); - const closeButton = figure.querySelector('.iiz__close'); - ReactTestUtils.Simulate.click(closeButton, { pageX: 0, pageY: 0 }); - - setTimeout(() => { - const zoomImg = figure.querySelector('.iiz__zoom-img'); - - expect(zoomImg).toBe(null); - done(); - }, 150); - }); - }); -}); \ No newline at end of file diff --git a/tests/index.spec.js b/tests/index.spec.js new file mode 100644 index 0000000..dbc4d95 --- /dev/null +++ b/tests/index.spec.js @@ -0,0 +1,260 @@ +import expect, { createSpy } from 'expect'; +import React from 'react'; +import { Simulate, act, findRenderedDOMComponentWithClass, findRenderedDOMComponentWithTag, scryRenderedDOMComponentsWithTag } from 'react-dom/test-utils'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { SRCS } from './constants/srcs'; +import InnerImageZoom from 'src/'; +import 'src/InnerImageZoom/styles.css'; + +describe('InnerImageZoom', () => { + let node; + + beforeEach(() => { + node = document.createElement('div'); + document.body.appendChild(node); + }); + + afterEach(() => { + document.body.removeChild(node); + unmountComponentAtNode(node); + }); + + const innerImageZoom = (props = {}) => { + return render(, node); + } + + describe('mount', () => { + describe('container', () => { + it('renders a figure', () => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + expect(figure).toExist(); + }); + + it('renders a figure with a custom classname', () => { + const component = innerImageZoom({ className: 'custom' }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + expect(figure.classList.contains('custom')).toBe(true); + }); + }); + + describe('original image', () => { + it('renders the original image', () => { + const component = innerImageZoom(); + const img = findRenderedDOMComponentWithTag(component, 'img'); + expect(img).toExist(); + }); + + it('renders the original image with sources', () => { + const component = innerImageZoom({ sources: SRCS.sources }); + const sources = scryRenderedDOMComponentsWithTag(component, 'source'); + expect(sources.length).toEqual(2); + }); + + it('only renders sources that have srcSet set', () => { + const component = innerImageZoom({ sources: SRCS.invalidSources }); + const sources = scryRenderedDOMComponentsWithTag(component, 'source'); + expect(sources.length).toEqual(1); + }); + }); + }); + + describe('zoom in', () => { + describe('render', () => { + it('renders the zoomed image on mouse enter', () => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + expect(zoomImg).toExist(); + }); + + it('renders the zoomed image with unique src if set', () => { + const component = innerImageZoom({ zoomSrc: SRCS.zoom }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + expect(zoomImg.getAttribute('src')).toEqual('https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?fit=crop&w=1000'); + }); + + it('renders the zoomed image on render if startsActive is true', () => { + const component = innerImageZoom({ startsActive: true }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + expect(zoomImg).toExist(); + }); + }); + + describe('show', () => { + it('makes the zoomed image visible on click', (done) => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + expect(zoomImg.classList.contains('iiz__zoom-img--visible')).toBe(true); + done(); + } + }); + + it('makes the zoomed image visible on mouse enter if zoomType hover is set', (done) => { + const component = innerImageZoom({ zoomType: 'hover' }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + expect(zoomImg.classList.contains('iiz__zoom-img--visible')).toBe(true); + done(); + } + }); + + it('renders the zoomed image in a fullscreen portal if fullscreenOnMobile is set', () => { + global.innerWidth = 500; + global.window.matchMedia = () => { return { matches: true }}; + const component = innerImageZoom({ fullscreenOnMobile: true }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.touchStart(figure); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomPortal = document.querySelector('.iiz__zoom-portal'); + expect(zoomPortal).toExist(); + }); + + it('fires afterZoomIn callback on zoom in', (done) => { + const afterZoomIn = createSpy(); + const component = innerImageZoom({ afterZoomIn: afterZoomIn }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + expect(afterZoomIn).toHaveBeenCalled(); + afterZoomIn.restore(); + done(); + } + }); + }); + }); + + describe('move', () => { + it('pans the zoomed image on mouse move', (done) => { + const component = innerImageZoom({ zoomSrc: SRCS.zoomSrc }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + const topPos = zoomImg.style.top; + Simulate.mouseMove(figure, { pageX: 150, pageY: 150 }); + const updatedTopPos = zoomImg.style.top; + expect(parseInt(topPos, 10)).toNotEqual(parseInt(updatedTopPos, 10)); + done(); + } + }); + }); + + describe('zoom out', () => { + it('hides the zoomed image on toggle click', (done) => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + Simulate.click(figure, { pageX: 100, pageY: 100 }); + expect(zoomImg.classList.contains('iiz__zoom-img--visible')).toBe(false); + done(); + } + }); + + it('hides the zoomed image on mouse leave', (done) => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + Simulate.mouseLeave(figure); + expect(zoomImg.classList.contains('iiz__zoom-img--visible')).toBe(false); + done(); + } + }); + + it('hides the zoomed image on close button click on touch devices', (done) => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.touchStart(figure); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + const button = findRenderedDOMComponentWithTag(component, 'button'); + Simulate.click(button, { pageX: 0, pageY: 0 }); + expect(zoomImg.classList.contains('iiz__zoom-img--visible')).toBe(false); + done(); + } + }); + + it('removes the zoomed image after fade transition', (done) => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + Simulate.mouseLeave(figure); + + setTimeout(() => { + const img = scryRenderedDOMComponentsWithTag(component, 'img'); + expect(img.length).toBe(1); + done(); + }, 150); + } + }); + + it('removes the zoomed image after fade transition on touch devices', (done) => { + const component = innerImageZoom(); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.touchStart(figure); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + const button = findRenderedDOMComponentWithTag(component, 'button'); + Simulate.click(button, { pageX: 0, pageY: 0 }); + + setTimeout(() => { + const img = scryRenderedDOMComponentsWithTag(component, 'img'); + expect(img.length).toBe(1); + done(); + }, 150); + } + }); + + it('fires afterZoomOut callback on zoom out', (done) => { + const afterZoomOut = createSpy(); + const component = innerImageZoom({ afterZoomOut: afterZoomOut }); + const figure = findRenderedDOMComponentWithTag(component, 'figure'); + Simulate.mouseEnter(figure); + Simulate.click(figure, { pageX: 100, pageY: 100 }); + const zoomImg = findRenderedDOMComponentWithClass(component, 'iiz__zoom-img'); + + zoomImg.onload = () => { + Simulate.mouseLeave(figure); + expect(afterZoomOut).toHaveBeenCalled(); + afterZoomOut.restore(); + done(); + } + }); + }); +}); \ No newline at end of file