Skip to content

Commit 34a1845

Browse files
committed
replace jsdom with happy-dom
1 parent 9e3b2b9 commit 34a1845

File tree

17 files changed

+167
-41
lines changed

17 files changed

+167
-41
lines changed

bun.lock

Lines changed: 15 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bunfig.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[test]
2+
preload = ["./happydom.ts"]
3+
root = "./tests"

package.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"creative coding"
3232
],
3333
"devDependencies": {
34-
"@litecanvas/jsdom-extras": "^2.0.1",
34+
"@happy-dom/global-registrator": "^18.0.1",
3535
"@size-limit/preset-small-lib": "^11.2.0",
3636
"@swc/core": "^1.13.3",
3737
"@types/jsdom": "^21.1.7",
@@ -51,7 +51,7 @@
5151
"scripts": {
5252
"prepare": "npm run build",
5353
"prepublishOnly": "npm test",
54-
"test": "ava --timeout=1s --fast-fail --tap | tap-min",
54+
"test": "ava --tap | tap-min",
5555
"test:watch": "ava --watch",
5656
"dev": "esbuild src/web.js --bundle --watch --outfile=samples/dist.js --servedir=samples",
5757
"build": "npm run genversion && node script/build.js && size-limit",
@@ -66,8 +66,14 @@
6666
],
6767
"ava": {
6868
"files": [
69-
"tests/**/*.js"
70-
]
69+
"tests/**/*.js",
70+
"!tests/_preload/**/*.js"
71+
],
72+
"require": [
73+
"./tests/_preload/happy-dom.js"
74+
],
75+
"failFast": true,
76+
"timeout": "10s"
7177
},
7278
"size-limit": [
7379
{

tests/_preload/happy-dom.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { GlobalRegistrator } from '@happy-dom/global-registrator'
2+
3+
/**
4+
* @param {LitecanvasInstance} instance
5+
* @param {string} event
6+
* @param {Function} callback
7+
* @returns {Promise<Function>}
8+
*/
9+
global.onLitecanvas = function (instance, event, callback) {
10+
return new Promise((resolve) => {
11+
const removeListener = instance.listen(event, (...args) => {
12+
const res = callback(...args)
13+
if (false !== res) {
14+
removeListener()
15+
resolve()
16+
}
17+
})
18+
})
19+
}
20+
21+
GlobalRegistrator.register()
22+
23+
// maybe fix node navigator
24+
if (!global.navigator) {
25+
global.navigator = {}
26+
}
27+
28+
// fake userActivation
29+
global.navigator.userActivation = global.navigator.userActivation || {}
30+
global.navigator.userActivation.hasBeenActive = true
31+
32+
// fake AudioContext
33+
global.AudioContext = class {
34+
createBuffer() {
35+
return {
36+
getChannelData() {
37+
return new Map()
38+
},
39+
}
40+
}
41+
42+
createBufferSource() {
43+
return {
44+
connect() {},
45+
start() {},
46+
}
47+
}
48+
}
49+
50+
// fake AudioBuffer
51+
global.AudioBuffer = class {}
52+
53+
// fake requestAnimationFrame
54+
global.requestAnimationFrame = (callback) => {
55+
return setTimeout(() => {
56+
callback(performance.now())
57+
}, 1000 / 60)
58+
}
59+
60+
// fake cancelAnimationFrame
61+
global.cancelAnimationFrame = (rafId) => {
62+
clearTimeout(rafId)
63+
}
64+
65+
// fake canvas tag
66+
createCanvasTag(window)
67+
68+
/**
69+
* @param {Window & globalThis} window
70+
* @returns {HTMLElement}
71+
*/
72+
function createCanvasTag(window) {
73+
const _createElement = global.window.document.createElement
74+
75+
/**
76+
* @param {string} tagName
77+
* @param {*} options
78+
*/
79+
window.document.createElement = function (tagName, options) {
80+
const el = _createElement.apply(window.document, arguments)
81+
if ('canvas' === tagName.toLowerCase()) {
82+
el.getContext = function (type) {
83+
if (!this.context) {
84+
this.context = createContext2d(this)
85+
}
86+
return this.context
87+
}
88+
el.width = 300
89+
el.height = 150
90+
}
91+
return el
92+
}
93+
}
94+
95+
function createContext2d(canvas) {
96+
const ctx = {
97+
canvas,
98+
99+
fillStyle: '#000000',
100+
font: '10px sans-serif',
101+
globalAlpha: 1,
102+
globalCompositeOperation: 'source-over',
103+
imageSmoothingEnabled: true,
104+
lineDashOffset: 0,
105+
lineWidth: 1,
106+
strokeStyle: '#000000',
107+
textAlign: 'start',
108+
textBaseline: 'alphabetic',
109+
textRendering: 'auto',
110+
}
111+
112+
const fn = () => {}
113+
const methods =
114+
'getContextAttributes,drawImage,beginPath,fill,stroke,clip,isPointInPath,isPointInStroke,createLinearGradient,createRadialGradient,createConicGradient,createPattern,createImageData,getImageData,putImageData,setLineDash,getLineDash,closePath,moveTo,lineTo,quadraticCurveTo,bezierCurveTo,arcTo,rect,roundRect,arc,ellipse,clearRect,fillRect,strokeRect,save,restore,reset,isContextLost,fillText,strokeText,measureText,scale,rotate,translate,transform,getTransform,setTransform,resetTransform,drawFocusIfNeeded'
115+
116+
for (const method of methods.split(',')) {
117+
ctx[method] = fn
118+
}
119+
120+
return ctx
121+
}

tests/cls.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import test from 'ava'
2-
import { setupDOM, onLitecanvas } from '@litecanvas/jsdom-extras'
32
import litecanvas from '../src/index.js'
43
import { defaultPalette as colors } from '../src/palette.js'
54
import * as sinon from 'sinon'
@@ -10,7 +9,6 @@ let /** @type {LitecanvasInstance} */
109
contextSpy
1110

1211
test.before(() => {
13-
setupDOM()
1412
sinon.stub(console) // silent console
1513

1614
local = litecanvas({

tests/events.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import test from 'ava'
2-
import { setupDOM, onLitecanvas } from '@litecanvas/jsdom-extras'
32
import litecanvas from '../src/index.js'
43
import * as sinon from 'sinon'
54

65
/** @type {LitecanvasInstance} */
76
let local
87

98
test.before(() => {
10-
setupDOM()
119
sinon.stub(console) // silent console
1210

1311
local = litecanvas({

tests/math.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import test from 'ava'
2-
import { setupDOM } from '@litecanvas/jsdom-extras'
32
import litecanvas from '../src/index.js'
43
import * as sinon from 'sinon'
54

65
/** @type {LitecanvasInstance} */
76
let local
87

98
test.before(() => {
10-
setupDOM()
119
sinon.stub(console) // silent console
1210

1311
local = litecanvas({

tests/quit.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import test from 'ava'
2-
import { setupDOM } from '@litecanvas/jsdom-extras'
32
import litecanvas from '../src/index.js'
43
import * as sinon from 'sinon'
54

65
test.before(() => {
7-
setupDOM()
86
sinon.stub(console) // silent console
97
})
108

tests/rand.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import test from 'ava'
2-
import { setupDOM } from '@litecanvas/jsdom-extras'
32
import litecanvas from '../src/index.js'
43
import * as sinon from 'sinon'
54

@@ -11,7 +10,6 @@ const MIN = 50
1110
const MAX = 100
1211

1312
test.before(() => {
14-
setupDOM()
1513
sinon.stub(console) // silent console
1614

1715
local = litecanvas({})

tests/randi.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import test from 'ava'
2-
import { setupDOM } from '@litecanvas/jsdom-extras'
32
import litecanvas from '../src/index.js'
43
import * as sinon from 'sinon'
54

@@ -11,7 +10,6 @@ const MIN = 50
1110
const MAX = 100
1211

1312
test.before(() => {
14-
setupDOM()
1513
sinon.stub(console) // silent console
1614

1715
local = litecanvas({})

0 commit comments

Comments
 (0)