@revoloo/cypress6
Version:
Cypress.io end to end testing tool
169 lines (136 loc) • 4.79 kB
text/typescript
import sinon, { SinonSpy, SinonFakeTimers } from 'sinon'
import scroller from '../../../src/lib/scroller'
const { _ } = Cypress
interface ContainerProps {
clientHeight?: number
scrollHeight?: number
scrollTop?: number
addEventListener?: SinonSpy
}
type TestContainer = Element & {
addEventListener?: SinonSpy
}
const getContainer = (props?: ContainerProps): TestContainer => {
return _.extend<TestContainer>({
clientHeight: 400,
scrollHeight: 900,
scrollTop: 0,
addEventListener: sinon.spy(),
}, props)
}
interface ElementProps {
clientHeight?: number
offsetTop?: number
}
const getElement = (props?: ElementProps): HTMLElement => {
return _.extend<HTMLElement>({
clientHeight: 20,
offsetTop: 150,
}, props)
}
describe('scroller', () => {
let clock: SinonFakeTimers
beforeEach(() => {
clock = sinon.useFakeTimers()
})
beforeEach(() => {
scroller.__reset()
})
it('throws an error if attempting to scroll an element before setting a container', () => {
expect(() => {
return scroller.scrollIntoView({} as HTMLElement)
}).to.throw().and.satisfy((err: Error) => {
expect(err.message).to.match(/container must be set/)
return true
})
})
it('does not scroll if near top and scrolling would result in negative scroll', () => {
const container = getContainer()
scroller.setContainer(container)
scroller.scrollIntoView(getElement({ offsetTop: 0 }))
expect(container.scrollTop).to.equal(0)
})
it('does not scroll if already full visible', () => {
const container = getContainer()
scroller.setContainer(container)
scroller.scrollIntoView(getElement({ offsetTop: 80 }))
expect(container.scrollTop).to.equal(0)
})
it('scrolls to the goal', () => {
const container = getContainer({ scrollTop: 50 })
scroller.setContainer(container)
scroller.scrollIntoView(getElement({ offsetTop: 600 }))
expect(container.scrollTop).to.equal(320)
})
context('#getScrollTop', () => {
it('returns the current scrollTop for the container', () => {
scroller.setContainer(getContainer({ scrollTop: 123 }))
expect(scroller.getScrollTop()).to.equal(123)
})
it('returns 0 if the container is not set', () => {
expect(scroller.getScrollTop()).to.equal(0)
})
})
context('#setScrollTop', () => {
it('sets the scrollTop on the container', () => {
scroller.setContainer(getContainer({ scrollTop: 123 }))
scroller.setScrollTop(456)
expect(scroller.getScrollTop()).to.equal(456)
})
it('does nothing if container is not set', () => {
scroller.setScrollTop(456)
expect(scroller.getScrollTop()).to.equal(0)
})
it('does nothing if value is null', () => {
scroller.setContainer(getContainer({ scrollTop: 123 }))
scroller.setScrollTop(null)
expect(scroller.getScrollTop()).to.equal(123)
})
it('does nothing if value is undefined', () => {
scroller.setContainer(getContainer({ scrollTop: 123 }))
scroller.setScrollTop()
expect(scroller.getScrollTop()).to.equal(123)
})
})
context('scrolling', () => {
it('listens to scroll event on container', () => {
const container = getContainer()
scroller.setContainer(container)
expect(container.addEventListener).to.have.been.calledWith('scroll')
})
it('calls onUserScroll callback if 3 or more user scroll events are detected within 50ms', () => {
const container = getContainer()
const onUserScroll = sinon.spy()
scroller.setContainer(container, onUserScroll)
container.addEventListener.callArg(1)
clock.tick(15)
container.addEventListener.callArg(1)
clock.tick(15)
container.addEventListener.callArg(1)
expect(onUserScroll).to.have.been.called
})
it('does nothing if 50ms passes before 3 user scroll events', () => {
const container = getContainer()
const onUserScroll = sinon.spy()
scroller.setContainer(container, onUserScroll)
container.addEventListener.callArg(1)
container.addEventListener.callArg(1)
clock.tick(50)
container.addEventListener.callArg(1)
expect(onUserScroll).not.to.have.been.called
})
it('does nothing for programmatic scroll events', () => {
const container = getContainer()
const onUserScroll = sinon.spy()
scroller.setContainer(container, onUserScroll)
scroller.scrollIntoView(getElement({ offsetTop: 600 }))
clock.tick(16)
container.addEventListener.callArg(1)
clock.tick(16)
container.addEventListener.callArg(1)
clock.tick(16)
container.addEventListener.callArg(1)
expect(onUserScroll).not.to.have.been.called
})
})
})