diff --git a/test/helpers.js b/test/helpers.js index 28f8509..3d7da9d 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,10 +1,29 @@ +import { fixture, html } from '@open-wc/testing'; + +export function fixtureSidebar() { + return fixture(html` +
+
+ +
+ `) +} + export function nextFrame() { return new Promise((resolve) => requestAnimationFrame(resolve)); } -export async function scrollTo(top) { - window.scrollTo({ top }); - await nextFrame(); +export async function scrollTo(top, options = {}) { + const steps = options.steps || 1; + const delta = top - window.pageYOffset; + + for (let i = 1; i <= steps; i++) { + window.scrollTo({ top: window.pageYOffset + i * delta / steps }); + await nextFrame(); + } + } export function getElementTop(element) { diff --git a/test/side-inner-exceeds-viewport.test.js b/test/side-inner-exceeds-viewport.test.js new file mode 100644 index 0000000..4a94a72 --- /dev/null +++ b/test/side-inner-exceeds-viewport.test.js @@ -0,0 +1,335 @@ +import { setViewport } from '@web/test-runner-commands' +import { expect } from '@open-wc/testing' +import sinon from 'sinon' +import { + scrollTo, + nextFrame, + getElementTop, + getElementBottom, + fixtureSidebar, +} from './helpers.js' +import FloatSidebar from '../src/float-sidebar.js' +import { + START, + TOP_FIXED, + BOTTOM_FIXED, + UNFIXED, + FINISH, +} from '../src/fsm-states.js' + +const VIEWPORT_WIDTH = 1000 +const VIEWPORT_HEIGHT = 1000 + +describe('transitions when height(sideInner) > height(viewport)', () => { + let sidebarInnerHeight, + wrapperElement, + sidebarElement, + sidebarInnerElement, + contentElement, + floatSidebar, + changeStateSpy + + async function forceUpdate() { + floatSidebar.forceUpdate() + await nextFrame() + } + + function setContentHeight(height) { + contentElement.style.height = `${height}px` + } + + function setSidebarInnerHeight(height) { + sidebarInnerElement.style.height = `${height}px` + sidebarInnerHeight = height + } + + function expectTransitionTo(state) { + expect(changeStateSpy).to.have.been.calledOnceWith(state) + changeStateSpy.resetHistory() + } + + function expectNoTransitions() { + expect(changeStateSpy).to.have.callCount(0) + } + + before(async () => { + await setViewport({ width: VIEWPORT_WIDTH, height: VIEWPORT_HEIGHT }) + }) + + beforeEach(async () => { + // Reset the scroll position before each test case. + window.scrollTo({ top: 0 }) + + changeStateSpy = sinon.spy() + + wrapperElement = await fixtureSidebar() + contentElement = wrapperElement.querySelector('.content') + sidebarElement = wrapperElement.querySelector('.sidebar') + sidebarInnerElement = wrapperElement.querySelector('.sidebar__inner') + + floatSidebar = new FloatSidebar({ + sidebar: sidebarElement, + relative: contentElement, + onStateChange: changeStateSpy, + }) + }) + + beforeEach(() => { + setSidebarInnerHeight(VIEWPORT_HEIGHT * 2) + }) + + // isSideInnerWithinPath === false + describe('when height(content) < height(sidebarInner)', () => { + beforeEach(async () => { + setContentHeight(sidebarInnerHeight / 2) + }) + + it('shoult not perform transitions on scroll', async () => { + // An alternative to the smooth scroll. + await scrollTo(document.body.clientHeight, { steps: 50 }) + expectNoTransitions() + }) + }) + + // isSideInnerWithinPath === true + describe('when height(content) > height(sidebarInner)', () => { + beforeEach(async () => { + setContentHeight(sidebarInnerHeight * 1.5) + await nextFrame() + }) + + it('START => BOTTOM_FIXED', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 1 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + }) + + it('START => BOTTOM_FIXED => START when height(content) decreases', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 1 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + setContentHeight(sidebarInnerHeight / 1.5) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => BOTTOM_FIXED => START', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 1 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => BOTTOM_FIXED => TOP_FIXED when height(sidebarInner) decreases', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 1 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + setSidebarInnerHeight(VIEWPORT_HEIGHT / 2) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + }) + + it('START => BOTTOM_FIXED => FINISH', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 1 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(getElementBottom(contentElement) - window.innerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + }) + + it('START => BOTTOM_FIXED => UNFIXED', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + }) + + it('START => BOTTOM_FIXED => UNFIXED => START when height(content) decreases', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + setContentHeight(sidebarInnerHeight / 1.5) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => BOTTOM_FIXED => UNFIXED => START', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(getElementTop(contentElement)) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => BOTTOM_FIXED => UNFIXED => FINISH', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(getElementBottom(contentElement) - window.innerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + }) + + it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(getElementTop(sidebarInnerElement)) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + }) + + it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => UNFIXED', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(getElementTop(sidebarInnerElement)) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + + await scrollTo(window.pageYOffset + 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + }) + + it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => START when height(content) decreases', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(getElementTop(sidebarInnerElement)) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + + setContentHeight(sidebarInnerHeight / 2) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => START', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(getElementTop(sidebarInnerElement)) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => FINISH', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(getElementTop(sidebarInnerElement)) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + + await scrollTo(getElementBottom(contentElement) - window.innerHeight) + await forceUpdate() + expectTransitionTo(FINISH) + }) + + it('START => BOTTOM_FIXED => UNFIXED => BOTTOM_FIXED', async () => { + await scrollTo( + getElementBottom(sidebarInnerElement) - window.innerHeight + 2 + ) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + + await scrollTo(window.pageYOffset - 1) + await forceUpdate() + expectTransitionTo(UNFIXED) + + await scrollTo(window.pageYOffset + 1) + await forceUpdate() + expectTransitionTo(BOTTOM_FIXED) + }) + + it('START => FINISH', async () => { + await scrollTo(getElementBottom(contentElement) - window.innerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + }) + }) +}) diff --git a/test/side-inner-is-within-viewport.test.js b/test/side-inner-is-within-viewport.test.js new file mode 100644 index 0000000..16d07b4 --- /dev/null +++ b/test/side-inner-is-within-viewport.test.js @@ -0,0 +1,177 @@ +import { setViewport } from '@web/test-runner-commands' +import { expect } from '@open-wc/testing' +import sinon from 'sinon' +import { + scrollTo, + nextFrame, + getElementTop, + getElementBottom, + fixtureSidebar +} from './helpers.js' +import FloatSidebar from '../src/float-sidebar.js' +import { START, TOP_FIXED, FINISH } from '../src/fsm-states.js' + +const VIEWPORT_WIDTH = 1000 +const VIEWPORT_HEIGHT = 1000 + +describe('transitions when height(sidebarInner) < height(viewport)', () => { + let sidebarInnerHeight, + wrapperElement, + sidebarElement, + sidebarInnerElement, + contentElement, + floatSidebar, + changeStateSpy + + async function forceUpdate() { + floatSidebar.forceUpdate() + await nextFrame() + } + + function setContentHeight(height) { + contentElement.style.height = `${height}px` + } + + function setSidebarInnerHeight(height) { + sidebarInnerElement.style.height = `${height}px` + sidebarInnerHeight = height + } + + function expectTransitionTo(state) { + expect(changeStateSpy).to.have.been.calledOnceWith(state) + changeStateSpy.resetHistory() + } + + function expectNoTransitions() { + expect(changeStateSpy).to.have.callCount(0) + } + + before(async () => { + await setViewport({ width: VIEWPORT_WIDTH, height: VIEWPORT_HEIGHT }) + }) + + beforeEach(async () => { + // Reset the scroll position before each test case. + window.scrollTo({ top: 0 }) + + changeStateSpy = sinon.spy() + + wrapperElement = await fixtureSidebar() + contentElement = wrapperElement.querySelector('.content') + sidebarElement = wrapperElement.querySelector('.sidebar') + sidebarInnerElement = wrapperElement.querySelector('.sidebar__inner') + + floatSidebar = new FloatSidebar({ + sidebar: sidebarElement, + relative: contentElement, + onStateChange: changeStateSpy, + }) + }) + + beforeEach(() => { + setSidebarInnerHeight(VIEWPORT_HEIGHT / 2) + }) + + // isSideInnerWithinPath === false + describe('when height(content) < height(sidebarInner)', () => { + beforeEach(async () => { + setContentHeight(sidebarInnerHeight / 2) + }) + + it('shoult not perform transitions on scroll', async () => { + // An alternative to the smooth scroll. + await scrollTo(document.body.clientHeight, { steps: 50 }) + expectNoTransitions() + }) + }) + + // isSideInnerWithinPath === true + describe('when height(content) > height(sidebarInner)', () => { + beforeEach(async () => { + setContentHeight(sidebarInnerHeight * 2) + await nextFrame() + }) + + it('START => TOP_FIXED', async () => { + // To catch possible off-by-one errors + await scrollTo(getElementTop(sidebarInnerElement)) + await forceUpdate() + expectNoTransitions() + + await scrollTo(getElementTop(sidebarInnerElement) + 1) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + }) + + it('START => TOP_FIXED => START when height(content) decreases', async () => { + await scrollTo(getElementTop(sidebarInnerElement) + 1) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + + setContentHeight(sidebarInnerHeight / 2) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => TOP_FIXED => START', async () => { + await scrollTo(getElementTop(sidebarInnerElement) + 1) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + + // To catch possible off-by-one errors + await scrollTo(getElementTop(contentElement) + 1) + await forceUpdate() + expectNoTransitions() + + await scrollTo(getElementTop(contentElement)) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => TOP_FIXED => FINISH', async () => { + await scrollTo(getElementTop(sidebarInnerElement) + 1) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + + await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + }) + + it('START => FINISH', async () => { + await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + }) + + it('START => FINISH => START when height(content) decreases', async () => { + await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + + setContentHeight(sidebarInnerHeight / 2) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => FINISH => START', async () => { + await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + + await scrollTo(getElementTop(contentElement)) + await forceUpdate() + expectTransitionTo(START) + }) + + it('START => FINISH => TOP_FIXED', async () => { + await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1) + await forceUpdate() + expectTransitionTo(FINISH) + + await scrollTo(getElementTop(sidebarInnerElement) - 1) + await forceUpdate() + expectTransitionTo(TOP_FIXED) + }) + }) +}) diff --git a/test/sidebar-height.test.js b/test/sidebar-height.test.js index 02fd389..df162f7 100644 --- a/test/sidebar-height.test.js +++ b/test/sidebar-height.test.js @@ -1,68 +1,64 @@ -import { expect, fixture, html } from '@open-wc/testing'; -import { nextFrame } from './helpers.js'; -import FloatSidebar from '../src/float-sidebar.js'; +import { expect } from '@open-wc/testing' +import { nextFrame, fixtureSidebar } from './helpers.js' +import FloatSidebar from '../src/float-sidebar.js' -describe('sidebar height', function() { - let wrapperElement, sidebarElement, sidebarInnerElement, contentElement; - let floatSidebar; +describe('sidebar height', function () { + let wrapperElement, + sidebarElement, + sidebarInnerElement, + contentElement, + floatSidebar async function forceUpdate() { - floatSidebar.forceUpdate(); - await nextFrame(); + floatSidebar.forceUpdate() + await nextFrame() } beforeEach(async () => { - wrapperElement = await fixture(html` -
-
- -
- `); - contentElement = wrapperElement.querySelector('.content'); - sidebarElement = wrapperElement.querySelector('.sidebar'); - sidebarInnerElement = wrapperElement.querySelector('.sidebar__inner'); + wrapperElement = await fixtureSidebar(); + contentElement = wrapperElement.querySelector('.content') + sidebarElement = wrapperElement.querySelector('.sidebar') + sidebarInnerElement = wrapperElement.querySelector('.sidebar__inner') floatSidebar = new FloatSidebar({ sidebar: sidebarElement, - relative: contentElement - }); - }); + relative: contentElement, + }) + }) describe('height(content) > height(sidebarInner)', () => { beforeEach(async () => { - contentElement.style.height = '1000px'; - sidebarInnerElement.style.height = '500px'; - await nextFrame(); - }); + contentElement.style.height = '1000px' + sidebarInnerElement.style.height = '500px' + await nextFrame() + }) it('should set the sidebar height to the content height', () => { - expect(sidebarElement.style.height).to.equal('1000px'); - }); + expect(sidebarElement.style.height).to.equal('1000px') + }) it('should set the sidebar height to the sidebar inner height when it increases', async () => { - sidebarInnerElement.style.height = '2000px'; - await forceUpdate(); - expect(sidebarElement.style.height).to.equal('2000px'); - }); - }); + sidebarInnerElement.style.height = '2000px' + await forceUpdate() + expect(sidebarElement.style.height).to.equal('2000px') + }) + }) describe('height(content) < height(sidebarInner)', () => { beforeEach(async () => { - contentElement.style.height = '500px'; - sidebarInnerElement.style.height = '1000px'; - await nextFrame(); - }); + contentElement.style.height = '500px' + sidebarInnerElement.style.height = '1000px' + await nextFrame() + }) it('should set the sidebar height to the sidebar inner height', () => { - expect(sidebarElement.style.height).to.equal('1000px'); - }); + expect(sidebarElement.style.height).to.equal('1000px') + }) it('should set the sidebar height to the content height when it increases', async () => { - contentElement.style.height = '2000px'; - await forceUpdate(); - expect(sidebarElement.style.height).to.equal('2000px'); - }); - }); -}); + contentElement.style.height = '2000px' + await forceUpdate() + expect(sidebarElement.style.height).to.equal('2000px') + }) + }) +}) diff --git a/test/transitions.test.js b/test/transitions.test.js deleted file mode 100644 index 71d543b..0000000 --- a/test/transitions.test.js +++ /dev/null @@ -1,417 +0,0 @@ -import { setViewport } from '@web/test-runner-commands'; -import { expect, fixture, html } from '@open-wc/testing'; -import sinon from 'sinon'; -import { - scrollTo, - nextFrame, - getElementTop, - getElementBottom -} from './helpers.js'; -import FloatSidebar from '../src/float-sidebar.js'; -import { START, TOP_FIXED, BOTTOM_FIXED, UNFIXED, FINISH } from '../src/fsm-states.js'; - -const VIEWPORT_WIDTH = 1000; -const VIEWPORT_HEIGHT = 1000; - -describe('transitions', function() { - let sidebarInnerHeight; - - let wrapperElement, sidebarElement, sidebarInnerElement, contentElement; - let floatSidebar; - - let changeStateSpy; - - async function forceUpdate() { - floatSidebar.forceUpdate(); - await nextFrame(); - } - - function setContentHeight(height) { - contentElement.style.height = `${height}px`; - } - - function setSidebarInnerHeight(height) { - sidebarInnerElement.style.height = `${height}px`; - sidebarInnerHeight = height; - } - - function expectTransitionTo(state) { - expect(changeStateSpy).to.have.been.calledOnceWith(state); - changeStateSpy.resetHistory(); - } - - function expectNoTransitions() { - expect(changeStateSpy).to.not.have.been.called; - } - - before(async () => { - await setViewport({ width: VIEWPORT_WIDTH, height: VIEWPORT_HEIGHT }); - }); - - beforeEach(async () => { - // Reset the scroll position before each test case. - window.scrollTo({ top: 0 }); - - changeStateSpy = sinon.spy(); - - wrapperElement = await fixture(html` -
-
- -
- `); - contentElement = wrapperElement.querySelector('.content'); - sidebarElement = wrapperElement.querySelector('.sidebar'); - sidebarInnerElement = wrapperElement.querySelector('.sidebar__inner'); - - floatSidebar = new FloatSidebar({ - sidebar: sidebarElement, - relative: contentElement, - onStateChange: changeStateSpy - }); - }); - - // isSideInnerWithinViewport === true - describe('when height(sidebarInner) < height(viewport)', () => { - beforeEach(() => { - setSidebarInnerHeight(VIEWPORT_HEIGHT / 2); - }); - - // isSideInnerWithinPath === false - describe('when height(content) < height(sidebarInner)', () => { - beforeEach(async () => { - setContentHeight(sidebarInnerHeight / 2); - }); - - it('shoult not perform transitions on scroll', async () => { - // An alternative to the smooth scroll. - for (let i = 0; i <= 50; i++) { - await scrollTo(document.body.clientHeight / 50 * i); - await forceUpdate(); - } - expectNoTransitions(); - }); - }); - - // isSideInnerWithinPath === true - describe('when height(content) > height(sidebarInner)', () => { - beforeEach(async () => { - setContentHeight(sidebarInnerHeight * 2); - await nextFrame(); - }); - - it('START => TOP_FIXED', async () => { - await scrollTo(getElementTop(sidebarInnerElement)); - await forceUpdate(); - expectNoTransitions(); - - await scrollTo(getElementTop(sidebarInnerElement) + 1); - await forceUpdate(); - expectTransitionTo(TOP_FIXED) - }); - - it('START => TOP_FIXED => START when height(content) decreases', async () => { - await scrollTo(getElementTop(sidebarInnerElement) + 1); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - - setContentHeight(sidebarInnerHeight / 2); - await forceUpdate(); - expectTransitionTo(START) - }); - - it('START => TOP_FIXED => START', async () => { - await scrollTo(getElementTop(sidebarInnerElement) + 1); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - - await scrollTo(getElementTop(contentElement)); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => TOP_FIXED => FINISH', async () => { - await scrollTo(getElementTop(sidebarInnerElement) + 1); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - - await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - }); - - it('START => FINISH', async () => { - await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - }); - - it('START => FINISH => START when height(content) decreases', async () => { - await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - - setContentHeight(sidebarInnerHeight / 2); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => FINISH => START', async () => { - await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - - await scrollTo(getElementTop(contentElement)); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => FINISH => TOP_FIXED', async () => { - await scrollTo(getElementBottom(contentElement) - sidebarInnerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - - await scrollTo(getElementTop(sidebarInnerElement) - 1); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - }); - }); - }); - - // isSideInnerWithinViewport === false - describe('when height(sidebarInner) > height(viewport)', () => { - beforeEach(() => { - setSidebarInnerHeight(VIEWPORT_HEIGHT * 2); - }); - - // isSideInnerWithinPath === false - describe('when height(content) < height(sidebarInner)', () => { - beforeEach(async () => { - setContentHeight(sidebarInnerHeight / 2); - }); - - it('shoult not perform transitions on scroll', async () => { - // An alternative to the smooth scroll. - for (let i = 0; i <= 50; i++) { - await scrollTo(document.body.clientHeight / 50 * i); - await forceUpdate(); - } - expectNoTransitions(); - }); - }); - - // isSideInnerWithinPath === true - describe('when height(content) > height(sidebarInner)', () => { - beforeEach(async () => { - setContentHeight(sidebarInnerHeight * 1.5); - await nextFrame(); - }); - - it('START => BOTTOM_FIXED', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - }); - - it('START => BOTTOM_FIXED => START when height(content) decreases', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - setContentHeight(sidebarInnerHeight / 1.5); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => BOTTOM_FIXED => START', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => BOTTOM_FIXED => TOP_FIXED when height(sidebarInner) decreases', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - setSidebarInnerHeight(VIEWPORT_HEIGHT / 2); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - }); - - it('START => BOTTOM_FIXED => FINISH', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(getElementBottom(contentElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - }); - - it('START => BOTTOM_FIXED => UNFIXED', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - }); - - it('START => BOTTOM_FIXED => UNFIXED => START when height(content) decreases', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - setContentHeight(sidebarInnerHeight / 1.5); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => BOTTOM_FIXED => UNFIXED => START', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(getElementTop(contentElement)); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => BOTTOM_FIXED => UNFIXED => FINISH', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(getElementBottom(contentElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - }); - - it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(getElementTop(sidebarInnerElement)); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - }); - - it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => UNFIXED', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(getElementTop(sidebarInnerElement)); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - - await scrollTo(window.pageYOffset + 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - }); - - it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => START when height(content) decreases', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(getElementTop(sidebarInnerElement)); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - - setContentHeight(sidebarInnerHeight / 2); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => START', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(getElementTop(sidebarInnerElement)); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(START); - }); - - it('START => BOTTOM_FIXED => UNFIXED => TOP_FIXED => FINISH', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(getElementTop(sidebarInnerElement)); - await forceUpdate(); - expectTransitionTo(TOP_FIXED); - - await scrollTo(getElementBottom(contentElement) - window.innerHeight); - await forceUpdate(); - expectTransitionTo(FINISH); - }); - - it('START => BOTTOM_FIXED => UNFIXED => BOTTOM_FIXED', async () => { - await scrollTo(getElementBottom(sidebarInnerElement) - window.innerHeight + 2); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - - await scrollTo(window.pageYOffset - 1); - await forceUpdate(); - expectTransitionTo(UNFIXED); - - await scrollTo(window.pageYOffset + 1); - await forceUpdate(); - expectTransitionTo(BOTTOM_FIXED); - }); - - it('START => FINISH', async () => { - await scrollTo(getElementBottom(contentElement) - window.innerHeight + 1); - await forceUpdate(); - expectTransitionTo(FINISH); - }); - }); - }); -})