Skip to content

Commit 6c0821f

Browse files
test(hikkaku): raise package coverage above 90% (#141)
* test(hikkaku): raise coverage above 90%\n\nCo-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix * fix * fix * fix * fix --------- Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
1 parent f666e59 commit 6c0821f

9 files changed

Lines changed: 503 additions & 7 deletions

File tree

.codecov.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
comment:
2+
layout: "reach, diff, flags, files"
3+
behavior: default
4+
require_changes: false
5+
require_base: true
6+
require_head: true

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
~/.bun/install
2323
~/.moon
2424
~/.turbo
25-
.turbo
25+
**/.turbo
2626
key: ${{ runner.os }}-bun-moonbit-turbo-${{ hashFiles('bun.lock', 'turbo.json', 'package.json') }}
2727
restore-keys: |
2828
${{ runner.os }}-bun-moonbit-turbo-
@@ -58,6 +58,8 @@ jobs:
5858
uses: codecov/codecov-action@v5
5959
with:
6060
token: ${{ secrets.CODECOV_TOKEN }}
61+
name: hikkaku-ci
62+
flags: tests
6163
files: |
6264
packages/hikkaku/coverage/lcov.info
6365
packages/testing/coverage/lcov.info

.github/workflows/pages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
~/.bun/install
3333
~/.moon
3434
~/.turbo
35-
.turbo
35+
**/.turbo
3636
key: ${{ runner.os }}-bun-moonbit-turbo-${{ hashFiles('bun.lock', 'turbo.json', 'package.json') }}
3737
restore-keys: |
3838
${{ runner.os }}-bun-moonbit-turbo-

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
~/.bun/install
5757
~/.moon
5858
~/.turbo
59-
.turbo
59+
**/.turbo
6060
key: ${{ runner.os }}-bun-moonbit-turbo-${{ hashFiles('bun.lock', 'turbo.json', 'package.json') }}
6161
restore-keys: |
6262
${{ runner.os }}-bun-moonbit-turbo-

.github/workflows/ref-sync.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
~/.bun/install
3535
~/.moon
3636
~/.turbo
37-
.turbo
37+
**/.turbo
3838
key: ${{ runner.os }}-bun-moonbit-turbo-${{ hashFiles('bun.lock', 'turbo.json', 'package.json') }}
3939
restore-keys: |
4040
${{ runner.os }}-bun-moonbit-turbo-
Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
import { describe, expect, test } from 'vite-plus/test'
2+
import { block, createBlocks } from '../core/composer'
3+
import type { ListReference, VariableReference } from '../core/types'
4+
import * as control from './control'
5+
import * as data from './data'
6+
import * as events from './events'
7+
import * as looks from './looks'
8+
import * as motion from './motion'
9+
import * as music from './music'
10+
import * as operator from './operator'
11+
import * as pen from './pen'
12+
import * as procedures from './procedures'
13+
import * as sensing from './sensing'
14+
import * as sound from './sound'
15+
16+
const toOpcodes = (blocks: Record<string, { opcode: string }>) => {
17+
return new Set(Object.values(blocks).map((value) => value.opcode))
18+
}
19+
20+
const branch = (condition: boolean, handler: () => void) => {
21+
return [condition, handler] as [boolean, () => void]
22+
}
23+
24+
describe('blocks/coverage-heavy', () => {
25+
test('covers block factories across modules', () => {
26+
const variable: VariableReference = {
27+
id: 'var-score',
28+
name: 'score',
29+
type: 'variable',
30+
}
31+
const list: ListReference = {
32+
id: 'list-items',
33+
name: 'items',
34+
type: 'list',
35+
}
36+
const costumeRef = { type: 'costume', name: 'costume2' } as const
37+
const soundRef = { type: 'sound', name: 'meow' } as const
38+
39+
const blocks = createBlocks(() => {
40+
block('event_whenflagclicked', { topLevel: true })
41+
42+
motion.moveSteps(10)
43+
motion.gotoXY(1, 2)
44+
motion.changeXBy(3)
45+
motion.changeYBy(4)
46+
motion.setX(5)
47+
motion.setY(6)
48+
motion.goTo('Sprite1')
49+
motion.goTo(operator.join('Sprite', '2'))
50+
motion.turnRight(15)
51+
motion.turnLeft(20)
52+
motion.pointInDirection(90)
53+
motion.pointTowards('_mouse_')
54+
motion.pointTowards(operator.join('mouse', ' pointer'))
55+
motion.glide(0.2, 10, 20)
56+
motion.glideTo(0.3, '_random_')
57+
motion.glideTo(0.3, operator.join('Sprite', '3'))
58+
motion.ifOnEdgeBounce()
59+
motion.setRotationStyle('left-right')
60+
looks.say(motion.getX())
61+
looks.say(motion.getY())
62+
looks.say(motion.getDirection())
63+
64+
looks.say('hello')
65+
looks.sayForSecs('hello', 0.5)
66+
looks.think('hmm')
67+
looks.thinkForSecs('hmm', 0.5)
68+
looks.show()
69+
looks.hide()
70+
looks.switchCostumeTo('costume1')
71+
looks.switchCostumeTo(costumeRef)
72+
looks.nextCostume()
73+
looks.switchBackdropTo('backdrop1')
74+
looks.switchBackdropTo(operator.join('backdrop', '2'))
75+
looks.switchBackdropToAndWait('backdrop3')
76+
looks.nextBackdrop()
77+
looks.changeLooksEffectBy('color', 10)
78+
looks.setLooksEffectTo('ghost', 20)
79+
looks.clearGraphicEffects()
80+
looks.changeSizeBy(5)
81+
looks.setSizeTo(120)
82+
looks.goToFrontBack('front')
83+
looks.goForwardBackwardLayers('forward', 1)
84+
looks.say(looks.getSize())
85+
looks.say(looks.getCostumeNumberName('number'))
86+
looks.say(looks.getBackdropNumberName('name'))
87+
88+
sound.playSound('meow')
89+
sound.playSound(soundRef)
90+
sound.playSoundUntilDone('meow')
91+
sound.stopAllSounds()
92+
sound.setSoundEffectTo('pitch', 20)
93+
sound.changeSoundEffectBy('pan', -10)
94+
sound.clearEffects()
95+
sound.setVolumeTo(80)
96+
sound.changeVolumeBy(-5)
97+
looks.say(sound.getVolume())
98+
99+
music.playDrumForBeats(1, 0.25)
100+
music.midiPlayDrumForBeats(36, 0.25)
101+
music.restForBeats(0.5)
102+
music.playNoteForBeats(60, 0.5)
103+
music.setInstrument(2)
104+
music.midiSetInstrument(40)
105+
music.setTempo(120)
106+
music.changeTempo(5)
107+
looks.say(music.getTempo())
108+
109+
pen.eraseAll()
110+
pen.clear()
111+
pen.stamp()
112+
pen.penDown()
113+
pen.penUp()
114+
pen.setPenColorTo('#ff0000')
115+
pen.setPenColorToColor('#00ff00')
116+
pen.changePenColorParamBy('color', 3)
117+
pen.changePenColorParamBy(operator.join('co', 'lor'), 2)
118+
pen.setPenColorParamTo('brightness', 50)
119+
pen.changePenSizeBy(1)
120+
pen.setPenSizeTo(3)
121+
pen.setPenShadeToNumber(20)
122+
pen.changePenShadeBy(5)
123+
pen.setPenHueToNumber(40)
124+
pen.changePenHueBy(10)
125+
126+
looks.say(operator.add(1, 2))
127+
looks.say(operator.subtract(5, 3))
128+
looks.say(operator.multiply(3, 4))
129+
looks.say(operator.divide(10, 2))
130+
control.waitUntil(operator.lt(1, 2))
131+
control.waitUntil(operator.equals(5, 5))
132+
control.waitUntil(operator.gt(3, 2))
133+
control.waitUntil(operator.and(true, false))
134+
control.waitUntil(operator.or(true, false))
135+
control.waitUntil(operator.not(false))
136+
looks.say(operator.random(1, 10))
137+
looks.say(operator.join('a', 'b'))
138+
looks.say(operator.letterOf(1, 'abc'))
139+
looks.say(operator.length('abc'))
140+
control.waitUntil(operator.contains('abc', 'a'))
141+
looks.say(operator.mod(10, 3))
142+
looks.say(operator.round(1.2))
143+
looks.say(operator.mathop('abs', -1))
144+
145+
looks.say(sensing.getMouseX())
146+
looks.say(sensing.getMouseY())
147+
control.waitUntil(sensing.touchingObject('_mouse_'))
148+
control.waitUntil(sensing.touchingColor('#ff00ff'))
149+
control.waitUntil(sensing.colorTouchingColor('#ff0000', '#00ff00'))
150+
looks.say(sensing.distanceTo('_mouse_'))
151+
looks.say(sensing.getTimer())
152+
sensing.resetTimer()
153+
sensing.setDragMode('draggable')
154+
control.waitUntil(sensing.getMouseDown())
155+
control.waitUntil(sensing.getKeyPressed('space'))
156+
looks.say(sensing.current('year'))
157+
looks.say(sensing.getAttributeOf('x position', '_stage_'))
158+
looks.say(sensing.daysSince2000())
159+
looks.say(sensing.getLoudness())
160+
control.waitUntil(sensing.isLoud())
161+
sensing.askAndWait('ready?')
162+
looks.say(sensing.getAnswer())
163+
looks.say(sensing.getUsername())
164+
165+
looks.say(data.getVariable(variable))
166+
data.setVariableTo(variable, 10)
167+
data.changeVariableBy(variable, 1)
168+
data.showVariable(variable)
169+
data.hideVariable(variable)
170+
looks.say(data.getListContents(list))
171+
data.addToList(list, 'apple')
172+
data.deleteOfList(list, 1)
173+
data.deleteAllOfList(list)
174+
data.insertAtList(list, 1, 'banana')
175+
data.replaceItemOfList(list, 1, 'cherry')
176+
looks.say(data.getItemOfList(list, 1))
177+
looks.say(data.getItemNumOfList(list, 'banana'))
178+
looks.say(data.lengthOfList(list))
179+
control.waitUntil(data.listContainsItem(list, 'banana'))
180+
data.showList(list)
181+
data.hideList(list)
182+
183+
events.whenFlagClicked(() => motion.moveSteps(1))
184+
events.whenFlagClicked()
185+
events.whenKeyPressed('space', () => motion.moveSteps(2))
186+
events.whenThisSpriteClicked(() => motion.moveSteps(3))
187+
events.whenStageClicked()
188+
events.whenBackdropSwitchesTo('backdrop1', () => motion.moveSteps(4))
189+
events.whenBroadcastReceived('message1', () => motion.moveSteps(5))
190+
events.whenTouchingObject('_mouse_', () => motion.moveSteps(6))
191+
events.whenGreaterThan('loudness', 10, () => motion.moveSteps(7))
192+
events.broadcast('hello')
193+
events.broadcast(operator.join('hel', 'lo'))
194+
events.broadcastAndWait('world')
195+
events.broadcastAndWait(operator.join('wor', 'ld'))
196+
197+
control.repeat(3, () => motion.moveSteps(1))
198+
control.repeat(3, () => {})
199+
control.repeatUntil(false, () => motion.moveSteps(1))
200+
control.repeatUntil(false, () => {})
201+
control.repeatWhile(true, () => motion.moveSteps(1))
202+
control.repeatWhile(true, () => {})
203+
control.forEach(variable, 5, () => motion.moveSteps(1))
204+
control.forEach(variable, 5, () => {})
205+
control.forever(() => motion.moveSteps(1))
206+
control.forever(() => {})
207+
control.wait(0.1)
208+
control.waitUntil(true)
209+
control.ifThen(true, () => motion.moveSteps(1))
210+
control.ifThen(true, () => {})
211+
control.ifElse(
212+
true,
213+
() => motion.moveSteps(1),
214+
() => motion.moveSteps(2),
215+
)
216+
control.ifElse(
217+
true,
218+
() => {},
219+
() => {},
220+
)
221+
control.match()
222+
control.match(() => {
223+
motion.moveSteps(8)
224+
})
225+
control.match(branch(true, () => motion.moveSteps(9)))
226+
control.match(
227+
branch(false, () => motion.moveSteps(10)),
228+
branch(true, () => motion.moveSteps(11)),
229+
() => motion.moveSteps(12),
230+
)
231+
control.stop('all')
232+
control.createClone(control.CREATE_CLONE_MYSELF)
233+
control.createClone(operator.join('Sprite', '4'))
234+
control.deleteThisClone()
235+
looks.say(control.getCounter())
236+
control.incrCounter()
237+
control.clearCounter()
238+
control.controlStartAsClone(() => motion.moveSteps(13))
239+
control.controlStartAsClone()
240+
control.allAtOnce(() => motion.moveSteps(14))
241+
control.allAtOnce(() => {})
242+
})
243+
244+
const opcodes = toOpcodes(blocks)
245+
expect(opcodes).toContain('motion_glideto')
246+
expect(opcodes).toContain('looks_switchbackdroptoandwait')
247+
expect(opcodes).toContain('sound_changeeffectby')
248+
expect(opcodes).toContain('music_midiSetInstrument')
249+
expect(opcodes).toContain('pen_changePenHueBy')
250+
expect(opcodes).toContain('operator_mathop')
251+
expect(opcodes).toContain('sensing_of')
252+
expect(opcodes).toContain('data_replaceitemoflist')
253+
expect(opcodes).toContain('event_broadcastandwait')
254+
expect(opcodes).toContain('control_all_at_once')
255+
})
256+
257+
test('covers procedure helpers and call styles', () => {
258+
const blocks = createBlocks(() => {
259+
const greet = procedures.defineProcedure(
260+
[
261+
procedures.procedureLabel('greet'),
262+
procedures.procedureBoolean('isLoud'),
263+
procedures.procedureStringOrNumber('name'),
264+
],
265+
({ isLoud, name }) => {
266+
control.ifElse(
267+
isLoud.getter(),
268+
() => looks.say('LOUD'),
269+
() => looks.say(name.getter()),
270+
)
271+
return undefined
272+
},
273+
true,
274+
)
275+
276+
const boolRef = greet.reference.arguments
277+
.isLoud as procedures.ProcedureBooleanReference
278+
const nameRef = greet.reference.arguments
279+
.name as procedures.ProcedureStringOrNumberReference
280+
281+
procedures.callProcedure(greet, [
282+
{ reference: boolRef, value: true },
283+
{ reference: nameRef, value: 'Ada' },
284+
])
285+
procedures.callProcedure(greet.reference, {
286+
[boolRef.id]: false,
287+
[nameRef.id]: 'Bob',
288+
})
289+
procedures.callProcedure(
290+
greet.reference.proccode,
291+
greet.reference.argumentids,
292+
{
293+
[boolRef.id]: true,
294+
[nameRef.id]: 'Cid',
295+
},
296+
false,
297+
)
298+
299+
control.waitUntil(procedures.argumentReporterBoolean(boolRef))
300+
looks.say(procedures.argumentReporterStringNumber(nameRef))
301+
302+
const ping = procedures.defineProcedure([
303+
procedures.procedureLabel('ping'),
304+
])
305+
procedures.callProcedure(
306+
ping.reference.proccode,
307+
ping.reference.argumentids,
308+
)
309+
})
310+
311+
const opcodes = toOpcodes(blocks)
312+
expect(opcodes).toContain('procedures_definition')
313+
expect(opcodes).toContain('procedures_call')
314+
expect(opcodes).toContain('argument_reporter_boolean')
315+
expect(opcodes).toContain('argument_reporter_string_number')
316+
})
317+
})

0 commit comments

Comments
 (0)