mirror of
https://github.com/remorses/gpuix.git
synced 2026-10-28 10:44:49 +08:00
Drop the previous GPU image when src or a live upload replaces it, and when the img node is pruned. Without drop_image, every setImagePixels frame leaked a RenderImage. scrollIntoView now uses the virtual-list logical index, not the windowed child index. A windowStart of 50 plus child 5 now scrolls to item 55. Attach setImage, setImagePixels, and scrollIntoView in getPublicInstance instead of createInstance, so concurrent React can abandon a host node before the methods exist. Pass the original buffer through instead of copying it with Buffer.from. The waveform test compares two live phases. Encoded setImage and windowed scrollIntoView have screenshot and list tests. Session: ses_f3c07efdbffeHwbaQhsE7fIz5z
66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
import fs from 'fs'
|
|
import path from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
import { describe, expect, it } from 'vitest'
|
|
import React from 'react'
|
|
import { createTestRoot, hasNativeTestRenderer } from '@gpuix/react/testing'
|
|
import { WaveformApp } from './waveform'
|
|
|
|
const describeNative = hasNativeTestRenderer ? describe : describe.skip
|
|
const SHOTS = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'screenshots')
|
|
const isCI = !!process.env.CI
|
|
|
|
fs.mkdirSync(SHOTS, { recursive: true })
|
|
|
|
function similarity(a: Buffer, b: Buffer): number {
|
|
const len = Math.max(a.length, b.length)
|
|
if (len === 0) return 1
|
|
let matching = 0
|
|
for (let i = 0; i < len; i++) {
|
|
if (a[i] === b[i]) matching++
|
|
}
|
|
return matching / len
|
|
}
|
|
|
|
describeNative('waveform example', () => {
|
|
it('paints a waveform through setImagePixels', () => {
|
|
const root = createTestRoot({ width: 800, height: 420 })
|
|
const first = path.join(SHOTS, 'waveform-phase-0.png')
|
|
const second = path.join(SHOTS, 'waveform-phase-1.png')
|
|
if (fs.existsSync(first)) fs.unlinkSync(first)
|
|
if (fs.existsSync(second)) fs.unlinkSync(second)
|
|
|
|
root.render(<WaveformApp phase={0} />)
|
|
root.renderer.flush()
|
|
root.renderer.captureScreenshot(first)
|
|
|
|
root.render(<WaveformApp phase={1.2} />)
|
|
root.renderer.flush()
|
|
root.renderer.captureScreenshot(second)
|
|
|
|
expect(fs.statSync(second).size).toBeGreaterThan(0)
|
|
if (!isCI) {
|
|
expect(similarity(fs.readFileSync(first), fs.readFileSync(second))).toBeLessThan(0.99)
|
|
}
|
|
})
|
|
|
|
it('scrolls the last clip into view from the host ref', () => {
|
|
const root = createTestRoot({ width: 800, height: 420 })
|
|
root.render(<WaveformApp />)
|
|
|
|
const list = root.renderer.findByTestId('clip-list')!
|
|
expect(root.renderer.getScrollOffset(list.id)).toEqual([0, 0])
|
|
|
|
const jump = root.renderer.findByTestId('jump-outro')!
|
|
const bounds = root.renderer.getElementBounds(jump.id)!
|
|
root.renderer.nativeSimulateClick(
|
|
bounds.x + bounds.width / 2,
|
|
bounds.y + bounds.height / 2,
|
|
)
|
|
|
|
const offset = root.renderer.getScrollOffset(list.id)
|
|
expect(offset).not.toBeNull()
|
|
expect(offset![1]).toBeLessThan(0)
|
|
})
|
|
})
|