Skip to content

Commit 61e3091

Browse files
authored
fix: Add tests, linting, improve output by providing typescript definitions (#2)
* Add integration tests * update screenshot tests and github actions * fix inconsitent screenshots names * update screenshot * Add flag to enable WebGPU on linux * fix issue with zero workers * MORE FLAGS * Try to run webkit instead of chromium * test with gpu checker * fix webkit test run flags * another shot * fix command * try to emulate gpu with CPU * create env file * remove unused screenshots, didsable playwright github action, rename itnegration tests command in package.json * add eslint * Small linting refactor * add typescritp definitions to the output, improve linting
1 parent 7418806 commit 61e3091

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+921
-894
lines changed

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export default tseslint.config(
1010
{
1111
rules: {
1212
"no-multiple-empty-lines": "error",
13+
"semi": ["error", "never"],
1314
},
1415
plugins: {
1516
"@stylistic/js": stylisticJs,

global.d.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,3 @@ declare module "*.png" {
1212
const content: string;
1313
export default content;
1414
}
15-
16-
interface Point {
17-
x: number;
18-
y: number;
19-
}
20-
21-
type Line = [Point, Point];
22-
23-
interface HTMLInputEvent extends Event {
24-
target: HTMLInputElement & EventTarget;
25-
}

integration-tests/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ async function test() {
77

88
const fileInput = document.querySelector<HTMLInputElement>('input')!
99
fileInput.addEventListener('change', (event) => {
10-
const { files } = (event.target as HTMLInputElement);
11-
if (!files) return;
10+
const { files } = (event.target as HTMLInputElement)
11+
if (!files) return
1212

1313
const img = new Image()
14-
img.src = URL.createObjectURL(files[0]);
14+
img.src = URL.createObjectURL(files[0])
1515
img.onload = () => {
1616
creator.addImage(img)
17-
};
17+
}
1818
})
1919

2020
let offset = 100

integration-tests/tests/creator.spec.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import { test, expect } from '@playwright/test';
2-
import path from 'path';
1+
2+
import { test, expect } from '@playwright/test'
3+
import path from 'path'
34

45
test('visible image after upload', async ({ page }, testinfo) => {
56
if (process.env.CI) {
6-
test.skip();
7-
return;
7+
test.skip()
8+
return
89
}
910

10-
testinfo.snapshotSuffix = ''; // by default is `process.platform`
11+
testinfo.snapshotSuffix = '' // by default is `process.platform`
12+
1113
// and it produces different screenshot name base on operating system
1214
// while we want to make app consistent on all operating systems
1315

@@ -17,19 +19,20 @@ test('visible image after upload', async ({ page }, testinfo) => {
1719

1820
await page.goto('http://127.0.0.1:3000')
1921

20-
const fileInput = page.locator('input[type="file"]');
21-
const testImagePath = path.join(__dirname, '../image-sample.png');
22-
await fileInput.setInputFiles(testImagePath);
22+
const fileInput = page.locator('input[type="file"]')
23+
const testImagePath = path.join(__dirname, '../image-sample.png')
24+
await fileInput.setInputFiles(testImagePath)
25+
26+
const canvas = page.locator('canvas')
2327

24-
const canvas = page.locator('canvas');
2528
await expect(canvas).toBeVisible()
2629

2730
await expect(canvas).toHaveScreenshot(['after-upload.png'])
2831

2932
const moveImgBtn = page.locator('#img-position')
3033
await moveImgBtn.click()
3134
await expect(canvas).toHaveScreenshot('after-move.png')
32-
});
35+
})
3336

3437

3538
/*

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"access": "public",
1111
"provenance": true
1212
},
13+
"typings": "./lib/main.d.ts",
1314
"release": {
1415
"branches": [
1516
"main",
@@ -21,7 +22,7 @@
2122
},
2223
"scripts": {
2324
"start": "export NODE_ENV=development && webpack serve --open",
24-
"build": "export $(grep -v '^#' .env | xargs) && export NODE_ENV=production && webpack",
25+
"build": "export $(grep -v '^#' .env | xargs) && export NODE_ENV=production && webpack && tsc --project tsconfig.build.json --emitDeclarationOnly ",
2526
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
2627
"test-e2e": "npx playwright test",
2728
"format": "eslint --fix \"src/**/*.{ts,js}\" \"integration-tests/**/*.{ts,js}\""
@@ -52,7 +53,9 @@
5253
"dependencies": {
5354
"@wasm-tool/wasm-pack-plugin": "^1.7.0"
5455
},
55-
"main": "webpack.config.js",
56+
"types": "dist/index.d.ts",
57+
"main": "dist/index.js",
58+
"module": "dist/index.esm.js",
5659
"repository": {
5760
"type": "git",
5861
"url": "git+ssh://git@github.com/mateuszJS/magic-render.git"
@@ -63,6 +66,6 @@
6366
},
6467
"homepage": "https://github.com/mateuszJS/magic-render#readme",
6568
"files": [
66-
"dist"
69+
"dist/**/*"
6770
]
6871
}

src/WebGPU/canvasSizeObserver.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ function updateCanvasSize(canvas: HTMLCanvasElement, width: number, height: numb
22
canvas.width = Math.max(
33
1,
44
Math.min(width, device.limits.maxTextureDimension2D)
5-
);
5+
)
66
canvas.height = Math.max(
77
1,
88
Math.min(height, device.limits.maxTextureDimension2D)
9-
);
9+
)
1010
}
1111

1212
export default function canvasSizeObserver(
@@ -17,14 +17,14 @@ export default function canvasSizeObserver(
1717
// TODO: should we also handle window.devicePixelRatio; ?
1818
const observer = new ResizeObserver((entries) => {
1919
for (const entry of entries) {
20-
const canvas = entry.target as HTMLCanvasElement;
21-
const width = entry.contentBoxSize[0].inlineSize | 0;
22-
const height = entry.contentBoxSize[0].blockSize | 0;
20+
const canvas = entry.target as HTMLCanvasElement
21+
const width = entry.contentBoxSize[0].inlineSize | 0
22+
const height = entry.contentBoxSize[0].blockSize | 0
2323
updateCanvasSize(canvas, width, height, device)
2424
callback()
2525
}
26-
});
27-
observer.observe(canvas);
26+
})
27+
observer.observe(canvas)
2828

2929
// observer calls it anyway but it just happens late enough that user see a flicker
3030
updateCanvasSize(canvas, canvas.clientWidth, canvas.clientHeight, device)

src/WebGPU/getDevice.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
export default async function getDevice() {
22
if (!navigator.gpu) {
3-
throw Error("this browser does not support WebGPU");
3+
throw Error("this browser does not support WebGPU")
44
}
55

6-
const adapter = await navigator.gpu.requestAdapter();
6+
const adapter = await navigator.gpu.requestAdapter()
77

88

99
if (!adapter) {
10-
throw Error("this browser supports webgpu but it appears disabled");
10+
throw Error("this browser supports webgpu but it appears disabled")
1111
}
1212

13-
const device = await adapter.requestDevice();
13+
const device = await adapter.requestDevice()
1414
device.lost.then((info) => {
15-
console.error(`WebGPU device was lost: ${info.message}`);
15+
console.error(`WebGPU device was lost: ${info.message}`)
1616

1717
if (info.reason !== "destroyed") {
1818
// reprot issue to the tracking system
1919
// getDevice(callback);
2020
}
21-
});
21+
})
2222

