Skip to content

Commit bb0f45d

Browse files
authored
fix: asset selection (#26)
1 parent 9a95830 commit bb0f45d

File tree

12 files changed

+181
-9
lines changed

12 files changed

+181
-9
lines changed

integration-tests/assetStates.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { expect } from '@playwright/test'
2+
3+
export const STATE_AFTER_UPLOAD = [
4+
{
5+
points: [
6+
{
7+
u: 0,
8+
v: 1,
9+
x: 240,
10+
y: 630,
11+
},
12+
{
13+
u: 1,
14+
v: 1,
15+
x: 660,
16+
y: 630,
17+
},
18+
{
19+
u: 1,
20+
v: 0,
21+
x: 660,
22+
y: 70,
23+
},
24+
{
25+
u: 0,
26+
v: 0,
27+
x: 240,
28+
y: 70,
29+
},
30+
],
31+
url: expect.any(String),
32+
},
33+
]

integration-tests/index.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
import initCreator from '../src/index'
22
import SampleImg from './image-sample.png'
33

4+
declare global {
5+
interface Window {
6+
testLastAssetUpdate: {
7+
calledTimes: number
8+
assets: object[] | null
9+
}
10+
}
11+
}
12+
413
const params = new URLSearchParams(document.location.search)
514
const isSampleParam = params.has('sample') // is the string "Jonathan"
615

716
async function test() {
817
const canvas = document.querySelector<HTMLCanvasElement>('canvas')!
18+
19+
const selectedAssetEl = document.querySelector<HTMLSpanElement>('#selected-asset-id')!
20+
const removeAssetBtn = document.querySelector<HTMLSpanElement>('#remove-btn')!
21+
22+
window.testLastAssetUpdate = {
23+
calledTimes: 0,
24+
assets: null,
25+
}
26+
927
const creator = await initCreator(
1028
canvas,
1129
isSampleParam
@@ -41,7 +59,16 @@ async function test() {
4159
},
4260
]
4361
: [],
44-
console.log
62+
(assets) => {
63+
window.testLastAssetUpdate = {
64+
calledTimes: window.testLastAssetUpdate.calledTimes + 1,
65+
assets,
66+
}
67+
console.log(assets)
68+
},
69+
(assetId) => {
70+
selectedAssetEl.textContent = assetId.toString()
71+
}
4572
)
4673

4774
const fileInput = document.querySelector<HTMLInputElement>('input')!
@@ -55,6 +82,10 @@ async function test() {
5582
creator.addImage(img)
5683
}
5784
})
85+
86+
removeAssetBtn.addEventListener('click', () => {
87+
creator.removeAsset()
88+
})
5889
}
5990

6091
test()

integration-tests/template.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
<body>
3232
<aside>
3333
<input type="file" />
34+
<p>Selected asset: <span id="selected-asset-id">0</span></p>
35+
<button id="remove-btn">Remove Asset</button>
3436
</aside>
3537
<canvas></canvas>
3638
</body>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// npx playwright test asset-removal.spec.ts --debug
2+
3+
import { test, expect } from '@playwright/test'
4+
import * as Utils from '../utils'
5+
6+
test('asset removal', async ({ page }, testinfo) => {
7+
if (process.env.CI) {
8+
test.skip()
9+
return
10+
}
11+
12+
testinfo.snapshotSuffix = '' // by default is `process.platform`
13+
14+
const expectLastUpdate = await Utils.init(page)
15+
await Utils.uploadAsset(page)
16+
const canvas = page.locator('canvas')
17+
const removeBtn = page.locator('#remove-btn')
18+
const assetIdEl = page.locator('#selected-asset-id')
19+
20+
// select asset
21+
await page.mouse.move(550, 275)
22+
await page.mouse.down()
23+
await page.mouse.up()
24+
25+
await removeBtn.click()
26+
await expect(canvas).toHaveScreenshot('removed-image.png')
27+
await expect(assetIdEl).toHaveText('0')
28+
29+
await expectLastUpdate(3, [])
30+
})
1.88 KB
Loading
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// npx playwright test asset-selection.spec.ts --debug
2+
3+
import { test, expect } from '@playwright/test'
4+
import * as Utils from '../utils'
5+
import { STATE_AFTER_UPLOAD } from '../assetStates'
6+
7+
test('asset selection', async ({ page }, testinfo) => {
8+
if (process.env.CI) {
9+
test.skip()
10+
return
11+
}
12+
testinfo.snapshotSuffix = '' // by default is `process.platform`
13+
const canvas = page.locator('canvas')
14+
const assetIdEl = page.locator('#selected-asset-id')
15+
16+
const expectLastUpdate = await Utils.init(page)
17+
18+
await expectLastUpdate(0, null)
19+
20+
await Utils.uploadAsset(page)
21+
22+
await page.waitForTimeout(1000) // wait for the upload to happen
23+
await expectLastUpdate(1, STATE_AFTER_UPLOAD)
24+
25+
// no selected by default
26+
await expect(assetIdEl).toHaveText('0')
27+
28+
// no selection after jsut hovering
29+
await page.mouse.move(550, 275)
30+
await page.waitForTimeout(100) // wait for the final result to test not-happy path
31+
await expect(assetIdEl).toHaveText('0')
32+
33+
// hover shouldn't trigger asset update
34+
await expectLastUpdate(1, STATE_AFTER_UPLOAD)
35+
36+
// update once selection happens
37+
await page.mouse.move(550, 275)
38+
await page.mouse.down()
39+
await page.mouse.up()
40+
await expect(canvas).toHaveScreenshot('select-image.png')
41+
await expect(assetIdEl).toHaveText('1000')
42+
await expectLastUpdate(2, STATE_AFTER_UPLOAD)
43+
44+
// update once selections is lost
45+
await page.mouse.move(100, 275)
46+
await page.mouse.down()
47+
await page.mouse.up()
48+
await expect(assetIdEl).toHaveText('0')
49+
50+
// loosing selection shouldn't trigger asset update
51+
await expectLastUpdate(3, STATE_AFTER_UPLOAD)
52+
})

