Skip to content

Commit 1d7fcb5

Browse files
committed
Implement CommonJS exports for modules and enhance test setup
- Added CommonJS export statements to board.js, config.js, game.js, pieces.js, and utils.js to facilitate module usage in Node/Jest tests. - Refactored test setup in game-flow.test.js and game-moves.test.js to utilize the newly exported functions, improving clarity and maintainability. - Removed the loadScripts function from tests to streamline the test environment setup.
1 parent 72fbb7e commit 1d7fcb5

File tree

9 files changed

+207
-64
lines changed

9 files changed

+207
-64
lines changed

js/board.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,19 @@ function setPossibleMoves(moves) {
247247
*/
248248
function clearPossibleMoves() {
249249
possibleMoves = [];
250+
}
251+
252+
// Export for Node/Jest tests (CommonJS)
253+
if (typeof module !== 'undefined' && module.exports) {
254+
module.exports = {
255+
boardElement,
256+
createBoard,
257+
renderPieces,
258+
getSquareElement,
259+
updateBoardVisuals,
260+
setSelectedSquare,
261+
clearSelectedSquare,
262+
setPossibleMoves,
263+
clearPossibleMoves
264+
};
250265
}

js/config.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,9 @@ const CONFIG = {
5454

5555
// Debug mode
5656
DEBUG: false,
57-
};
57+
};
58+
59+
// Export for Node/Jest tests (CommonJS)
60+
if (typeof module !== 'undefined' && module.exports) {
61+
module.exports = { CONFIG };
62+
}

js/game.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,4 +898,24 @@ function generateNotationWithDisambiguation(move, boardBefore) {
898898
else if (isKingInCheck(nextPlayer, boardState)) notation += '+';
899899
if (move.isEnPassant) notation += ' e.p.';
900900
return notation;
901+
}
902+
903+
// Export for Node/Jest tests (CommonJS)
904+
if (typeof module !== 'undefined' && module.exports) {
905+
module.exports = {
906+
initializeGame,
907+
handleBoardClick,
908+
makeMove,
909+
resetGame,
910+
generateLegalMovesForPiece,
911+
generateAllLegalMoves,
912+
undoLastMove,
913+
findKingInCheck,
914+
isKingInCheck,
915+
isCheckmate,
916+
isStalemate,
917+
canCastle,
918+
generateNotation,
919+
generateNotationWithDisambiguation
920+
};
901921
}

js/pieces.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,21 @@ function getInitialPieces() {
126126
console.log("Last row (white pieces):", board[7].map(p => p ? p.type : 'null'));
127127

128128
return board;
129+
}
130+
131+
// Export for Node/Jest tests (CommonJS)
132+
if (typeof module !== 'undefined' && module.exports) {
133+
module.exports = {
134+
PAWN,
135+
ROOK,
136+
KNIGHT,
137+
BISHOP,
138+
QUEEN,
139+
KING,
140+
WHITE,
141+
BLACK,
142+
Piece,
143+
isPseudoLegalMove,
144+
getInitialPieces
145+
};
129146
}

