Skip to content

Commit

Permalink
Add tests and a cleanup function
Browse files Browse the repository at this point in the history
  • Loading branch information
danil.radkovskyi committed Jul 17, 2024
1 parent 792274f commit d53d457
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
16 changes: 11 additions & 5 deletions src/elements/play-pen/play-pen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import {
emptyAssetsState,
PlayAssets
} from '../play-assets/play-assets.js'
import {debounce} from '../../utils/debounce.js'
import {debounce, type DebounceCleanupFn} from '../../utils/debounce.js'

declare global {
interface HTMLElementTagNameMap {
Expand All @@ -74,9 +74,7 @@ declare global {
export class PlayPen extends LitElement {
static override readonly styles: CSSResultGroup = css`
${cssReset}
${unsafeCSS(penVars)}
:host {
/* Light mode. */
color: var(--color-foreground);
Expand Down Expand Up @@ -118,6 +116,7 @@ export class PlayPen extends LitElement {
}
/* Makes dropdowns appear over other content */
play-pen-header,
play-pen-footer {
z-index: var(--z-menu);
Expand Down Expand Up @@ -181,6 +180,8 @@ export class PlayPen extends LitElement {
private _src: string | undefined
#template?: boolean

#cleanupDelayedSideEffects: DebounceCleanupFn = () => {}

override connectedCallback(): void {
super.connectedCallback()

Expand Down Expand Up @@ -218,6 +219,11 @@ export class PlayPen extends LitElement {
this.#setName(pen.name, false)
}

override disconnectedCallback() {
this.#cleanupDelayedSideEffects()
super.disconnectedCallback()
}

protected override render(): TemplateResult {
return html`
<play-assets
Expand Down Expand Up @@ -440,10 +446,10 @@ export class PlayPen extends LitElement {
appEntrypointFilename
)
}
this.#setSrcSideEffects(save)
this.#cleanupDelayedSideEffects = this.#setSrcSideEffects(save)
}

/** Throttled changes after updating sources. */
/** Debounced changes after updating sources. */
#setSrcSideEffects = debounce((save: boolean): void => {
this.#version++
this._bundle = link(
Expand Down
18 changes: 17 additions & 1 deletion src/utils/debounce.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {debounce} from './debounce.js'
import {expect, it, describe} from 'vitest'
import {expect, it, describe, vi} from 'vitest'

describe('debounce', () => {
it('executes with a delay', async () => {
Expand All @@ -11,13 +11,18 @@ describe('debounce', () => {
await new Promise(resolve => setTimeout(resolve, 100))
expect(out.val).toBe(1)
})

it('executes the last call of a series', async () => {
const out = {val: 0}
const fn = debounce((val: number) => (out.val = val), 100)
fn(1)
await new Promise(resolve => setTimeout(resolve, 0))
expect(out.val).toBe(0)

fn(2)
await new Promise(resolve => setTimeout(resolve, 0))
expect(out.val).toBe(0)

fn(3)
await new Promise(resolve => setTimeout(resolve, 100))
expect(out.val).toBe(3)
Expand All @@ -26,4 +31,15 @@ describe('debounce', () => {
await new Promise(resolve => setTimeout(resolve, 100))
expect(out.val).toBe(4)
})

it('has a cleanup function that cancels the delayed execution', async () => {
const innerFn = vi.fn()
const debouncedFn = debounce(innerFn, 1000)
const cleanupFn = debouncedFn(1)
await new Promise(resolve => setTimeout(resolve, 0))
expect(innerFn).toBeCalledTimes(0)
cleanupFn()
await new Promise(resolve => setTimeout(resolve, 1000))
expect(innerFn).toBeCalledTimes(0)
})
})
7 changes: 6 additions & 1 deletion src/utils/debounce.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
/** Delay function execution until after the invocations stopped. */
export type DebounceCleanupFn = () => void

export const debounce = <T extends unknown[]>(
fn: (...args: T) => void,
period: number
): ((...args: T) => void) => {
): ((...args: T) => DebounceCleanupFn) => {
let timeout: ReturnType<typeof setTimeout> | undefined
return (...args: T) => {
clearTimeout(timeout)
timeout = setTimeout(() => {
fn(...args)
}, period)
return () => {
clearTimeout(timeout)
}
}
}

0 comments on commit d53d457

Please sign in to comment.