2323
return device
2424
}

src/WebGPU/getTexture/createCheckedImageData.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ const FAKE_MIPMAPS_COLORS = [
1313
'#FFBC00',
1414
]
1515

16-
const ctx = document.createElement('canvas').getContext('2d', {willReadFrequently: true})!;
16+
const ctx = document.createElement('canvas').getContext('2d', {willReadFrequently: true})!
1717

1818
export default function createCheckedImageData(size: number, index: number): ImageData {
19-
ctx.canvas.width = size;
20-
ctx.canvas.height = size;
21-
ctx.fillStyle = index & 1 ? '#000' : '#fff';
22-
ctx.fillRect(0, 0, size, size);
23-
ctx.fillStyle = FAKE_MIPMAPS_COLORS[index % FAKE_MIPMAPS_COLORS.length];
24-
ctx.fillRect(0, 0, size / 2, size / 2);
25-
ctx.fillRect(size / 2, size / 2, size / 2, size / 2);
19+
ctx.canvas.width = size
20+
ctx.canvas.height = size
21+
ctx.fillStyle = index & 1 ? '#000' : '#fff'
22+
ctx.fillRect(0, 0, size, size)
23+
ctx.fillStyle = FAKE_MIPMAPS_COLORS[index % FAKE_MIPMAPS_COLORS.length]
24+
ctx.fillRect(0, 0, size / 2, size / 2)
25+
ctx.fillRect(size / 2, size / 2, size / 2, size / 2)
2626

27-
ctx.fillStyle = index & 1 ? '#FFFFFF' : '#000000';
28-
ctx.font = `${size * 0.3}px serif`;
27+
ctx.fillStyle = index & 1 ? '#FFFFFF' : '#000000'
28+
ctx.font = `${size * 0.3}px serif`
2929
ctx.textAlign = 'center'
3030
ctx.textBaseline = 'middle'
3131
;[
@@ -34,9 +34,9 @@ export default function createCheckedImageData(size: number, index: number): Ima
3434
{ x: 0.75, y: 0.75 },
3535
{ x: 0.75, y: 0.25 },
3636
].forEach(p => {
37-
ctx.fillText(index.toString(), p.x * size, p.y * size);
37+
ctx.fillText(index.toString(), p.x * size, p.y * size)
3838
})
3939

4040

41-
return ctx.getImageData(0, 0, size, size);
42-
};
41+
return ctx.getImageData(0, 0, size, size)
42+
}