js/utils.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,20 @@ function debugLog(...args) {
220220

221221
// Add more utility functions as needed, e.g.,
222222
// - Deep cloning objects/arrays
223-
// - Formatting move history entries
223+
// - Formatting move history entries
224+
225+
// Export for Node/Jest tests (CommonJS)
226+
if (typeof module !== 'undefined' && module.exports) {
227+
module.exports = {
228+
algebraicToCoords,
229+
coordsToAlgebraic,
230+
isWithinBounds,
231+
deepClone,
232+
saveToLocalStorage,
233+
loadFromLocalStorage,
234+
formatSAN,
235+
playSound,
236+
getOppositeColor,
237+
debugLog
238+
};
239+
}

tests/integration/game-flow.test.js

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,7 @@
11
const { JSDOM } = require('jsdom');
2-
const fs = require('fs');
3-
const path = require('path');
4-
5-
function loadScripts(window) {
6-
['js/utils.js', 'js/pieces.js', 'js/board.js', 'js/game.js'].forEach((p) => {
7-
const script = window.document.createElement('script');
8-
script.textContent = fs.readFileSync(path.resolve(p), 'utf-8');
9-
window.document.body.appendChild(script);
10-
});
11-
}
122

133
describe('integration: game flow', () => {
14-
let window;
4+
let window, initializeGame, handleBoardClick;
155

166
beforeEach(() => {
177
const dom = new JSDOM(
@@ -20,20 +10,66 @@ describe('integration: game flow', () => {
2010
<ul id="move-history"></ul>
2111
<div id="game-status"></div>
2212
<button id="reset-button"></button>
13+
<button id="undo-button"></button>
2314
</body>`,
2415
{ url: 'http://localhost' }
2516
);
2617
window = dom.window;
2718
global.window = window;
2819
global.document = window.document;
29-
loadScripts(window);
30-
window.initializeGame();
20+
global.localStorage = window.localStorage;
21+
22+
// Set up globals in dependency order
23+
const config = require('../../js/config');
24+
global.CONFIG = config.CONFIG;
25+
26+
const utils = require('../../js/utils');
27+
global.coordsToAlgebraic = utils.coordsToAlgebraic;
28+
global.algebraicToCoords = utils.algebraicToCoords;
29+
global.isWithinBounds = utils.isWithinBounds;
30+
global.deepClone = utils.deepClone;
31+
global.playSound = utils.playSound;
32+
global.debugLog = utils.debugLog;
33+
34+
const pieces = require('../../js/pieces');
35+
global.PAWN = pieces.PAWN;
36+
global.ROOK = pieces.ROOK;
37+
global.KNIGHT = pieces.KNIGHT;
38+
global.BISHOP = pieces.BISHOP;
39+
global.QUEEN = pieces.QUEEN;
40+
global.KING = pieces.KING;
41+
global.WHITE = pieces.WHITE;
42+
global.BLACK = pieces.BLACK;
43+
global.Piece = pieces.Piece;
44+
global.isPseudoLegalMove = pieces.isPseudoLegalMove;
45+
global.getInitialPieces = pieces.getInitialPieces;
46+
47+
const board = require('../../js/board');
48+
global.boardElement = board.boardElement;
49+
global.createBoard = board.createBoard;
50+
global.renderPieces = board.renderPieces;
51+
global.getSquareElement = board.getSquareElement;
52+
global.updateBoardVisuals = board.updateBoardVisuals;
53+
global.setSelectedSquare = board.setSelectedSquare;
54+
global.clearSelectedSquare = board.clearSelectedSquare;
55+
global.setPossibleMoves = board.setPossibleMoves;
56+
global.clearPossibleMoves = board.clearPossibleMoves;
57+
58+
const game = require('../../js/game');
59+
initializeGame = game.initializeGame;
60+
handleBoardClick = game.handleBoardClick;
61+
62+
// Also attach to window for code that expects window.*
63+
window.initializeGame = initializeGame;
64+
window.handleBoardClick = handleBoardClick;
65+
66+
initializeGame();
3167
});
3268

3369
test('select move updates status and history', () => {
3470
// e2 -> e4 (6,4 to 4,4)
35-
window.handleBoardClick(6, 4);
36-
window.handleBoardClick(4, 4);
71+
handleBoardClick(6, 4);
72+
handleBoardClick(4, 4);
3773
expect(window.document.getElementById('game-status').textContent).toMatch(/Black's turn/);
3874
const items = window.document.querySelectorAll('#move-history li .white-move');
3975
expect(items.length).toBeGreaterThan(0);

tests/unit/game-moves.test.js

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,68 @@
11
const { JSDOM } = require('jsdom');
2-
const fs = require('fs');
3-
const path = require('path');
4-
5-
function loadScripts(window) {
6-
['js/utils.js', 'js/pieces.js', 'js/board.js', 'js/game.js'].forEach((p) => {
7-
const script = window.document.createElement('script');
8-
script.textContent = fs.readFileSync(path.resolve(p), 'utf-8');
9-
window.document.body.appendChild(script);
10-
});
11-
}
122

133
describe('game core', () => {
14-
let window;
4+
let window, initializeGame, handleBoardClick, generateLegalMovesForPiece;
155

166
beforeEach(() => {
17-
const dom = new JSDOM(`<!DOCTYPE html><body><div id="chess-board"></div><ul id="move-history"></ul><div id="game-status"></div><button id="reset-button"></button></body>`, { url: 'http://localhost' });
7+
const dom = new JSDOM(`<!DOCTYPE html><body><div id="chess-board"></div><ul id="move-history"></ul><div id="game-status"></div><button id="reset-button"></button><button id="undo-button"></button></body>`, { url: 'http://localhost' });
188
window = dom.window;
199
global.window = window;
2010
global.document = window.document;
21-
loadScripts(window);
22-
window.initializeGame();
11+
global.localStorage = window.localStorage;
12+
13+
// Set up globals in dependency order
14+
const config = require('../../js/config');
15+
global.CONFIG = config.CONFIG;
16+
17+
const utils = require('../../js/utils');
18+
global.coordsToAlgebraic = utils.coordsToAlgebraic;
19+
global.algebraicToCoords = utils.algebraicToCoords;
20+
global.isWithinBounds = utils.isWithinBounds;
21+
global.deepClone = utils.deepClone;
22+
global.playSound = utils.playSound;
23+
global.debugLog = utils.debugLog;
24+
25+
const pieces = require('../../js/pieces');
26+
global.PAWN = pieces.PAWN;
27+
global.ROOK = pieces.ROOK;
28+
global.KNIGHT = pieces.KNIGHT;
29+
global.BISHOP = pieces.BISHOP;
30+
global.QUEEN = pieces.QUEEN;
31+
global.KING = pieces.KING;
32+
global.WHITE = pieces.WHITE;
33+
global.BLACK = pieces.BLACK;
34+
global.Piece = pieces.Piece;
35+
global.isPseudoLegalMove = pieces.isPseudoLegalMove;
36+
global.getInitialPieces = pieces.getInitialPieces;
37+
38+
const board = require('../../js/board');
39+
global.boardElement = board.boardElement;
40+
global.createBoard = board.createBoard;
41+
global.renderPieces = board.renderPieces;
42+
global.getSquareElement = board.getSquareElement;
43+
global.updateBoardVisuals = board.updateBoardVisuals;
44+
global.setSelectedSquare = board.setSelectedSquare;
45+
global.clearSelectedSquare = board.clearSelectedSquare;
46+
global.setPossibleMoves = board.setPossibleMoves;
47+
global.clearPossibleMoves = board.clearPossibleMoves;
48+
49+
const game = require('../../js/game');
50+
initializeGame = game.initializeGame;
51+
handleBoardClick = game.handleBoardClick;
52+
generateLegalMovesForPiece = game.generateLegalMovesForPiece;
53+
54+
// Also attach to window for code that expects window.*
55+
window.initializeGame = initializeGame;
56+
window.handleBoardClick = handleBoardClick;
57+
window.generateLegalMovesForPiece = generateLegalMovesForPiece;
58+
59+
initializeGame();
2360
});
2461

2562
test('can make a legal opening move', () => {
2663
// e2 -> e4
27-
window.handleBoardClick(6, 4);
28-
const moves = window.generateLegalMovesForPiece(6, 4);
64+
handleBoardClick(6, 4);
65+
const moves = generateLegalMovesForPiece(6, 4);
2966
expect(moves.some((m) => m.row === 4 && m.col === 4)).toBe(true);
3067
});
3168
});

tests/unit/pieces.test.js

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
const { JSDOM } = require('jsdom');
2-
const fs = require('fs');
3-
const path = require('path');
4-
5-
function loadScripts(window) {
6-
['js/utils.js', 'js/pieces.js'].forEach((p) => {
7-
const script = window.document.createElement('script');
8-
script.textContent = fs.readFileSync(path.resolve(p), 'utf-8');
9-
window.document.body.appendChild(script);
10-
});
11-
}
122

133
describe('pieces', () => {
14-
let window;
4+
let getInitialPieces;
155

166
beforeEach(() => {
17-
const dom = new JSDOM(`<!DOCTYPE html><body></body>`);
18-
window = dom.window;
19-
global.window = window;
20-
global.document = window.document;
21-
loadScripts(window);
7+
const dom = new JSDOM(`<!DOCTYPE html><body></body>`, { url: 'http://localhost' });
8+
global.window = dom.window;
9+
global.document = dom.window.document;
10+
11+
// Set up CONFIG and utils globals before requiring pieces
12+
const config = require('../../js/config');
13+
global.CONFIG = config.CONFIG;
14+
const utils = require('../../js/utils');
15+
global.isWithinBounds = utils.isWithinBounds;
16+
17+
// Require pieces module
18+
const pieces = require('../../js/pieces');
19+
getInitialPieces = pieces.getInitialPieces;
2220
});
2321

2422
test('initial pieces count', () => {
25-
const board = window.getInitialPieces();
23+
const board = getInitialPieces();
2624
let count = 0;
2725
for (let r = 0; r < 8; r++) {
2826
for (let c = 0; c < 8; c++) {

tests/unit/utils.test.js

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
const { JSDOM } = require('jsdom');
22

3-
// Load utils.js into jsdom environment
4-
function loadScripts(window) {
5-
const script = window.document.createElement('script');
6-
script.textContent = require('fs').readFileSync(require('path').resolve('js/utils.js'), 'utf-8');
7-
window.document.body.appendChild(script);
8-
}
9-
103
describe('utils', () => {
11-
let window;
4+
let algebraicToCoords, coordsToAlgebraic;
125

136
beforeEach(() => {
147
const dom = new JSDOM(`<!DOCTYPE html><body></body>`, { url: 'http://localhost' });
15-
window = dom.window;
16-
global.window = window;
17-
global.document = window.document;
18-
global.localStorage = window.localStorage;
19-
loadScripts(window);
8+
global.window = dom.window;
9+
global.document = dom.window.document;
10+
global.localStorage = dom.window.localStorage;
11+
12+
// Set up CONFIG global before requiring utils
13+
const config = require('../../js/config');
14+
global.CONFIG = config.CONFIG;
15+
16+
// Require utils module
17+
const utils = require('../../js/utils');
18+
algebraicToCoords = utils.algebraicToCoords;
19+
coordsToAlgebraic = utils.coordsToAlgebraic;
2020
});
2121

2222
test('coordsToAlgebraic and algebraicToCoords round-trip', () => {
23-
const { algebraicToCoords, coordsToAlgebraic } = window;
2423
const positions = ['a1', 'h8', 'e4', 'b7'];
2524
positions.forEach((alg) => {
2625
const c = algebraicToCoords(alg);

0 commit comments

Comments
 (0)