Skip to content

Commit

Permalink
Added a test file and bunch of console.log's to help debug issues
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywhy committed Oct 21, 2024
1 parent f5aade1 commit c05ac41
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 22 deletions.
48 changes: 26 additions & 22 deletions src/transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function enter(element, transitionOptions = {}) {
const toClasses = element.dataset.transitionEnterTo || transitionOptions.enterTo || 'enter-to'
const toggleClass = element.dataset.toggleClass || transitionOptions.toggleClass || 'hidden'

return performTransitions(element, {
return performTransitions("enter", element, {
firstFrame() {
element.classList.add(...transitionClasses.split(' '))
element.classList.add(...fromClasses.split(' '))
Expand All @@ -49,7 +49,7 @@ export async function leave(element, transitionOptions = {}) {
const toClasses = element.dataset.transitionLeaveTo || transitionOptions.leaveTo || 'leave-to'
const toggleClass = element.dataset.toggleClass || transitionOptions.toggle || 'hidden'

return performTransitions(element, {
return performTransitions("leave", element, {
firstFrame() {
element.classList.add(...fromClasses.split(' '))
element.classList.remove(...toClasses.split(' '))
Expand All @@ -73,34 +73,34 @@ function setupTransition(element) {
}

export function cancelTransition(element) {
console.log("Canceling")
console.log(`Canceling ${element._stimulus_transition.enterOrLeave}`)
element._stimulus_transition.interrupt()

if(element._stimulus_transition.timeout) {
console.log("Canceling timeout")
clearTimeout(element._stimulus_transition.timeout)
}
console.log(`Done interrupting`)
}

function performTransitions(element, transitionStages) {
console.log("performTransition()")
function performTransitions(type, element, transitionStages) {
console.log(`performTransition() ${type}`)
if (element._stimulus_transition) {
cancelTransition(element)
element._stimulus_transition = null
} else {
console.log("Not cancelling")
console.log(`Not cancelling ${type}`)
}

let interrupted, firstStageComplete, secondStageComplete

setupTransition(element)

// Note: Remove this later
element._stimulus_transition.enterOrLeave = type

element._stimulus_transition.cleanup = () => {
if(! firstStageComplete) {
console.log("Completing first stage")
console.log(`Completing first stage ${type}`)
transitionStages.firstFrame()
}
if(! secondStageComplete) {
console.log("Completing first stage")
console.log(`Completing second stage ${type}`)
transitionStages.secondFrame()
}

Expand All @@ -109,9 +109,13 @@ function performTransitions(element, transitionStages) {
}

element._stimulus_transition.interrupt = () => {
console.log("Interrupting")
element._stimulus_transition.cleanup()
console.log(`Interrupting ${element._stimulus_transition.enterOrLeave}`)
interrupted = true
if(element._stimulus_transition.timeout) {
console.log(`Canceling timeout ${element._stimulus_transition.enterOrLeave}`)
clearTimeout(element._stimulus_transition.timeout)
}
element._stimulus_transition.cleanup()
}


Expand All @@ -120,21 +124,21 @@ function performTransitions(element, transitionStages) {

requestAnimationFrame(() => {
if(interrupted) {
console.log("First frame interrupted")
console.log(`First frame interrupted`)
return
} else {
console.log("First frame")
console.log(`First frame ${element._stimulus_transition.enterOrLeave}`)
}

transitionStages.firstFrame()
firstStageComplete = true

requestAnimationFrame(() => {
if(interrupted) {
console.log("Second frame interrupted")
console.log(`Second frame interrupted`)
return
} else {
console.log("Second frame")
console.log(`Second frame ${element._stimulus_transition.enterOrLeave}`)
}

transitionStages.secondFrame()
Expand All @@ -143,14 +147,14 @@ function performTransitions(element, transitionStages) {
if(element._stimulus_transition) {
element._stimulus_transition.timeout = setTimeout(() => {
if(interrupted) {
console.log("Timeout interrupted")
console.log(`Timeout interrupted ${element._stimulus_transition.enterOrLeave}`)
return
} else {
console.log("Timeout")
console.log(`Timeout ${element._stimulus_transition.enterOrLeave}`)
}

element._stimulus_transition.cleanup()
console.log("End timeout")
console.log(`End timeout`)
resolve()
}, getAnimationDuration(element))
}
Expand Down
87 changes: 87 additions & 0 deletions test/transition_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { html, fixture, expect, nextFrame } from '@open-wc/testing'
import { enter, leave, cancelTransition } from '../src/transition'
import { Application } from '@hotwired/stimulus'
import Popover from '../src/popover'

describe('Transition', () => {
beforeEach(async () => {
await fixture(html`
<div class="inline-block relative cursor-pointer" data-controller="popover" data-action="mouseenter->popover#show mouseleave->popover#hide">
<span class="underline">Hover me</span>
<div class="hidden absolute left-0 bottom-7 w-max bg-white border border-gray-200 shadow rounded p-2"
data-popover-target="content"
data-transition-enter="transition-opacity ease-in-out duration-100"
data-transition-enter-from="opacity-0"
data-transition-enter-to="opacity-100 second-frame"
data-transition-leave="transition-opacity ease-in-out duration-100"
data-transition-leave-from="opacity-100"
data-transition-leave-to="opacity-0"
>
This popover shows on hover
</div>
</div>
`)

const application = Application.start()
application.register('popover', Popover)
})

it('should clean up after a completed transition', async () => {
const target = document.querySelector('[data-popover-target="content"]')

await enter(target, {})

expect(target._stimulus_transition).to.be.null
expect(target.className.includes('hidden')).to.be.false

await leave(target, {})

expect(target.className.includes('hidden')).to.be.true
expect(target.className.includes('transition-opacity')).to.be.false
expect(target.className.includes('ease-in-out')).to.be.false
expect(target._stimulus_transition).to.be.null
})
it('should cancel and clean up when canceled before the first stage', async () => {
const target = document.querySelector('[data-popover-target="content"]')

enter(target, {})
cancelTransition(target)

expect(target.className.includes('second-frame')).to.be.true
expect(target.className.includes('hidden')).to.be.false
expect(target.className.includes('transition-opacity')).to.be.false
expect(target.className.includes('ease-in-out')).to.be.false
expect(target._stimulus_transition).to.be.null
})


it('should cancel and clean up when canceled before second stage', async () => {
const target = document.querySelector('[data-popover-target="content"]')

enter(target, {})
await nextFrame()
cancelTransition(target)

expect(target.className.includes('second-frame')).to.be.true
expect(target.className.includes('hidden')).to.be.false
expect(target.className.includes('transition-opacity')).to.be.false
expect(target.className.includes('ease-in-out')).to.be.false
expect(target._stimulus_transition).to.be.null
})


it('should cancel and clean up when canceled after second stage', async () => {
const target = document.querySelector('[data-popover-target="content"]')

enter(target, {})
await nextFrame()
await nextFrame()
cancelTransition(target)

expect(target.className.includes('second-frame')).to.be.true
expect(target.className.includes('hidden')).to.be.false
expect(target.className.includes('transition-opacity')).to.be.false
expect(target.className.includes('ease-in-out')).to.be.false
expect(target._stimulus_transition).to.be.null
})
})

0 comments on commit c05ac41

Please sign in to comment.