1+ // Node.js compatible test runner for extra.js functionality
2+ // Testing Framework: Simple custom test runner (no external dependencies)
3+
4+ // Since this is browser-focused code, we'll create mock implementations for testing
5+ const assert = require ( 'assert' ) ;
6+
7+ // Mock browser APIs
8+ global . document = {
9+ querySelector : ( ) => ( { checked : false , appendChild : ( ) => { } , innerHTML : '' } ) ,
10+ getElementById : ( ) => ( { children : [ ] , appendChild : ( ) => { } , removeChild : ( ) => { } } ) ,
11+ createElement : ( ) => ( { className : '' , style : { } , dataset : { } , innerHTML : '' } ) ,
12+ head : { appendChild : ( ) => { } }
13+ } ;
14+
15+ global . window = {
16+ innerWidth : 1920 ,
17+ innerHeight : 1080 ,
18+ matchMedia : ( ) => ( { matches : false } )
19+ } ;
20+
21+ global . console = { log : ( ) => { } } ;
22+ global . fetch = ( ) => Promise . resolve ( { ok : true } ) ;
23+
24+ // Test configuration constants
25+ const serverip = "localhost" ;
26+ const textures = [
27+ { src : "stone.png" , probability : 0.59 } ,
28+ { src : "copper_ore.png" , probability : 0.128 } ,
29+ { src : "coal_ore.png" , probability : 0.128 } ,
30+ { src : "iron_ore.png" , probability : 0.064 } ,
31+ { src : "lapis_ore.png" , probability : 0.032 } ,
32+ { src : "redstone_ore.png" , probability : 0.032 } ,
33+ { src : "gold_ore.png" , probability : 0.016 } ,
34+ { src : "emerald_ore.png" , probability : 0.008 } ,
35+ { src : "diamond_ore.png" , probability : 0.002 }
36+ ] ;
37+
38+ // Mock selectTexture function
39+ function selectTexture ( ) {
40+ const rand = Math . random ( ) ;
41+ let cumulativeProbability = 0 ;
42+ for ( const texture of textures ) {
43+ cumulativeProbability += texture . probability ;
44+ if ( rand < cumulativeProbability ) {
45+ return texture . src ;
46+ }
47+ }
48+ return "stone.png" ;
49+ }
50+
51+ // Test runner
52+ function runTests ( ) {
53+ console . log ( 'Running Extra.js Node.js Tests...\n' ) ;
54+
55+ // Test 1: Texture array validation
56+ console . log ( '✓ Testing texture array validation' ) ;
57+ assert . strictEqual ( textures . length , 9 , 'Should have 9 textures' ) ;
58+
59+ textures . forEach ( ( texture , index ) => {
60+ assert . ok ( texture . hasOwnProperty ( 'src' ) , `Texture ${ index + 1 } should have src` ) ;
61+ assert . ok ( texture . hasOwnProperty ( 'probability' ) , `Texture ${ index + 1 } should have probability` ) ;
62+ assert . strictEqual ( typeof texture . src , 'string' , `Texture ${ index + 1 } src should be string` ) ;
63+ assert . strictEqual ( typeof texture . probability , 'number' , `Texture ${ index + 1 } probability should be number` ) ;
64+ } ) ;
65+
66+ const totalProbability = textures . reduce ( ( sum , texture ) => sum + texture . probability , 0 ) ;
67+ assert . ok ( Math . abs ( totalProbability - 1.0 ) < 0.001 , 'Total probability should be ~1.0' ) ;
68+
69+ // Test 2: selectTexture function
70+ console . log ( '✓ Testing selectTexture function' ) ;
71+ const originalRandom = Math . random ;
72+
73+ Math . random = ( ) => 0.1 ;
74+ assert . strictEqual ( selectTexture ( ) , 'stone.png' , 'Should select stone for 0.1' ) ;
75+
76+ Math . random = ( ) => 0.65 ;
77+ assert . strictEqual ( selectTexture ( ) , 'copper_ore.png' , 'Should select copper for 0.65' ) ;
78+
79+ Math . random = ( ) => 0.999 ;
80+ assert . strictEqual ( selectTexture ( ) , 'diamond_ore.png' , 'Should select diamond for 0.999' ) ;
81+
82+ Math . random = ( ) => 1.0 ;
83+ assert . strictEqual ( selectTexture ( ) , 'stone.png' , 'Should fallback to stone for 1.0' ) ;
84+
85+ Math . random = originalRandom ;
86+
87+ // Test 3: Configuration constants
88+ console . log ( '✓ Testing configuration constants' ) ;
89+ assert . strictEqual ( serverip , "localhost" , 'Server IP should be localhost' ) ;
90+ assert . strictEqual ( typeof serverip , "string" , 'Server IP should be string' ) ;
91+
92+ // Test 4: Texture probability distribution
93+ console . log ( '✓ Testing texture probability distribution' ) ;
94+ const stoneTexture = textures . find ( t => t . src === 'stone.png' ) ;
95+ assert . strictEqual ( stoneTexture . probability , 0.59 , 'Stone should be most common' ) ;
96+
97+ const diamondTexture = textures . find ( t => t . src === 'diamond_ore.png' ) ;
98+ assert . strictEqual ( diamondTexture . probability , 0.002 , 'Diamond should be rarest' ) ;
99+
100+ // Test 5: Utility function mocks
101+ console . log ( '✓ Testing utility functions' ) ;
102+
103+ function sleep ( ms ) {
104+ return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
105+ }
106+
107+ assert . ok ( sleep ( 100 ) instanceof Promise , 'sleep should return Promise' ) ;
108+
109+ function getTimeoutDuration ( ) {
110+ const mediaQuery = window . matchMedia ( "(prefers-reduced-motion: reduce)" ) ;
111+ return mediaQuery . matches ? 0 : 1000 ;
112+ }
113+
114+ assert . strictEqual ( getTimeoutDuration ( ) , 1000 , 'Should return 1000 for normal motion' ) ;
115+
116+ // Test 6: Error handling
117+ console . log ( '✓ Testing error handling' ) ;
118+
119+ function updateTile ( element ) {
120+ if ( ! element ) return ;
121+ const tile_image = selectTexture ( ) ;
122+ element . style . backgroundImage = `url("images/blocks/${ tile_image } ")` ;
123+ element . dataset . type = tile_image ;
124+ }
125+
126+ // Should not throw for null/undefined
127+ assert . doesNotThrow ( ( ) => updateTile ( null ) , 'Should handle null gracefully' ) ;
128+ assert . doesNotThrow ( ( ) => updateTile ( undefined ) , 'Should handle undefined gracefully' ) ;
129+
130+ console . log ( '\n✅ All tests passed!' ) ;
131+ }
132+
133+ // Run tests if called directly
134+ if ( require . main === module ) {
135+ try {
136+ runTests ( ) ;
137+ } catch ( error ) {
138+ console . error ( '❌ Test failed:' , error . message ) ;
139+ process . exit ( 1 ) ;
140+ }
141+ }
142+
143+ module . exports = { runTests, textures, selectTexture } ;
0 commit comments