feat: add wooden fish play template

This commit is contained in:
2026-05-21 23:34:07 +08:00
parent ef09a23c35
commit 5b0f9f3763
121 changed files with 11580 additions and 159 deletions

View File

@@ -0,0 +1,71 @@
// @vitest-environment jsdom
import { expect, test } from 'vitest';
import {
applyWoodenFishTap,
chooseWoodenFishFloatingWord,
formatWoodenFishFloatingText,
isWoodenFishFunctionalTarget,
normalizeWoodenFishFloatingWords,
} from './woodenFishRuntimeModel';
test('applyWoodenFishTap creates word counter on first appearance', () => {
const snapshot = applyWoodenFishTap(
{
totalTapCount: 0,
wordCounters: [],
},
'幸运',
);
expect(snapshot).toEqual({
totalTapCount: 1,
wordCounters: [{ text: '幸运', count: 1 }],
});
});
test('applyWoodenFishTap keeps counting repeated and rapid taps', () => {
const first = applyWoodenFishTap(
{
totalTapCount: 0,
wordCounters: [],
},
'功德',
);
const second = applyWoodenFishTap(first, '功德');
const third = applyWoodenFishTap(second, '健康');
expect(third.totalTapCount).toBe(3);
expect(third.wordCounters).toEqual([
{ text: '功德', count: 2 },
{ text: '健康', count: 1 },
]);
});
test('chooseWoodenFishFloatingWord samples normalized words by random index', () => {
expect(chooseWoodenFishFloatingWord(['幸运', '功德'], () => 0.72)).toBe(
'功德',
);
expect(chooseWoodenFishFloatingWord([], () => 0)).toBe('幸运');
});
test('floating word model stores base terms and formats runtime reward text', () => {
expect(normalizeWoodenFishFloatingWords([' 幸运+1 ', '幸运', '健康1'])).toEqual(
['幸运', '健康'],
);
expect(formatWoodenFishFloatingText('幸运')).toBe('幸运+1');
expect(formatWoodenFishFloatingText('功德+1')).toBe('功德+1');
});
test('isWoodenFishFunctionalTarget detects functional controls', () => {
const root = document.createElement('div');
const button = document.createElement('button');
button.dataset.woodenFishFunctional = 'true';
const icon = document.createElement('span');
button.appendChild(icon);
root.appendChild(button);
expect(isWoodenFishFunctionalTarget(icon)).toBe(true);
expect(isWoodenFishFunctionalTarget(root)).toBe(false);
});