src/WebGPU/getTexture/generateMimapsArray.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ export default function generateMips(
5151
return textureSample(ourTexture, ourSampler, fsInput.texcoord, 0);
5252
}
5353
`,
54-
});
54+
})
5555

5656
sampler = device.createSampler({
5757
minFilter: 'linear',
5858
magFilter: 'linear',
59-
});
59+
})
6060
}
6161

6262
if (!pipelineByFormat[texture.format]) {
@@ -72,30 +72,30 @@ export default function generateMips(
7272
entryPoint: 'fs',
7373
targets: [{ format: texture.format }],
7474
},
75-
});
75+
})
7676
}
77-
const pipeline = pipelineByFormat[texture.format]!;
77+
const pipeline = pipelineByFormat[texture.format]!
7878

7979
const encoder = device.createCommandEncoder({
8080
label: 'mip gen encoder',
81-
});
81+
})
8282

83-
let width = texture.width;
84-
let height = texture.height;
85-
let baseMipLevel = 0;
83+
let width = texture.width
84+
let height = texture.height
85+
let baseMipLevel = 0
8686
while (width > 1 || height > 1) {
87-
width = Math.max(1, width / 2 | 0);
88-
height = Math.max(1, height / 2 | 0);
87+
width = Math.max(1, width / 2 | 0)
88+
height = Math.max(1, height / 2 | 0)
8989

9090
const bindGroup = device.createBindGroup({
9191
layout: pipeline.getBindGroupLayout(0),
9292
entries: [
9393
{ binding: 0, resource: sampler },
9494
{ binding: 1, resource: texture.createView({baseMipLevel, mipLevelCount: 1, ...textureOptions}) },
9595
],
96-
});
96+
})
9797

98-
++baseMipLevel;
98+
++baseMipLevel
9999

100100
// jsut testign if mipmaps are correctly using previous mimap to render next one
101101
// if (baseMipLevel === 3) {
@@ -118,15 +118,15 @@ export default function generateMips(
118118
storeOp: 'store',
119119
},
120120
],
121-
} as const;
121+
} as const
122122

123-
const pass = encoder.beginRenderPass(renderPassDescriptor);
124-
pass.setPipeline(pipeline);
125-
pass.setBindGroup(0, bindGroup);
126-
pass.draw(6); // call our vertex shader 6 times
127-
pass.end();
123+
const pass = encoder.beginRenderPass(renderPassDescriptor)
124+
pass.setPipeline(pipeline)
125+
pass.setBindGroup(0, bindGroup)
126+
pass.draw(6) // call our vertex shader 6 times
127+
pass.end()
128128
}
129129

130-
const commandBuffer = encoder.finish();
131-
device.queue.submit([commandBuffer]);
132-
};
130+
const commandBuffer = encoder.finish()
131+
device.queue.submit([commandBuffer])
132+
}

0 commit comments

Comments
 (0)