integration-tests/tests/ui-hover.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ test('ui elements get correct highlight on hover', async ({ page }, testinfo) =>
2323
await page.mouse.move(550, 275)
2424
await page.mouse.down()
2525
await page.mouse.up()
26-
await expect(canvas).toHaveScreenshot('select-image.png')
2726

2827
// highlights rotation ui
2928
await page.mouse.move(550, 685)

integration-tests/utils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Page } from '@playwright/test'
22
import path from 'path'
33
import { fileURLToPath } from 'url'
4+
import { expect } from '@playwright/test'
45

56
const PAGE_WIDTH = 1000
67
const PAGE_HEIGHT = 700
@@ -20,6 +21,19 @@ export async function init(page: Page) {
2021
window.addEventListener('mousemove', (e) => console.log(e.clientX, e.clientY))
2122
) // to display cursor position during debugging
2223
// helps to copy position here
24+
25+
async function expectLastUpdate(
26+
numberOfTheUpdate: number,
27+
assetsUpdate: Window['testLastAssetUpdate']['assets']
28+
) {
29+
const testLastAssetUpdate = await page.evaluate(() => window.testLastAssetUpdate)
30+
expect(testLastAssetUpdate).toEqual({
31+
calledTimes: numberOfTheUpdate,
32+
assets: assetsUpdate,
33+
})
34+
}
35+
36+
return expectLastUpdate
2337
}
2438

2539
const __dirname = path.dirname(fileURLToPath(import.meta.url))

src/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
add_asset,
99
remove_asset,
1010
connect_on_asset_update_callback,
11+
connect_on_asset_selection_callback,
1112
destroy_state,
1213
import_icons,
1314
} from './logic/index.zig'
@@ -34,7 +35,8 @@ export interface TextureSource {
3435
export default async function initCreator(
3536
canvas: HTMLCanvasElement,
3637
assets: SerializedAsset[],
37-
onAssetsUpdate: (assets: SerializedAsset[]) => void
38+
onAssetsUpdate: (assets: SerializedAsset[]) => void,
39+
onAssetSelect: (assetId: number) => void
3840
): Promise<CreatorAPI> {
3941
/* setup WebGPU stuff */
4042
const device = await getDevice()
@@ -73,6 +75,8 @@ export default async function initCreator(
7375
onAssetsUpdate(serializedAssetsTextureUrl)
7476
})
7577

78+
connect_on_asset_selection_callback(onAssetSelect)
79+
7680
function addImage(img: HTMLImageElement, points?: PointUV[]) {
7781
const newTextureId = textures.length
7882
textures.push({
@@ -110,13 +114,9 @@ export default async function initCreator(
110114

111115
const stopCreator = runCreator(canvas, context, device, presentationFormat, textures)
112116

113-
function removeAsset() {
114-
remove_asset()
115-
}
116-
117117
return {
118118
addImage,
119-
removeAsset,
119+
removeAsset: remove_asset,
120120
destroy: () => {
121121
stopCreator()
122122
destroy_state()

0 commit comments

Comments
 (0)