Skip to content

Commit

Permalink
Adding tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgperry authored and mergatron[bot] committed Nov 11, 2021
1 parent 95fe903 commit 61cfc9e
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 5 deletions.
2 changes: 1 addition & 1 deletion cypress.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"baseUrl": "http://0.0.0.0:9990",
"baseUrl": "http://localhost:9990",
"video": true,
"screenshots": false
}
154 changes: 154 additions & 0 deletions cypress/integration/while-in-view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
describe("whileInView", () => {
it("Animates when an element enters the viewport", () => {
cy.visit("?test=while-in-view")
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(255, 0, 0)"
)
expect($element.innerHTML).to.equal("Out")
})

cy.scrollTo(0, 50)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(0, 255, 0)"
)
expect($element.innerHTML).to.equal("In")
})
})

it("Animates when an element leaves the viewport", () => {
cy.visit("?test=while-in-view")
.wait(50)
.scrollTo(0, 0)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(255, 0, 0)"
)
expect($element.innerHTML).to.equal("Out")
})
})

it("Animates only when all an element enters the viewport and amount='all'", () => {
cy.visit("?test=while-in-view&amount=all")
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(255, 0, 0)"
)
})

cy.scrollTo(0, 50)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(255, 0, 0)"
)
})

cy.scrollTo(0, 150)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(0, 255, 0)"
)
})
})

it("Animates when an element enters the viewport once", () => {
cy.visit("?test=while-in-view&once=true")
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(255, 0, 0)"
)
expect($element.innerHTML).to.equal("Out")
})

cy.scrollTo(0, 50)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(0, 255, 0)"
)
expect($element.innerHTML).to.equal("In")
})

cy.scrollTo(0, 0)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(0, 255, 0)"
)
expect($element.innerHTML).to.equal("In")
})
})

it("Animates when entering a custom root", () => {
cy.visit("?test=while-in-view-custom-root")
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(255, 0, 0)"
)
})
.get("#container")
.scrollTo(500, 0)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(0, 255, 0)"
)
})
.get("#container")
.scrollTo(0, 0)
.wait(50)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(255, 0, 0)"
)
})
})

/**
* Manually verified this does work but headless browser not respecting margin
*/
it.skip("Respects margin", () => {
cy.visit("?test=while-in-view&margin=100px")
.wait(100)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(0, 255, 0)"
)
expect($element.innerHTML).to.equal("In")
})
})

it("If IntersectionObserver doesn't exist, immediately animates to whileInView", () => {
cy.visit("?test=while-in-view&delete=true")
.wait(100)
.get("#box")
.should(([$element]: any) => {
expect($element.style.backgroundColor).to.equal(
"rgb(0, 255, 0)"
)
expect($element.innerHTML).to.equal("In")
})
})
})
27 changes: 27 additions & 0 deletions dev/tests/while-in-view-custom-root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { motion } from "@framer"
import * as React from "react"

export const App = () => {
const containerRef = React.useRef(null)

return (
<div id="container" style={container} ref={containerRef}>
<div style={{ flex: "0 0 400px" }} />
<motion.div
id="box"
initial={false}
transition={{ duration: 0.01 }}
animate={{ background: "rgba(255,0,0,1)" }}
whileInView={{ background: "rgba(0,255,0,1)" }}
viewport={{ root: containerRef }}
style={{ width: 100, height: 100, flexShrink: 0 }}
/>
</div>
)
}

const container = {
width: 300,
overflow: "scroll",
display: "flex",
}
37 changes: 37 additions & 0 deletions dev/tests/while-in-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { motion } from "@framer"
import * as React from "react"

export const App = () => {
const params = new URLSearchParams(window.location.search)
const amount = params.get("amount") || undefined
const once = params.get("once") ? true : undefined
const margin = params.get("margin") || undefined
const deleteObserver = params.get("delete") || undefined
const [inViewport, setInViewport] = React.useState(false)

if (deleteObserver) {
window.IntersectionObserver = undefined
}

return (
<div style={container}>
<motion.div
id="box"
initial={false}
transition={{ duration: 0.01 }}
animate={{ background: "rgba(255,0,0,1)" }}
whileInView={{ background: "rgba(0,255,0,1)" }}
viewport={{ amount, once, margin }}
style={{ width: 100, height: 100 }}
onViewportEnter={() => setInViewport(true)}
onViewportLeave={() => setInViewport(false)}
>
{inViewport ? "In" : "Out"}
</motion.div>
</div>
)
}

const container = {
paddingTop: 700,
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"test-e2e-chrome": "start-server-and-test start-dev-server http://localhost:9990 'cypress run --headless --browser chrome --spec \"cypress/integration/layout-relative.chrome.ts\"'",
"test-e2e-electron": "start-server-and-test start-dev-server http://localhost:9990 'cypress run --headless --config ignoreTestFiles=*.chrome.ts'",
"test-e2e": "yarn test-e2e-chrome && yarn test-e2e-electron",
"test-e2e-file": "start-server-and-test start-dev-server http://localhost:9990 'cypress run --headless --spec \"cypress/integration/drag-framer-page.ts\"'",
"test-e2e-file": "start-server-and-test start-dev-server http://localhost:9990 'cypress run --headless --spec \"cypress/integration/while-in-view.ts\"'",
"test-watch": "jest --watch --coverage --coverageReporters=lcov --config jest.config.json",
"projection-dev": "python -m SimpleHTTPServer",
"collect-projection-tests": "node ./dev/projection/collect-projection-tests.js",
Expand Down
2 changes: 1 addition & 1 deletion src/motion/features/viewport/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { RefObject } from "react"
import { TargetAndTransition } from "../../../types"
import { VariantLabels } from "../../types"

export type ViewportEventHandler = (entry: IntersectionObserverEntry) => void
export type ViewportEventHandler = () => void

export interface ViewportOptions {
root?: RefObject<Element>
Expand Down
8 changes: 6 additions & 2 deletions src/motion/features/viewport/use-viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export function useViewport({
const { animationState } = visualElement

if (typeof IntersectionObserver === "undefined") {
animationState?.setActive(AnimationType.InView, true)
requestAnimationFrame(() => {
onViewportEnter?.()
animationState?.setActive(AnimationType.InView, true)
})

return
}

Expand All @@ -42,7 +46,7 @@ export function useViewport({
const callback = isIntersecting
? onViewportEnter
: onViewportLeave
callback?.(entry)
callback?.()
},
{
root: root?.current,
Expand Down
2 changes: 2 additions & 0 deletions src/render/utils/animation-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type AnimationList = string[] | TargetAndTransition[]

export const variantPriorityOrder = [
AnimationType.Animate,
AnimationType.InView,
AnimationType.Focus,
AnimationType.Hover,
AnimationType.Tap,
Expand Down Expand Up @@ -419,6 +420,7 @@ function createTypeState(isActive = false): AnimationTypeState {
function createState() {
return {
[AnimationType.Animate]: createTypeState(true),
[AnimationType.InView]: createTypeState(),
[AnimationType.Hover]: createTypeState(),
[AnimationType.Tap]: createTypeState(),
[AnimationType.Drag]: createTypeState(),
Expand Down

0 comments on commit 61cfc9e

Please sign in to comment.