diff --git a/app/controllers/break_escape/static_files_controller.rb b/app/controllers/break_escape/static_files_controller.rb
index f076c69..4862b70 100644
--- a/app/controllers/break_escape/static_files_controller.rb
+++ b/app/controllers/break_escape/static_files_controller.rb
@@ -20,6 +20,9 @@ module BreakEscape
engine_root.join('public', 'break_escape', 'assets', params[:path])
when %r{^/break_escape/stylesheets/}
engine_root.join('public', 'break_escape', 'css', params[:path])
+ when %r{^/break_escape/.*\.html$}
+ # HTML test files like /break_escape/test-assets.html
+ engine_root.join('public', 'break_escape', "#{params[:filename]}.html")
else
# Fallback for any other pattern
engine_root.join('public', 'break_escape', params[:path])
@@ -47,6 +50,8 @@ module BreakEscape
def determine_content_type(file_path)
case File.extname(file_path).downcase
+ when '.html'
+ 'text/html'
when '.css'
'text/css'
when '.js'
diff --git a/config/routes.rb b/config/routes.rb
index 143ab4e..0cabd09 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,10 +1,12 @@
BreakEscape::Engine.routes.draw do
- # Static files - match only static file paths (must come BEFORE resource routes)
- # Note: These routes are automatically prefixed with /break_escape by the mount in the parent app
+ # Static files - caught by routes and served by lightweight controller
+ # This ensures files are served from the engine's public directory
+ # Constraint { path: /.*/ } ensures we capture the full path including filename with extension
get '/css/*path', to: 'static_files#serve', constraints: { path: /.*/ }
get '/js/*path', to: 'static_files#serve', constraints: { path: /.*/ }
get '/assets/*path', to: 'static_files#serve', constraints: { path: /.*/ }
get '/stylesheets/*path', to: 'static_files#serve', constraints: { path: /.*/ }
+ get '/:filename.html', to: 'static_files#serve', constraints: { filename: /test-.*|index/ }
# Mission selection
resources :missions, only: [:index, :show]
diff --git a/public/break_escape/js/core/game.js b/public/break_escape/js/core/game.js
index 8cd3b2c..e94b591 100644
--- a/public/break_escape/js/core/game.js
+++ b/public/break_escape/js/core/game.js
@@ -29,372 +29,372 @@ export function preload() {
document.getElementById('loading').style.display = 'block';
// Load tilemap files and regular tilesets first
- this.load.tilemapTiledJSON('room_reception', 'assets/rooms/room_reception2.json');
- this.load.tilemapTiledJSON('room_office', 'assets/rooms/room_office2.json');
- this.load.tilemapTiledJSON('room_ceo', 'assets/rooms/room_ceo2.json');
- this.load.tilemapTiledJSON('room_closet', 'assets/rooms/room_closet2.json');
- this.load.tilemapTiledJSON('room_servers', 'assets/rooms/room_servers2.json');
+ this.load.tilemapTiledJSON('room_reception', 'rooms/room_reception2.json');
+ this.load.tilemapTiledJSON('room_office', 'rooms/room_office2.json');
+ this.load.tilemapTiledJSON('room_ceo', 'rooms/room_ceo2.json');
+ this.load.tilemapTiledJSON('room_closet', 'rooms/room_closet2.json');
+ this.load.tilemapTiledJSON('room_servers', 'rooms/room_servers2.json');
// Load new variable-sized rooms for grid system
- this.load.tilemapTiledJSON('small_room_1x1gu', 'assets/rooms/small_room_1x1gu.json');
- this.load.tilemapTiledJSON('hall_1x2gu', 'assets/rooms/hall_1x2gu.json');
+ this.load.tilemapTiledJSON('small_room_1x1gu', 'rooms/small_room_1x1gu.json');
+ this.load.tilemapTiledJSON('hall_1x2gu', 'rooms/hall_1x2gu.json');
// Load room images (now using smaller 32px scale images)
- this.load.image('room_reception', 'assets/tiles/rooms/room1.png');
- this.load.image('room18', 'assets/tiles/rooms/room18.png');
- this.load.image('room6', 'assets/tiles/rooms/room6.png');
- this.load.image('room14', 'assets/tiles/rooms/room14.png');
- this.load.image('room19', 'assets/tiles/rooms/room19.png');
- this.load.image('door_32', 'assets/tiles/door_32.png');
- this.load.spritesheet('door_sheet', 'assets/tiles/door_sheet_32.png', {
+ this.load.image('room_reception', 'tiles/rooms/room1.png');
+ this.load.image('room18', 'tiles/rooms/room18.png');
+ this.load.image('room6', 'tiles/rooms/room6.png');
+ this.load.image('room14', 'tiles/rooms/room14.png');
+ this.load.image('room19', 'tiles/rooms/room19.png');
+ this.load.image('door_32', 'tiles/door_32.png');
+ this.load.spritesheet('door_sheet', 'tiles/door_sheet_32.png', {
frameWidth: 32,
frameHeight: 64
});
// Load tileset images referenced by the new Tiled map
- this.load.image('office-updated', 'assets/tiles/rooms/room1.png');
- this.load.image('door_sheet_32', 'assets/tiles/door_sheet_32.png');
+ this.load.image('office-updated', 'tiles/rooms/room1.png');
+ this.load.image('door_sheet_32', 'tiles/door_sheet_32.png');
// Load side door spritesheet for east/west doors (6 frames: closed, opening, open, etc.)
- this.load.spritesheet('door_side_sheet_32', 'assets/tiles/door_side_sheet_32.png', {
+ this.load.spritesheet('door_side_sheet_32', 'tiles/door_side_sheet_32.png', {
frameWidth: 32,
frameHeight: 32
});
// Load table tileset images
- this.load.image('desk-ceo1', 'assets/tables/desk-ceo1.png');
- this.load.image('desk-ceo2', 'assets/tables/desk-ceo2.png');
- this.load.image('desk1', 'assets/tables/desk1.png');
- this.load.image('smalldesk1', 'assets/tables/smalldesk1.png');
- this.load.image('smalldesk2', 'assets/tables/smalldesk2.png');
- this.load.image('reception_table1', 'assets/tables/reception_table1.png');
+ this.load.image('desk-ceo1', 'tables/desk-ceo1.png');
+ this.load.image('desk-ceo2', 'tables/desk-ceo2.png');
+ this.load.image('desk1', 'tables/desk1.png');
+ this.load.image('smalldesk1', 'tables/smalldesk1.png');
+ this.load.image('smalldesk2', 'tables/smalldesk2.png');
+ this.load.image('reception_table1', 'tables/reception_table1.png');
// Load object sprites - keeping existing ones for backward compatibility
- this.load.image('pc', 'assets/objects/pc1.png');
- this.load.image('key', 'assets/objects/key.png');
- this.load.image('notes', 'assets/objects/notes1.png');
- this.load.image('phone', 'assets/objects/phone1.png');
- this.load.image('suitcase', 'assets/objects/suitcase-1.png');
- this.load.image('smartscreen', 'assets/objects/smartscreen.png');
- this.load.image('photo', 'assets/objects/picture1.png');
- this.load.image('safe', 'assets/objects/safe1.png');
- this.load.image('book', 'assets/objects/book1.png');
- this.load.image('workstation', 'assets/objects/workstation.png');
- this.load.image('bluetooth_scanner', 'assets/objects/bluetooth_scanner.png');
- this.load.image('bluetooth', 'assets/objects/bluetooth.png');
- this.load.image('tablet', 'assets/objects/tablet.png');
- this.load.image('fingerprint', 'assets/objects/fingerprint_small.png');
- this.load.image('lockpick', 'assets/objects/lockpick.png');
- this.load.image('spoofing_kit', 'assets/objects/office-misc-headphones.png');
- this.load.image('keyway', 'assets/icons/keyway.png');
- this.load.image('password', 'assets/icons/password.png');
- this.load.image('pin', 'assets/icons/pin.png');
- this.load.image('talk', 'assets/icons/talk.png');
+ this.load.image('pc', 'objects/pc1.png');
+ this.load.image('key', 'objects/key.png');
+ this.load.image('notes', 'objects/notes1.png');
+ this.load.image('phone', 'objects/phone1.png');
+ this.load.image('suitcase', 'objects/suitcase-1.png');
+ this.load.image('smartscreen', 'objects/smartscreen.png');
+ this.load.image('photo', 'objects/picture1.png');
+ this.load.image('safe', 'objects/safe1.png');
+ this.load.image('book', 'objects/book1.png');
+ this.load.image('workstation', 'objects/workstation.png');
+ this.load.image('bluetooth_scanner', 'objects/bluetooth_scanner.png');
+ this.load.image('bluetooth', 'objects/bluetooth.png');
+ this.load.image('tablet', 'objects/tablet.png');
+ this.load.image('fingerprint', 'objects/fingerprint_small.png');
+ this.load.image('lockpick', 'objects/lockpick.png');
+ this.load.image('spoofing_kit', 'objects/office-misc-headphones.png');
+ this.load.image('keyway', 'icons/keyway.png');
+ this.load.image('password', 'icons/password.png');
+ this.load.image('pin', 'icons/pin.png');
+ this.load.image('talk', 'icons/talk.png');
// Load RFID keycard and cloner assets
- this.load.image('keycard', 'assets/objects/keycard.png');
- this.load.image('keycard-ceo', 'assets/objects/keycard-ceo.png');
- this.load.image('keycard-security', 'assets/objects/keycard-security.png');
- this.load.image('keycard-maintenance', 'assets/objects/keycard-maintenance.png');
- this.load.image('rfid_cloner', 'assets/objects/rfid_cloner.png');
- this.load.image('rfid-icon', 'assets/icons/rfid-icon.png');
- this.load.image('nfc-waves', 'assets/icons/nfc-waves.png');
+ this.load.image('keycard', 'objects/keycard.png');
+ this.load.image('keycard-ceo', 'objects/keycard-ceo.png');
+ this.load.image('keycard-security', 'objects/keycard-security.png');
+ this.load.image('keycard-maintenance', 'objects/keycard-maintenance.png');
+ this.load.image('rfid_cloner', 'objects/rfid_cloner.png');
+ this.load.image('rfid-icon', 'icons/rfid-icon.png');
+ this.load.image('nfc-waves', 'icons/nfc-waves.png');
// Load new object sprites from Tiled map tileset
// These are the key objects that appear in the new room_reception2.json
- this.load.image('fingerprint_kit', 'assets/objects/fingerprint_kit.png');
- this.load.image('pin-cracker', 'assets/objects/pin-cracker.png');
- this.load.image('bin11', 'assets/objects/bin11.png');
- this.load.image('bin10', 'assets/objects/bin10.png');
- this.load.image('bin9', 'assets/objects/bin9.png');
- this.load.image('bin8', 'assets/objects/bin8.png');
- this.load.image('bin7', 'assets/objects/bin7.png');
- this.load.image('bin6', 'assets/objects/bin6.png');
- this.load.image('bin5', 'assets/objects/bin5.png');
- this.load.image('bin4', 'assets/objects/bin4.png');
- this.load.image('bin3', 'assets/objects/bin3.png');
- this.load.image('bin2', 'assets/objects/bin2.png');
- this.load.image('bin1', 'assets/objects/bin1.png');
+ this.load.image('fingerprint_kit', 'objects/fingerprint_kit.png');
+ this.load.image('pin-cracker', 'objects/pin-cracker.png');
+ this.load.image('bin11', 'objects/bin11.png');
+ this.load.image('bin10', 'objects/bin10.png');
+ this.load.image('bin9', 'objects/bin9.png');
+ this.load.image('bin8', 'objects/bin8.png');
+ this.load.image('bin7', 'objects/bin7.png');
+ this.load.image('bin6', 'objects/bin6.png');
+ this.load.image('bin5', 'objects/bin5.png');
+ this.load.image('bin4', 'objects/bin4.png');
+ this.load.image('bin3', 'objects/bin3.png');
+ this.load.image('bin2', 'objects/bin2.png');
+ this.load.image('bin1', 'objects/bin1.png');
// Suitcases
- this.load.image('suitcase21', 'assets/objects/suitcase21.png');
- this.load.image('suitcase20', 'assets/objects/suitcase20.png');
- this.load.image('suitcase19', 'assets/objects/suitcase19.png');
- this.load.image('suitcase18', 'assets/objects/suitcase18.png');
- this.load.image('suitcase17', 'assets/objects/suitcase17.png');
- this.load.image('suitcase16', 'assets/objects/suitcase16.png');
- this.load.image('suitcase15', 'assets/objects/suitcase15.png');
- this.load.image('suitcase14', 'assets/objects/suitcase14.png');
- this.load.image('suitcase13', 'assets/objects/suitcase13.png');
- this.load.image('suitcase12', 'assets/objects/suitcase12.png');
- this.load.image('suitcase11', 'assets/objects/suitcase11.png');
- this.load.image('suitcase10', 'assets/objects/suitcase10.png');
- this.load.image('suitcase9', 'assets/objects/suitcase9.png');
- this.load.image('suitcase8', 'assets/objects/suitcase8.png');
- this.load.image('suitcase7', 'assets/objects/suitcase7.png');
- this.load.image('suitcase6', 'assets/objects/suitcase6.png');
- this.load.image('suitcase5', 'assets/objects/suitcase5.png');
- this.load.image('suitcase4', 'assets/objects/suitcase4.png');
- this.load.image('suitcase3', 'assets/objects/suitcase3.png');
- this.load.image('suitcase2', 'assets/objects/suitcase2.png');
- this.load.image('suitcase-1', 'assets/objects/suitcase-1.png');
+ this.load.image('suitcase21', 'objects/suitcase21.png');
+ this.load.image('suitcase20', 'objects/suitcase20.png');
+ this.load.image('suitcase19', 'objects/suitcase19.png');
+ this.load.image('suitcase18', 'objects/suitcase18.png');
+ this.load.image('suitcase17', 'objects/suitcase17.png');
+ this.load.image('suitcase16', 'objects/suitcase16.png');
+ this.load.image('suitcase15', 'objects/suitcase15.png');
+ this.load.image('suitcase14', 'objects/suitcase14.png');
+ this.load.image('suitcase13', 'objects/suitcase13.png');
+ this.load.image('suitcase12', 'objects/suitcase12.png');
+ this.load.image('suitcase11', 'objects/suitcase11.png');
+ this.load.image('suitcase10', 'objects/suitcase10.png');
+ this.load.image('suitcase9', 'objects/suitcase9.png');
+ this.load.image('suitcase8', 'objects/suitcase8.png');
+ this.load.image('suitcase7', 'objects/suitcase7.png');
+ this.load.image('suitcase6', 'objects/suitcase6.png');
+ this.load.image('suitcase5', 'objects/suitcase5.png');
+ this.load.image('suitcase4', 'objects/suitcase4.png');
+ this.load.image('suitcase3', 'objects/suitcase3.png');
+ this.load.image('suitcase2', 'objects/suitcase2.png');
+ this.load.image('suitcase-1', 'objects/suitcase-1.png');
// Plants
- this.load.image('plant-flat-pot7', 'assets/objects/plant-flat-pot7.png');
- this.load.image('plant-flat-pot6', 'assets/objects/plant-flat-pot6.png');
- this.load.image('plant-flat-pot5', 'assets/objects/plant-flat-pot5.png');
- this.load.image('plant-flat-pot4', 'assets/objects/plant-flat-pot4.png');
- this.load.image('plant-flat-pot3', 'assets/objects/plant-flat-pot3.png');
- this.load.image('plant-flat-pot2', 'assets/objects/plant-flat-pot2.png');
- this.load.image('plant-flat-pot1', 'assets/objects/plant-flat-pot1.png');
+ this.load.image('plant-flat-pot7', 'objects/plant-flat-pot7.png');
+ this.load.image('plant-flat-pot6', 'objects/plant-flat-pot6.png');
+ this.load.image('plant-flat-pot5', 'objects/plant-flat-pot5.png');
+ this.load.image('plant-flat-pot4', 'objects/plant-flat-pot4.png');
+ this.load.image('plant-flat-pot3', 'objects/plant-flat-pot3.png');
+ this.load.image('plant-flat-pot2', 'objects/plant-flat-pot2.png');
+ this.load.image('plant-flat-pot1', 'objects/plant-flat-pot1.png');
// Office furniture
- this.load.image('outdoor-lamp4', 'assets/objects/outdoor-lamp4.png');
- this.load.image('outdoor-lamp3', 'assets/objects/outdoor-lamp3.png');
- this.load.image('outdoor-lamp2', 'assets/objects/outdoor-lamp2.png');
- this.load.image('outdoor-lamp1', 'assets/objects/outdoor-lamp1.png');
- this.load.image('plant-large10', 'assets/objects/plant-large10.png');
- this.load.image('lamp-stand5', 'assets/objects/lamp-stand5.png');
- this.load.image('plant-large9', 'assets/objects/plant-large9.png');
- this.load.image('plant-large8', 'assets/objects/plant-large8.png');
- this.load.image('plant-large7', 'assets/objects/plant-large7.png');
- this.load.image('plant-large6', 'assets/objects/plant-large6.png');
- this.load.image('lamp-stand4', 'assets/objects/lamp-stand4.png');
- this.load.image('plant-large5', 'assets/objects/plant-large5.png');
- this.load.image('plant-large4', 'assets/objects/plant-large4.png');
- this.load.image('plant-large3', 'assets/objects/plant-large3.png');
- this.load.image('plant-large2', 'assets/objects/plant-large2.png');
- this.load.image('lamp-stand3', 'assets/objects/lamp-stand3.png');
- this.load.image('plant-large1', 'assets/objects/plant-large1.png');
- this.load.image('lamp-stand2', 'assets/objects/lamp-stand2.png');
- this.load.image('lamp-stand1', 'assets/objects/lamp-stand1.png');
+ this.load.image('outdoor-lamp4', 'objects/outdoor-lamp4.png');
+ this.load.image('outdoor-lamp3', 'objects/outdoor-lamp3.png');
+ this.load.image('outdoor-lamp2', 'objects/outdoor-lamp2.png');
+ this.load.image('outdoor-lamp1', 'objects/outdoor-lamp1.png');
+ this.load.image('plant-large10', 'objects/plant-large10.png');
+ this.load.image('lamp-stand5', 'objects/lamp-stand5.png');
+ this.load.image('plant-large9', 'objects/plant-large9.png');
+ this.load.image('plant-large8', 'objects/plant-large8.png');
+ this.load.image('plant-large7', 'objects/plant-large7.png');
+ this.load.image('plant-large6', 'objects/plant-large6.png');
+ this.load.image('lamp-stand4', 'objects/lamp-stand4.png');
+ this.load.image('plant-large5', 'objects/plant-large5.png');
+ this.load.image('plant-large4', 'objects/plant-large4.png');
+ this.load.image('plant-large3', 'objects/plant-large3.png');
+ this.load.image('plant-large2', 'objects/plant-large2.png');
+ this.load.image('lamp-stand3', 'objects/lamp-stand3.png');
+ this.load.image('plant-large1', 'objects/plant-large1.png');
+ this.load.image('lamp-stand2', 'objects/lamp-stand2.png');
+ this.load.image('lamp-stand1', 'objects/lamp-stand1.png');
// Pictures
- this.load.image('picture14', 'assets/objects/picture14.png');
- this.load.image('picture13', 'assets/objects/picture13.png');
- this.load.image('picture12', 'assets/objects/picture12.png');
- this.load.image('picture11', 'assets/objects/picture11.png');
- this.load.image('picture10', 'assets/objects/picture10.png');
- this.load.image('picture9', 'assets/objects/picture9.png');
- this.load.image('picture8', 'assets/objects/picture8.png');
- this.load.image('picture7', 'assets/objects/picture7.png');
- this.load.image('picture6', 'assets/objects/picture6.png');
- this.load.image('picture5', 'assets/objects/picture5.png');
- this.load.image('picture4', 'assets/objects/picture4.png');
- this.load.image('picture3', 'assets/objects/picture3.png');
- this.load.image('picture2', 'assets/objects/picture2.png');
- this.load.image('picture1', 'assets/objects/picture1.png');
+ this.load.image('picture14', 'objects/picture14.png');
+ this.load.image('picture13', 'objects/picture13.png');
+ this.load.image('picture12', 'objects/picture12.png');
+ this.load.image('picture11', 'objects/picture11.png');
+ this.load.image('picture10', 'objects/picture10.png');
+ this.load.image('picture9', 'objects/picture9.png');
+ this.load.image('picture8', 'objects/picture8.png');
+ this.load.image('picture7', 'objects/picture7.png');
+ this.load.image('picture6', 'objects/picture6.png');
+ this.load.image('picture5', 'objects/picture5.png');
+ this.load.image('picture4', 'objects/picture4.png');
+ this.load.image('picture3', 'objects/picture3.png');
+ this.load.image('picture2', 'objects/picture2.png');
+ this.load.image('picture1', 'objects/picture1.png');
// Office misc items
- this.load.image('office-misc-smallplant2', 'assets/objects/office-misc-smallplant2.png');
- this.load.image('office-misc-smallplant3', 'assets/objects/office-misc-smallplant3.png');
- this.load.image('office-misc-smallplant4', 'assets/objects/office-misc-smallplant4.png');
- this.load.image('office-misc-smallplant5', 'assets/objects/office-misc-smallplant5.png');
- this.load.image('office-misc-box1', 'assets/objects/office-misc-box1.png');
- this.load.image('office-misc-container', 'assets/objects/office-misc-container.png');
- this.load.image('office-misc-lamp3', 'assets/objects/office-misc-lamp3.png');
- this.load.image('office-misc-hdd6', 'assets/objects/office-misc-hdd6.png');
- this.load.image('office-misc-speakers6', 'assets/objects/office-misc-speakers6.png');
- this.load.image('office-misc-pencils6', 'assets/objects/office-misc-pencils6.png');
- this.load.image('office-misc-fan2', 'assets/objects/office-misc-fan2.png');
- this.load.image('office-misc-cup5', 'assets/objects/office-misc-cup5.png');
- this.load.image('office-misc-hdd5', 'assets/objects/office-misc-hdd5.png');
- this.load.image('office-misc-speakers5', 'assets/objects/office-misc-speakers5.png');
- this.load.image('office-misc-cup4', 'assets/objects/office-misc-cup4.png');
- this.load.image('office-misc-speakers4', 'assets/objects/office-misc-speakers4.png');
- this.load.image('office-misc-pencils5', 'assets/objects/office-misc-pencils5.png');
+ this.load.image('office-misc-smallplant2', 'objects/office-misc-smallplant2.png');
+ this.load.image('office-misc-smallplant3', 'objects/office-misc-smallplant3.png');
+ this.load.image('office-misc-smallplant4', 'objects/office-misc-smallplant4.png');
+ this.load.image('office-misc-smallplant5', 'objects/office-misc-smallplant5.png');
+ this.load.image('office-misc-box1', 'objects/office-misc-box1.png');
+ this.load.image('office-misc-container', 'objects/office-misc-container.png');
+ this.load.image('office-misc-lamp3', 'objects/office-misc-lamp3.png');
+ this.load.image('office-misc-hdd6', 'objects/office-misc-hdd6.png');
+ this.load.image('office-misc-speakers6', 'objects/office-misc-speakers6.png');
+ this.load.image('office-misc-pencils6', 'objects/office-misc-pencils6.png');
+ this.load.image('office-misc-fan2', 'objects/office-misc-fan2.png');
+ this.load.image('office-misc-cup5', 'objects/office-misc-cup5.png');
+ this.load.image('office-misc-hdd5', 'objects/office-misc-hdd5.png');
+ this.load.image('office-misc-speakers5', 'objects/office-misc-speakers5.png');
+ this.load.image('office-misc-cup4', 'objects/office-misc-cup4.png');
+ this.load.image('office-misc-speakers4', 'objects/office-misc-speakers4.png');
+ this.load.image('office-misc-pencils5', 'objects/office-misc-pencils5.png');
- this.load.image('office-misc-clock', 'assets/objects/office-misc-clock.png');
- this.load.image('office-misc-fan', 'assets/objects/office-misc-fan.png');
- this.load.image('office-misc-speakers3', 'assets/objects/office-misc-speakers3.png');
- this.load.image('office-misc-camera', 'assets/objects/office-misc-camera.png');
- this.load.image('office-misc-headphones', 'assets/objects/office-misc-headphones.png');
- this.load.image('office-misc-hdd4', 'assets/objects/office-misc-hdd4.png');
- this.load.image('office-misc-pencils4', 'assets/objects/office-misc-pencils4.png');
- this.load.image('office-misc-cup3', 'assets/objects/office-misc-cup3.png');
- this.load.image('office-misc-cup2', 'assets/objects/office-misc-cup2.png');
- this.load.image('office-misc-speakers2', 'assets/objects/office-misc-speakers2.png');
- this.load.image('office-misc-stapler', 'assets/objects/office-misc-stapler.png');
- this.load.image('office-misc-hdd3', 'assets/objects/office-misc-hdd3.png');
- this.load.image('office-misc-hdd2', 'assets/objects/office-misc-hdd2.png');
- this.load.image('office-misc-pencils3', 'assets/objects/office-misc-pencils3.png');
- this.load.image('office-misc-pencils2', 'assets/objects/office-misc-pencils2.png');
- this.load.image('office-misc-pens', 'assets/objects/office-misc-pens.png');
- this.load.image('office-misc-lamp2', 'assets/objects/office-misc-lamp2.png');
- this.load.image('office-misc-hdd', 'assets/objects/office-misc-hdd.png');
- this.load.image('office-misc-smallplant', 'assets/objects/office-misc-smallplant.png');
- this.load.image('office-misc-pencils', 'assets/objects/office-misc-pencils.png');
- this.load.image('office-misc-speakers', 'assets/objects/office-misc-speakers.png');
- this.load.image('office-misc-cup', 'assets/objects/office-misc-cup.png');
- this.load.image('office-misc-lamp', 'assets/objects/office-misc-lamp.png');
- this.load.image('phone5', 'assets/objects/phone5.png');
- this.load.image('phone4', 'assets/objects/phone4.png');
- this.load.image('phone3', 'assets/objects/phone3.png');
- this.load.image('phone2', 'assets/objects/phone2.png');
- this.load.image('phone1', 'assets/objects/phone1.png');
+ this.load.image('office-misc-clock', 'objects/office-misc-clock.png');
+ this.load.image('office-misc-fan', 'objects/office-misc-fan.png');
+ this.load.image('office-misc-speakers3', 'objects/office-misc-speakers3.png');
+ this.load.image('office-misc-camera', 'objects/office-misc-camera.png');
+ this.load.image('office-misc-headphones', 'objects/office-misc-headphones.png');
+ this.load.image('office-misc-hdd4', 'objects/office-misc-hdd4.png');
+ this.load.image('office-misc-pencils4', 'objects/office-misc-pencils4.png');
+ this.load.image('office-misc-cup3', 'objects/office-misc-cup3.png');
+ this.load.image('office-misc-cup2', 'objects/office-misc-cup2.png');
+ this.load.image('office-misc-speakers2', 'objects/office-misc-speakers2.png');
+ this.load.image('office-misc-stapler', 'objects/office-misc-stapler.png');
+ this.load.image('office-misc-hdd3', 'objects/office-misc-hdd3.png');
+ this.load.image('office-misc-hdd2', 'objects/office-misc-hdd2.png');
+ this.load.image('office-misc-pencils3', 'objects/office-misc-pencils3.png');
+ this.load.image('office-misc-pencils2', 'objects/office-misc-pencils2.png');
+ this.load.image('office-misc-pens', 'objects/office-misc-pens.png');
+ this.load.image('office-misc-lamp2', 'objects/office-misc-lamp2.png');
+ this.load.image('office-misc-hdd', 'objects/office-misc-hdd.png');
+ this.load.image('office-misc-smallplant', 'objects/office-misc-smallplant.png');
+ this.load.image('office-misc-pencils', 'objects/office-misc-pencils.png');
+ this.load.image('office-misc-speakers', 'objects/office-misc-speakers.png');
+ this.load.image('office-misc-cup', 'objects/office-misc-cup.png');
+ this.load.image('office-misc-lamp', 'objects/office-misc-lamp.png');
+ this.load.image('phone5', 'objects/phone5.png');
+ this.load.image('phone4', 'objects/phone4.png');
+ this.load.image('phone3', 'objects/phone3.png');
+ this.load.image('phone2', 'objects/phone2.png');
+ this.load.image('phone1', 'objects/phone1.png');
// Bags and briefcases
- this.load.image('bag25', 'assets/objects/bag25.png');
- this.load.image('bag24', 'assets/objects/bag24.png');
- this.load.image('bag23', 'assets/objects/bag23.png');
- this.load.image('bag22', 'assets/objects/bag22.png');
- this.load.image('bag21', 'assets/objects/bag21.png');
- this.load.image('bag20', 'assets/objects/bag20.png');
- this.load.image('bag19', 'assets/objects/bag19.png');
- this.load.image('bag18', 'assets/objects/bag18.png');
- this.load.image('bag17', 'assets/objects/bag17.png');
- this.load.image('bag16', 'assets/objects/bag16.png');
- this.load.image('bag15', 'assets/objects/bag15.png');
- this.load.image('bag14', 'assets/objects/bag14.png');
- this.load.image('bag13', 'assets/objects/bag13.png');
- this.load.image('bag12', 'assets/objects/bag12.png');
- this.load.image('bag11', 'assets/objects/bag11.png');
- this.load.image('bag10', 'assets/objects/bag10.png');
- this.load.image('bag9', 'assets/objects/bag9.png');
- this.load.image('bag8', 'assets/objects/bag8.png');
- this.load.image('bag7', 'assets/objects/bag7.png');
- this.load.image('bag6', 'assets/objects/bag6.png');
- this.load.image('bag5', 'assets/objects/bag5.png');
- this.load.image('bag4', 'assets/objects/bag4.png');
- this.load.image('bag3', 'assets/objects/bag3.png');
- this.load.image('bag2', 'assets/objects/bag2.png');
- this.load.image('bag1', 'assets/objects/bag1.png');
+ this.load.image('bag25', 'objects/bag25.png');
+ this.load.image('bag24', 'objects/bag24.png');
+ this.load.image('bag23', 'objects/bag23.png');
+ this.load.image('bag22', 'objects/bag22.png');
+ this.load.image('bag21', 'objects/bag21.png');
+ this.load.image('bag20', 'objects/bag20.png');
+ this.load.image('bag19', 'objects/bag19.png');
+ this.load.image('bag18', 'objects/bag18.png');
+ this.load.image('bag17', 'objects/bag17.png');
+ this.load.image('bag16', 'objects/bag16.png');
+ this.load.image('bag15', 'objects/bag15.png');
+ this.load.image('bag14', 'objects/bag14.png');
+ this.load.image('bag13', 'objects/bag13.png');
+ this.load.image('bag12', 'objects/bag12.png');
+ this.load.image('bag11', 'objects/bag11.png');
+ this.load.image('bag10', 'objects/bag10.png');
+ this.load.image('bag9', 'objects/bag9.png');
+ this.load.image('bag8', 'objects/bag8.png');
+ this.load.image('bag7', 'objects/bag7.png');
+ this.load.image('bag6', 'objects/bag6.png');
+ this.load.image('bag5', 'objects/bag5.png');
+ this.load.image('bag4', 'objects/bag4.png');
+ this.load.image('bag3', 'objects/bag3.png');
+ this.load.image('bag2', 'objects/bag2.png');
+ this.load.image('bag1', 'objects/bag1.png');
// Briefcases
- this.load.image('briefcase-orange-1', 'assets/objects/briefcase-orange-1.png');
- this.load.image('briefcase-yellow-1', 'assets/objects/briefcase-yellow-1.png');
- this.load.image('briefcase13', 'assets/objects/briefcase13.png');
- this.load.image('briefcase-purple-1', 'assets/objects/briefcase-purple-1.png');
- this.load.image('briefcase-green-1', 'assets/objects/briefcase-green-1.png');
- this.load.image('briefcase-blue-1', 'assets/objects/briefcase-blue-1.png');
- this.load.image('briefcase-red-1', 'assets/objects/briefcase-red-1.png');
- this.load.image('briefcase12', 'assets/objects/briefcase12.png');
- this.load.image('briefcase11', 'assets/objects/briefcase11.png');
- this.load.image('briefcase10', 'assets/objects/briefcase10.png');
- this.load.image('briefcase9', 'assets/objects/briefcase9.png');
- this.load.image('briefcase8', 'assets/objects/briefcase8.png');
- this.load.image('briefcase7', 'assets/objects/briefcase7.png');
- this.load.image('briefcase6', 'assets/objects/briefcase6.png');
- this.load.image('briefcase5', 'assets/objects/briefcase5.png');
- this.load.image('briefcase4', 'assets/objects/briefcase4.png');
- this.load.image('briefcase3', 'assets/objects/briefcase3.png');
- this.load.image('briefcase2', 'assets/objects/briefcase2.png');
- this.load.image('briefcase1', 'assets/objects/briefcase1.png');
+ this.load.image('briefcase-orange-1', 'objects/briefcase-orange-1.png');
+ this.load.image('briefcase-yellow-1', 'objects/briefcase-yellow-1.png');
+ this.load.image('briefcase13', 'objects/briefcase13.png');
+ this.load.image('briefcase-purple-1', 'objects/briefcase-purple-1.png');
+ this.load.image('briefcase-green-1', 'objects/briefcase-green-1.png');
+ this.load.image('briefcase-blue-1', 'objects/briefcase-blue-1.png');
+ this.load.image('briefcase-red-1', 'objects/briefcase-red-1.png');
+ this.load.image('briefcase12', 'objects/briefcase12.png');
+ this.load.image('briefcase11', 'objects/briefcase11.png');
+ this.load.image('briefcase10', 'objects/briefcase10.png');
+ this.load.image('briefcase9', 'objects/briefcase9.png');
+ this.load.image('briefcase8', 'objects/briefcase8.png');
+ this.load.image('briefcase7', 'objects/briefcase7.png');
+ this.load.image('briefcase6', 'objects/briefcase6.png');
+ this.load.image('briefcase5', 'objects/briefcase5.png');
+ this.load.image('briefcase4', 'objects/briefcase4.png');
+ this.load.image('briefcase3', 'objects/briefcase3.png');
+ this.load.image('briefcase2', 'objects/briefcase2.png');
+ this.load.image('briefcase1', 'objects/briefcase1.png');
// Chairs
- this.load.image('chair-grey-4', 'assets/objects/chair-grey-4.png');
- this.load.image('chair-grey-3', 'assets/objects/chair-grey-3.png');
- this.load.image('chair-darkgreen-3', 'assets/objects/chair-darkgreen-3.png');
- this.load.image('chair-grey-2', 'assets/objects/chair-grey-2.png');
- this.load.image('chair-darkgray-1', 'assets/objects/chair-darkgray-1.png');
- this.load.image('chair-darkgreen-2', 'assets/objects/chair-darkgreen-2.png');
- this.load.image('chair-darkgreen-1', 'assets/objects/chair-darkgreen-1.png');
- this.load.image('chair-grey-1', 'assets/objects/chair-grey-1.png');
- this.load.image('chair-red-4', 'assets/objects/chair-red-4.png');
- this.load.image('chair-red-3', 'assets/objects/chair-red-3.png');
- this.load.image('chair-green-2', 'assets/objects/chair-green-2.png');
- this.load.image('chair-green-1', 'assets/objects/chair-green-1.png');
- this.load.image('chair-red-2', 'assets/objects/chair-red-2.png');
- this.load.image('chair-red-1', 'assets/objects/chair-red-1.png');
- this.load.image('chair-white-2', 'assets/objects/chair-white-2.png');
- this.load.image('chair-white-1', 'assets/objects/chair-white-1.png');
+ this.load.image('chair-grey-4', 'objects/chair-grey-4.png');
+ this.load.image('chair-grey-3', 'objects/chair-grey-3.png');
+ this.load.image('chair-darkgreen-3', 'objects/chair-darkgreen-3.png');
+ this.load.image('chair-grey-2', 'objects/chair-grey-2.png');
+ this.load.image('chair-darkgray-1', 'objects/chair-darkgray-1.png');
+ this.load.image('chair-darkgreen-2', 'objects/chair-darkgreen-2.png');
+ this.load.image('chair-darkgreen-1', 'objects/chair-darkgreen-1.png');
+ this.load.image('chair-grey-1', 'objects/chair-grey-1.png');
+ this.load.image('chair-red-4', 'objects/chair-red-4.png');
+ this.load.image('chair-red-3', 'objects/chair-red-3.png');
+ this.load.image('chair-green-2', 'objects/chair-green-2.png');
+ this.load.image('chair-green-1', 'objects/chair-green-1.png');
+ this.load.image('chair-red-2', 'objects/chair-red-2.png');
+ this.load.image('chair-red-1', 'objects/chair-red-1.png');
+ this.load.image('chair-white-2', 'objects/chair-white-2.png');
+ this.load.image('chair-white-1', 'objects/chair-white-1.png');
// Keyboards
- this.load.image('keyboard8', 'assets/objects/keyboard8.png');
- this.load.image('keyboard7', 'assets/objects/keyboard7.png');
- this.load.image('keyboard6', 'assets/objects/keyboard6.png');
- this.load.image('keyboard5', 'assets/objects/keyboard5.png');
- this.load.image('keyboard4', 'assets/objects/keyboard4.png');
- this.load.image('keyboard3', 'assets/objects/keyboard3.png');
- this.load.image('keyboard2', 'assets/objects/keyboard2.png');
- this.load.image('keyboard1', 'assets/objects/keyboard1.png');
+ this.load.image('keyboard8', 'objects/keyboard8.png');
+ this.load.image('keyboard7', 'objects/keyboard7.png');
+ this.load.image('keyboard6', 'objects/keyboard6.png');
+ this.load.image('keyboard5', 'objects/keyboard5.png');
+ this.load.image('keyboard4', 'objects/keyboard4.png');
+ this.load.image('keyboard3', 'objects/keyboard3.png');
+ this.load.image('keyboard2', 'objects/keyboard2.png');
+ this.load.image('keyboard1', 'objects/keyboard1.png');
// Safes
- this.load.image('safe5', 'assets/objects/safe5.png');
- this.load.image('safe4', 'assets/objects/safe4.png');
- this.load.image('safe3', 'assets/objects/safe3.png');
- this.load.image('safe2', 'assets/objects/safe2.png');
- this.load.image('safe1', 'assets/objects/safe1.png');
+ this.load.image('safe5', 'objects/safe5.png');
+ this.load.image('safe4', 'objects/safe4.png');
+ this.load.image('safe3', 'objects/safe3.png');
+ this.load.image('safe2', 'objects/safe2.png');
+ this.load.image('safe1', 'objects/safe1.png');
// Notes
- this.load.image('notes1', 'assets/objects/notes1.png');
- this.load.image('notes2', 'assets/objects/notes2.png');
- this.load.image('notes3', 'assets/objects/notes3.png');
- this.load.image('notes4', 'assets/objects/notes4.png');
+ this.load.image('notes1', 'objects/notes1.png');
+ this.load.image('notes2', 'objects/notes2.png');
+ this.load.image('notes3', 'objects/notes3.png');
+ this.load.image('notes4', 'objects/notes4.png');
// Servers and tech
- this.load.image('servers', 'assets/objects/servers.png');
- this.load.image('servers3', 'assets/objects/servers3.png');
- this.load.image('servers2', 'assets/objects/servers2.png');
- this.load.image('sofa1', 'assets/objects/sofa1.png');
- this.load.image('plant-large13', 'assets/objects/plant-large13.png');
- this.load.image('office-misc-lamp4', 'assets/objects/office-misc-lamp4.png');
- this.load.image('chair-waiting-right-1', 'assets/objects/chair-waiting-right-1.png');
- this.load.image('chair-waiting-left-1', 'assets/objects/chair-waiting-left-1.png');
- this.load.image('plant-large12', 'assets/objects/plant-large12.png');
- this.load.image('plant-large11', 'assets/objects/plant-large11.png');
+ this.load.image('servers', 'objects/servers.png');
+ this.load.image('servers3', 'objects/servers3.png');
+ this.load.image('servers2', 'objects/servers2.png');
+ this.load.image('sofa1', 'objects/sofa1.png');
+ this.load.image('plant-large13', 'objects/plant-large13.png');
+ this.load.image('office-misc-lamp4', 'objects/office-misc-lamp4.png');
+ this.load.image('chair-waiting-right-1', 'objects/chair-waiting-right-1.png');
+ this.load.image('chair-waiting-left-1', 'objects/chair-waiting-left-1.png');
+ this.load.image('plant-large12', 'objects/plant-large12.png');
+ this.load.image('plant-large11', 'objects/plant-large11.png');
// Load animated plant frames
- this.load.image('plant-large11-top-ani1', 'assets/objects/plant-large11-top-ani1.png');
- this.load.image('plant-large11-top-ani2', 'assets/objects/plant-large11-top-ani2.png');
- this.load.image('plant-large11-top-ani3', 'assets/objects/plant-large11-top-ani3.png');
- this.load.image('plant-large11-top-ani4', 'assets/objects/plant-large11-top-ani4.png');
+ this.load.image('plant-large11-top-ani1', 'objects/plant-large11-top-ani1.png');
+ this.load.image('plant-large11-top-ani2', 'objects/plant-large11-top-ani2.png');
+ this.load.image('plant-large11-top-ani3', 'objects/plant-large11-top-ani3.png');
+ this.load.image('plant-large11-top-ani4', 'objects/plant-large11-top-ani4.png');
- this.load.image('plant-large12-top-ani1', 'assets/objects/plant-large12-top-ani1.png');
- this.load.image('plant-large12-top-ani2', 'assets/objects/plant-large12-top-ani2.png');
- this.load.image('plant-large12-top-ani3', 'assets/objects/plant-large12-top-ani3.png');
- this.load.image('plant-large12-top-ani4', 'assets/objects/plant-large12-top-ani4.png');
- this.load.image('plant-large12-top-ani5', 'assets/objects/plant-large12-top-ani5.png');
+ this.load.image('plant-large12-top-ani1', 'objects/plant-large12-top-ani1.png');
+ this.load.image('plant-large12-top-ani2', 'objects/plant-large12-top-ani2.png');
+ this.load.image('plant-large12-top-ani3', 'objects/plant-large12-top-ani3.png');
+ this.load.image('plant-large12-top-ani4', 'objects/plant-large12-top-ani4.png');
+ this.load.image('plant-large12-top-ani5', 'objects/plant-large12-top-ani5.png');
- this.load.image('plant-large13-top-ani1', 'assets/objects/plant-large13-top-ani1.png');
- this.load.image('plant-large13-top-ani2', 'assets/objects/plant-large13-top-ani2.png');
- this.load.image('plant-large13-top-ani3', 'assets/objects/plant-large13-top-ani3.png');
- this.load.image('plant-large13-top-ani4', 'assets/objects/plant-large13-top-ani4.png');
- this.load.image('pc1', 'assets/objects/pc1.png');
- this.load.image('pc3', 'assets/objects/pc3.png');
- this.load.image('pc4', 'assets/objects/pc4.png');
- this.load.image('pc5', 'assets/objects/pc5.png');
- this.load.image('pc6', 'assets/objects/pc6.png');
- this.load.image('pc7', 'assets/objects/pc7.png');
- this.load.image('pc8', 'assets/objects/pc8.png');
- this.load.image('pc9', 'assets/objects/pc9.png');
- this.load.image('pc10', 'assets/objects/pc10.png');
- this.load.image('pc11', 'assets/objects/pc11.png');
- this.load.image('pc12', 'assets/objects/pc12.png');
+ this.load.image('plant-large13-top-ani1', 'objects/plant-large13-top-ani1.png');
+ this.load.image('plant-large13-top-ani2', 'objects/plant-large13-top-ani2.png');
+ this.load.image('plant-large13-top-ani3', 'objects/plant-large13-top-ani3.png');
+ this.load.image('plant-large13-top-ani4', 'objects/plant-large13-top-ani4.png');
+ this.load.image('pc1', 'objects/pc1.png');
+ this.load.image('pc3', 'objects/pc3.png');
+ this.load.image('pc4', 'objects/pc4.png');
+ this.load.image('pc5', 'objects/pc5.png');
+ this.load.image('pc6', 'objects/pc6.png');
+ this.load.image('pc7', 'objects/pc7.png');
+ this.load.image('pc8', 'objects/pc8.png');
+ this.load.image('pc9', 'objects/pc9.png');
+ this.load.image('pc10', 'objects/pc10.png');
+ this.load.image('pc11', 'objects/pc11.png');
+ this.load.image('pc12', 'objects/pc12.png');
// Laptops
- this.load.image('laptop7', 'assets/objects/laptop7.png');
- this.load.image('laptop6', 'assets/objects/laptop6.png');
- this.load.image('laptop5', 'assets/objects/laptop5.png');
- this.load.image('laptop4', 'assets/objects/laptop4.png');
- this.load.image('laptop3', 'assets/objects/laptop3.png');
- this.load.image('laptop2', 'assets/objects/laptop2.png');
- this.load.image('laptop1', 'assets/objects/laptop1.png');
+ this.load.image('laptop7', 'objects/laptop7.png');
+ this.load.image('laptop6', 'objects/laptop6.png');
+ this.load.image('laptop5', 'objects/laptop5.png');
+ this.load.image('laptop4', 'objects/laptop4.png');
+ this.load.image('laptop3', 'objects/laptop3.png');
+ this.load.image('laptop2', 'objects/laptop2.png');
+ this.load.image('laptop1', 'objects/laptop1.png');
// Chalkboards and bookcases
- this.load.image('chalkboard3', 'assets/objects/chalkboard3.png');
- this.load.image('chalkboard2', 'assets/objects/chalkboard2.png');
- this.load.image('chalkboard', 'assets/objects/chalkboard.png');
- this.load.image('bookcase', 'assets/objects/bookcase.png');
+ this.load.image('chalkboard3', 'objects/chalkboard3.png');
+ this.load.image('chalkboard2', 'objects/chalkboard2.png');
+ this.load.image('chalkboard', 'objects/chalkboard.png');
+ this.load.image('bookcase', 'objects/bookcase.png');
// Spooky basement items
- this.load.image('spooky-splatter', 'assets/objects/spooky-splatter.png');
- this.load.image('spooky-candles2', 'assets/objects/spooky-candles2.png');
- this.load.image('spooky-candles', 'assets/objects/spooky-candles.png');
- this.load.image('torch-left', 'assets/objects/torch-left.png');
- this.load.image('torch-right', 'assets/objects/torch-right.png');
- this.load.image('torch-1', 'assets/objects/torch-1.png');
+ this.load.image('spooky-splatter', 'objects/spooky-splatter.png');
+ this.load.image('spooky-candles2', 'objects/spooky-candles2.png');
+ this.load.image('spooky-candles', 'objects/spooky-candles.png');
+ this.load.image('torch-left', 'objects/torch-left.png');
+ this.load.image('torch-right', 'objects/torch-right.png');
+ this.load.image('torch-1', 'objects/torch-1.png');
// Load character sprite sheet instead of single image
- this.load.spritesheet('hacker', 'assets/characters/hacker.png', {
+ this.load.spritesheet('hacker', 'characters/hacker.png', {
frameWidth: 64,
frameHeight: 64
});
// Load character sprite sheet instead of single image
- this.load.spritesheet('hacker-red', 'assets/characters/hacker-red.png', {
+ this.load.spritesheet('hacker-red', 'characters/hacker-red.png', {
frameWidth: 64,
frameHeight: 64
});
@@ -402,37 +402,37 @@ export function preload() {
// Animated plant textures are loaded above
// Load swivel chair rotation images
- this.load.image('chair-exec-rotate1', 'assets/objects/chair-exec-rotate1.png');
- this.load.image('chair-exec-rotate2', 'assets/objects/chair-exec-rotate2.png');
- this.load.image('chair-exec-rotate3', 'assets/objects/chair-exec-rotate3.png');
- this.load.image('chair-exec-rotate4', 'assets/objects/chair-exec-rotate4.png');
- this.load.image('chair-exec-rotate5', 'assets/objects/chair-exec-rotate5.png');
- this.load.image('chair-exec-rotate6', 'assets/objects/chair-exec-rotate6.png');
- this.load.image('chair-exec-rotate7', 'assets/objects/chair-exec-rotate7.png');
- this.load.image('chair-exec-rotate8', 'assets/objects/chair-exec-rotate8.png');
+ this.load.image('chair-exec-rotate1', 'objects/chair-exec-rotate1.png');
+ this.load.image('chair-exec-rotate2', 'objects/chair-exec-rotate2.png');
+ this.load.image('chair-exec-rotate3', 'objects/chair-exec-rotate3.png');
+ this.load.image('chair-exec-rotate4', 'objects/chair-exec-rotate4.png');
+ this.load.image('chair-exec-rotate5', 'objects/chair-exec-rotate5.png');
+ this.load.image('chair-exec-rotate6', 'objects/chair-exec-rotate6.png');
+ this.load.image('chair-exec-rotate7', 'objects/chair-exec-rotate7.png');
+ this.load.image('chair-exec-rotate8', 'objects/chair-exec-rotate8.png');
// Load white chair rotation images
- this.load.image('chair-white-1-rotate1', 'assets/objects/chair-white-1-rotate1.png');
- this.load.image('chair-white-1-rotate2', 'assets/objects/chair-white-1-rotate2.png');
- this.load.image('chair-white-1-rotate3', 'assets/objects/chair-white-1-rotate3.png');
- this.load.image('chair-white-1-rotate4', 'assets/objects/chair-white-1-rotate4.png');
- this.load.image('chair-white-1-rotate5', 'assets/objects/chair-white-1-rotate5.png');
- this.load.image('chair-white-1-rotate6', 'assets/objects/chair-white-1-rotate6.png');
- this.load.image('chair-white-1-rotate7', 'assets/objects/chair-white-1-rotate7.png');
- this.load.image('chair-white-1-rotate8', 'assets/objects/chair-white-1-rotate8.png');
+ this.load.image('chair-white-1-rotate1', 'objects/chair-white-1-rotate1.png');
+ this.load.image('chair-white-1-rotate2', 'objects/chair-white-1-rotate2.png');
+ this.load.image('chair-white-1-rotate3', 'objects/chair-white-1-rotate3.png');
+ this.load.image('chair-white-1-rotate4', 'objects/chair-white-1-rotate4.png');
+ this.load.image('chair-white-1-rotate5', 'objects/chair-white-1-rotate5.png');
+ this.load.image('chair-white-1-rotate6', 'objects/chair-white-1-rotate6.png');
+ this.load.image('chair-white-1-rotate7', 'objects/chair-white-1-rotate7.png');
+ this.load.image('chair-white-1-rotate8', 'objects/chair-white-1-rotate8.png');
- this.load.image('chair-white-2-rotate1', 'assets/objects/chair-white-2-rotate1.png');
- this.load.image('chair-white-2-rotate2', 'assets/objects/chair-white-2-rotate2.png');
- this.load.image('chair-white-2-rotate3', 'assets/objects/chair-white-2-rotate3.png');
- this.load.image('chair-white-2-rotate4', 'assets/objects/chair-white-2-rotate4.png');
- this.load.image('chair-white-2-rotate5', 'assets/objects/chair-white-2-rotate5.png');
- this.load.image('chair-white-2-rotate6', 'assets/objects/chair-white-2-rotate6.png');
- this.load.image('chair-white-2-rotate7', 'assets/objects/chair-white-2-rotate7.png');
- this.load.image('chair-white-2-rotate8', 'assets/objects/chair-white-2-rotate8.png');
+ this.load.image('chair-white-2-rotate1', 'objects/chair-white-2-rotate1.png');
+ this.load.image('chair-white-2-rotate2', 'objects/chair-white-2-rotate2.png');
+ this.load.image('chair-white-2-rotate3', 'objects/chair-white-2-rotate3.png');
+ this.load.image('chair-white-2-rotate4', 'objects/chair-white-2-rotate4.png');
+ this.load.image('chair-white-2-rotate5', 'objects/chair-white-2-rotate5.png');
+ this.load.image('chair-white-2-rotate6', 'objects/chair-white-2-rotate6.png');
+ this.load.image('chair-white-2-rotate7', 'objects/chair-white-2-rotate7.png');
+ this.load.image('chair-white-2-rotate8', 'objects/chair-white-2-rotate8.png');
// Load audio files
// NPC system sounds
- this.load.audio('message_received', 'assets/sounds/message_received.mp3');
+ this.load.audio('message_received', 'sounds/message_received.mp3');
// Initialize sound manager and preload all sounds
// Store as window property so we can access it later in create()
diff --git a/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js b/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js
index 44c81a4..d19dc7d 100644
--- a/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js
+++ b/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js
@@ -353,14 +353,14 @@ export class LockpickingMinigamePhaser extends MinigameScene {
preload() {
// Load sound effects
- this.load.audio('lockpick_binding', 'assets/sounds/lockpick_binding.mp3');
- this.load.audio('lockpick_click', 'assets/sounds/lockpick_click.mp3');
- this.load.audio('lockpick_overtension', 'assets/sounds/lockpick_overtension.mp3');
- this.load.audio('lockpick_reset', 'assets/sounds/lockpick_reset.mp3');
- this.load.audio('lockpick_set', 'assets/sounds/lockpick_set.mp3');
- this.load.audio('lockpick_success', 'assets/sounds/lockpick_success.mp3');
- this.load.audio('lockpick_tension', 'assets/sounds/lockpick_tension.mp3');
- this.load.audio('lockpick_wrong', 'assets/sounds/lockpick_wrong.mp3');
+ this.load.audio('lockpick_binding', 'sounds/lockpick_binding.mp3');
+ this.load.audio('lockpick_click', 'sounds/lockpick_click.mp3');
+ this.load.audio('lockpick_overtension', 'sounds/lockpick_overtension.mp3');
+ this.load.audio('lockpick_reset', 'sounds/lockpick_reset.mp3');
+ this.load.audio('lockpick_set', 'sounds/lockpick_set.mp3');
+ this.load.audio('lockpick_success', 'sounds/lockpick_success.mp3');
+ this.load.audio('lockpick_tension', 'sounds/lockpick_tension.mp3');
+ this.load.audio('lockpick_wrong', 'sounds/lockpick_wrong.mp3');
}
create() {
@@ -420,7 +420,10 @@ export class LockpickingMinigamePhaser extends MinigameScene {
width: 600,
height: 400,
backgroundColor: '#1a1a1a',
- scene: LockpickingScene
+ scene: LockpickingScene,
+ loader: {
+ baseURL: (window.breakEscapeConfig?.assetsPath || '/break_escape/assets') + '/'
+ }
};
// Adjust canvas size for mobile to crop empty space
diff --git a/public/break_escape/js/minigames/password/password-minigame.js b/public/break_escape/js/minigames/password/password-minigame.js
index a82a3e5..e80102a 100644
--- a/public/break_escape/js/minigames/password/password-minigame.js
+++ b/public/break_escape/js/minigames/password/password-minigame.js
@@ -302,7 +302,7 @@ export class PasswordMinigame extends MinigameScene {
// Update button image
const img = this.togglePasswordBtn.querySelector('img');
if (img) {
- img.src = this.gameData.showPassword ? 'assets/icons/visible.png' : 'assets/icons/hidden.png';
+ img.src = this.gameData.showPassword ? 'icons/visible.png' : 'icons/hidden.png';
}
}
diff --git a/public/break_escape/js/minigames/person-chat/person-chat-ui.js b/public/break_escape/js/minigames/person-chat/person-chat-ui.js
index eddba9d..9a77ca0 100644
--- a/public/break_escape/js/minigames/person-chat/person-chat-ui.js
+++ b/public/break_escape/js/minigames/person-chat/person-chat-ui.js
@@ -280,7 +280,7 @@ export default class PersonChatUI {
id: 'player',
displayName: character.displayName || 'Agent 0x00',
spriteSheet: character.spriteSheet || 'hacker',
- spriteTalk: character.spriteTalk || 'assets/characters/hacker-talk.png',
+ spriteTalk: character.spriteTalk || 'characters/hacker-talk.png',
spriteConfig: character.spriteConfig || {}
};
} else {
diff --git a/public/break_escape/js/systems/minigame-starters.js b/public/break_escape/js/systems/minigame-starters.js
index 63ffb42..995743f 100644
--- a/public/break_escape/js/systems/minigame-starters.js
+++ b/public/break_escape/js/systems/minigame-starters.js
@@ -90,7 +90,7 @@ export function startLockpickingMinigame(lockable, scene, difficulty = 'medium',
itemObservations = `A door leading out of ${currentRoomName}`;
}
- itemImage = 'assets/tiles/door.png'; // Use default door image
+ itemImage = 'tiles/door.png'; // Use default door image
} else {
// This is a regular item - use scenarioData
itemName = lockable?.scenarioData?.name || lockable?.name || 'Locked Item';
@@ -393,7 +393,7 @@ export function startKeySelectionMinigame(lockable, type, playerKeys, requiredKe
itemObservations = `A door leading out of ${currentRoomName}`;
}
- itemImage = 'assets/tiles/door.png'; // Use default door image
+ itemImage = 'tiles/door.png'; // Use default door image
} else {
// This is a regular item - use scenarioData
itemName = lockable?.scenarioData?.name || lockable?.name || 'Locked Item';
diff --git a/public/break_escape/js/systems/sound-manager.js b/public/break_escape/js/systems/sound-manager.js
index f0d6af3..e1f160f 100644
--- a/public/break_escape/js/systems/sound-manager.js
+++ b/public/break_escape/js/systems/sound-manager.js
@@ -29,58 +29,58 @@ class SoundManager {
*/
preloadSounds() {
// Lockpicking mini-game sounds
- this.scene.load.audio('lockpick_binding', 'assets/sounds/lockpick_binding.mp3');
- this.scene.load.audio('lockpick_click', 'assets/sounds/lockpick_click.mp3');
- this.scene.load.audio('lockpick_overtension', 'assets/sounds/lockpick_overtension.mp3');
- this.scene.load.audio('lockpick_reset', 'assets/sounds/lockpick_reset.mp3');
- this.scene.load.audio('lockpick_set', 'assets/sounds/lockpick_set.mp3');
- this.scene.load.audio('lockpick_success', 'assets/sounds/lockpick_success.mp3');
- this.scene.load.audio('lockpick_tension', 'assets/sounds/lockpick_tension.mp3');
- this.scene.load.audio('lockpick_wrong', 'assets/sounds/lockpick_wrong.mp3');
+ this.scene.load.audio('lockpick_binding', 'sounds/lockpick_binding.mp3');
+ this.scene.load.audio('lockpick_click', 'sounds/lockpick_click.mp3');
+ this.scene.load.audio('lockpick_overtension', 'sounds/lockpick_overtension.mp3');
+ this.scene.load.audio('lockpick_reset', 'sounds/lockpick_reset.mp3');
+ this.scene.load.audio('lockpick_set', 'sounds/lockpick_set.mp3');
+ this.scene.load.audio('lockpick_success', 'sounds/lockpick_success.mp3');
+ this.scene.load.audio('lockpick_tension', 'sounds/lockpick_tension.mp3');
+ this.scene.load.audio('lockpick_wrong', 'sounds/lockpick_wrong.mp3');
// GASP door sounds
- this.scene.load.audio('door_knock', 'assets/sounds/GASP_Door Knock.mp3');
+ this.scene.load.audio('door_knock', 'sounds/GASP_Door Knock.mp3');
// GASP interaction sounds
- this.scene.load.audio('item_interact_1', 'assets/sounds/GASP_Item Interact_1.mp3');
- this.scene.load.audio('item_interact_2', 'assets/sounds/GASP_Item Interact_2.mp3');
- this.scene.load.audio('item_interact_3', 'assets/sounds/GASP_Item Interact_3.mp3');
+ this.scene.load.audio('item_interact_1', 'sounds/GASP_Item Interact_1.mp3');
+ this.scene.load.audio('item_interact_2', 'sounds/GASP_Item Interact_2.mp3');
+ this.scene.load.audio('item_interact_3', 'sounds/GASP_Item Interact_3.mp3');
// GASP lock interaction sounds
- this.scene.load.audio('lock_interact_1', 'assets/sounds/GASP_Lock Interact_1.mp3');
- this.scene.load.audio('lock_interact_2', 'assets/sounds/GASP_Lock Interact_2.mp3');
- this.scene.load.audio('lock_interact_3', 'assets/sounds/GASP_Lock Interact_3.mp3');
- this.scene.load.audio('lock_interact_4', 'assets/sounds/GASP_Lock Interact_4.mp3');
- this.scene.load.audio('lock_and_load', 'assets/sounds/GASP_Lock and Load.mp3');
+ this.scene.load.audio('lock_interact_1', 'sounds/GASP_Lock Interact_1.mp3');
+ this.scene.load.audio('lock_interact_2', 'sounds/GASP_Lock Interact_2.mp3');
+ this.scene.load.audio('lock_interact_3', 'sounds/GASP_Lock Interact_3.mp3');
+ this.scene.load.audio('lock_interact_4', 'sounds/GASP_Lock Interact_4.mp3');
+ this.scene.load.audio('lock_and_load', 'sounds/GASP_Lock and Load.mp3');
// GASP UI click sounds
- this.scene.load.audio('ui_click_1', 'assets/sounds/GASP_UI_Clicks_1.mp3');
- this.scene.load.audio('ui_click_2', 'assets/sounds/GASP_UI_Clicks_2.mp3');
- this.scene.load.audio('ui_click_3', 'assets/sounds/GASP_UI_Clicks_3.mp3');
- this.scene.load.audio('ui_click_4', 'assets/sounds/GASP_UI_Clicks_4.mp3');
- this.scene.load.audio('ui_click_6', 'assets/sounds/GASP_UI_Clicks_6.mp3');
+ this.scene.load.audio('ui_click_1', 'sounds/GASP_UI_Clicks_1.mp3');
+ this.scene.load.audio('ui_click_2', 'sounds/GASP_UI_Clicks_2.mp3');
+ this.scene.load.audio('ui_click_3', 'sounds/GASP_UI_Clicks_3.mp3');
+ this.scene.load.audio('ui_click_4', 'sounds/GASP_UI_Clicks_4.mp3');
+ this.scene.load.audio('ui_click_6', 'sounds/GASP_UI_Clicks_6.mp3');
// GASP UI alert sounds
- this.scene.load.audio('ui_alert_1', 'assets/sounds/GASP_UI_Alert_1.mp3');
- this.scene.load.audio('ui_alert_2', 'assets/sounds/GASP_UI_Alert_2.mp3');
+ this.scene.load.audio('ui_alert_1', 'sounds/GASP_UI_Alert_1.mp3');
+ this.scene.load.audio('ui_alert_2', 'sounds/GASP_UI_Alert_2.mp3');
// GASP UI confirm sound
- this.scene.load.audio('ui_confirm', 'assets/sounds/GASP_UI_Confirm.mp3');
+ this.scene.load.audio('ui_confirm', 'sounds/GASP_UI_Confirm.mp3');
// GASP UI notification sounds
- this.scene.load.audio('ui_notification_1', 'assets/sounds/GASP_UI_Notification_1.mp3');
- this.scene.load.audio('ui_notification_2', 'assets/sounds/GASP_UI_Notification_2.mp3');
- this.scene.load.audio('ui_notification_3', 'assets/sounds/GASP_UI_Notification_3.mp3');
- this.scene.load.audio('ui_notification_4', 'assets/sounds/GASP_UI_Notification_4.mp3');
- this.scene.load.audio('ui_notification_5', 'assets/sounds/GASP_UI_Notification_5.mp3');
- this.scene.load.audio('ui_notification_6', 'assets/sounds/GASP_UI_Notification_6.mp3');
+ this.scene.load.audio('ui_notification_1', 'sounds/GASP_UI_Notification_1.mp3');
+ this.scene.load.audio('ui_notification_2', 'sounds/GASP_UI_Notification_2.mp3');
+ this.scene.load.audio('ui_notification_3', 'sounds/GASP_UI_Notification_3.mp3');
+ this.scene.load.audio('ui_notification_4', 'sounds/GASP_UI_Notification_4.mp3');
+ this.scene.load.audio('ui_notification_5', 'sounds/GASP_UI_Notification_5.mp3');
+ this.scene.load.audio('ui_notification_6', 'sounds/GASP_UI_Notification_6.mp3');
// GASP UI reject sound
- this.scene.load.audio('ui_reject', 'assets/sounds/GASP_UI_Reject.mp3');
+ this.scene.load.audio('ui_reject', 'sounds/GASP_UI_Reject.mp3');
// Game-specific sounds
- this.scene.load.audio('chair_roll', 'assets/sounds/chair_roll.mp3');
- this.scene.load.audio('message_received', 'assets/sounds/message_received.mp3');
+ this.scene.load.audio('chair_roll', 'sounds/chair_roll.mp3');
+ this.scene.load.audio('message_received', 'sounds/message_received.mp3');
}
/**
diff --git a/public/break_escape/js/utils/constants.js b/public/break_escape/js/utils/constants.js
index 197267c..14ae64b 100644
--- a/public/break_escape/js/utils/constants.js
+++ b/public/break_escape/js/utils/constants.js
@@ -49,7 +49,7 @@ export const GAME_CONFIG = typeof Phaser !== 'undefined' ? {
parent: 'game-container',
pixelArt: true,
loader: {
- baseURL: '/break_escape/'
+ baseURL: (window.breakEscapeConfig?.assetsPath || '/break_escape/assets') + '/'
},
scale: {
mode: Phaser.Scale.ENVELOP, // Fill entire container while maintaining aspect ratio
diff --git a/public/break_escape/test-assets.html b/public/break_escape/test-assets.html
new file mode 100644
index 0000000..ff84384
--- /dev/null
+++ b/public/break_escape/test-assets.html
@@ -0,0 +1,106 @@
+
+
+
+ Break Escape - Asset Loading Test
+
+
+
+ Break Escape - Asset Loading Test
+
+
+
+
+
diff --git a/test/controllers/break_escape/static_files_controller_test.rb b/test/controllers/break_escape/static_files_controller_test.rb
new file mode 100644
index 0000000..84865dd
--- /dev/null
+++ b/test/controllers/break_escape/static_files_controller_test.rb
@@ -0,0 +1,202 @@
+require 'test_helper'
+
+module BreakEscape
+ class StaticFilesControllerTest < ActionDispatch::IntegrationTest
+ include Engine.routes.url_helpers
+
+ # CSS file serving tests
+ test 'CSS: should serve files with correct MIME type' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ assert_equal 'text/css', response.content_type
+ end
+
+ test 'CSS: should serve with inline disposition' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ assert_match /inline/, response.headers['Content-Disposition']
+ end
+
+ test 'CSS: should return 404 for non-existent files' do
+ get '/break_escape/css/non-existent.css'
+ assert_response :not_found
+ end
+
+ # JavaScript file serving tests
+ test 'JS: should serve files with correct MIME type' do
+ get '/break_escape/js/main.js'
+ assert_response :success
+ assert_equal 'application/javascript', response.content_type
+ end
+
+ test 'JS: should serve nested files' do
+ get '/break_escape/js/utils/constants.js'
+ assert_response :success
+ assert_equal 'application/javascript', response.content_type
+ end
+
+ test 'JS: should serve core game module' do
+ get '/break_escape/js/core/game.js'
+ assert_response :success
+ assert_equal 'application/javascript', response.content_type
+ end
+
+ test 'JS: should return 404 for non-existent files' do
+ get '/break_escape/js/non-existent.js'
+ assert_response :not_found
+ end
+
+ # Asset file serving tests
+ test 'Assets: should serve audio with correct MIME type' do
+ get '/break_escape/assets/sounds/lockpick_binding.mp3'
+ assert_response :success
+ assert_equal 'audio/mpeg', response.content_type
+ end
+
+ test 'Assets: should serve PNG tiles with correct MIME type' do
+ get '/break_escape/assets/tiles/door_32.png'
+ assert_response :success
+ assert_equal 'image/png', response.content_type
+ end
+
+ test 'Assets: should serve nested files' do
+ get '/break_escape/assets/tiles/door_32.png'
+ assert_response :success
+ assert_equal 'image/png', response.content_type
+ end
+
+ test 'Assets: should return 404 for non-existent files' do
+ get '/break_escape/assets/sounds/non-existent.mp3'
+ assert_response :not_found
+ end
+
+ # HTML test page serving tests
+ test 'HTML: should serve test files with correct MIME type' do
+ get '/break_escape/test-assets.html'
+ assert_response :success
+ assert_equal 'text/html', response.content_type
+ end
+
+ test 'HTML: should return 404 for non-existent files' do
+ get '/break_escape/non-existent.html'
+ assert_response :not_found
+ end
+
+ # Route parameter capture tests
+ test 'Routes: should capture full filename with extension' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ end
+
+ test 'Routes: should capture complex paths with segments' do
+ get '/break_escape/js/utils/constants.js'
+ assert_response :success
+ end
+
+ test 'Routes: should handle files with multiple dots' do
+ get '/break_escape/assets/tiles/door_sheet_32.png'
+ assert_response :success
+ assert_equal 'image/png', response.content_type
+ end
+
+ # Security tests - directory traversal
+ test 'Security: should prevent directory traversal in CSS' do
+ get '/break_escape/css/../../config/database.yml'
+ assert_response :not_found
+ end
+
+ test 'Security: should prevent directory traversal in JS' do
+ get '/break_escape/js/../../config/secrets.yml'
+ assert_response :not_found
+ end
+
+ test 'Security: should prevent directory traversal in assets' do
+ get '/break_escape/assets/../../config/database.yml'
+ assert_response :not_found
+ end
+
+ # Phaser asset configuration
+ test 'Phaser: main JS imports GAME_CONFIG' do
+ get '/break_escape/js/main.js'
+ assert_response :success
+ assert_includes response.body, 'GAME_CONFIG'
+ end
+
+ test 'Phaser: constants define GAME_CONFIG with baseURL' do
+ get '/break_escape/js/utils/constants.js'
+ assert_response :success
+ content = response.body
+ assert_includes content, 'GAME_CONFIG'
+ assert_includes content, 'baseURL'
+ assert_includes content, '/break_escape/assets'
+ end
+
+ test 'Phaser: game.js has asset references without prefix' do
+ get '/break_escape/js/core/game.js'
+ assert_response :success
+ content = response.body
+ assert_includes content, 'this.load.audio'
+ assert content.include?('sounds/'), "Should reference sounds without assets/ prefix"
+ end
+
+ # File integrity tests
+ test 'Integrity: CSS files are non-empty' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ assert response.body.length > 0
+ end
+
+ test 'Integrity: JavaScript files are non-empty' do
+ get '/break_escape/js/main.js'
+ assert_response :success
+ assert response.body.length > 0
+ end
+
+ test 'Integrity: audio files are non-empty' do
+ get '/break_escape/assets/sounds/lockpick_binding.mp3'
+ assert_response :success
+ assert response.body.length > 0
+ end
+
+ test 'Integrity: image files are non-empty' do
+ get '/break_escape/assets/tiles/door_32.png'
+ assert_response :success
+ assert response.body.length > 0
+ end
+
+ # Response header tests
+ test 'Headers: should include Cache-Control' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ assert response.headers['Cache-Control']
+ end
+
+ test 'Headers: should set Content-Disposition to inline' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ assert_match /inline/, response.headers['Content-Disposition']
+ end
+
+ test 'Headers: should include Content-Length' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ assert response.headers['Content-Length']
+ end
+
+ # Minigame asset loading tests
+ test 'Minigame: should serve lockpicking script' do
+ get '/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js'
+ assert_response :success
+ assert_equal 'application/javascript', response.content_type
+ end
+
+ test 'Minigame: should serve lockpicking sounds' do
+ sounds = ['lockpick_binding.mp3', 'lockpick_click.mp3', 'lockpick_success.mp3']
+ sounds.each do |sound|
+ get "/break_escape/assets/sounds/#{sound}"
+ assert_response :success, "Failed to serve #{sound}"
+ assert_equal 'audio/mpeg', response.content_type
+ end
+ end
+ end
+end
diff --git a/test/dummy/log/test.log b/test/dummy/log/test.log
index 78552dd..5b53d39 100644
--- a/test/dummy/log/test.log
+++ b/test/dummy/log/test.log
@@ -2852,3 +2852,4029 @@ BreakEscape::GameTest: test_should_track_inventory
[1m[36mBreakEscape::Game Update (0.3ms)[0m [1m[33mUPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ?[0m [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"key\",\"name\":\"Test Key\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100}"], ["updated_at", "2025-11-20 21:08:52.359144"], ["id", 1]]
[1m[36mTRANSACTION (0.0ms)[0m [1m[35mRELEASE SAVEPOINT active_record_1[0m
[1m[36mTRANSACTION (0.1ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.2ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:02:30', '2025-11-21 10:02:30');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:02:30', '2025-11-21 10:02:30');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:02:30', '2025-11-21 10:02:30');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:02:30', '2025-11-21 10:02:30')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (0.7ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_return_404_for_non-existent_files
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/non-existent.html" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+
+ActionController::RoutingError (No route matches [GET] "/break_escape/non-existent.html"):
+
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_main_JS_imports_GAME_CONFIG
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.2ms)
+Completed 200 OK in 1ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_core_game_module
+------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_audio_with_correct_MIME_type
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Cache-Control
+----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_null_byte_injection
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css%00.jpg" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JPEG
+ Parameters: {"path"=>"hud.css\u0000.jpg"}
+Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Content-Length
+-----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_script
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_JS
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 1ms (Views: 0.5ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.1ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_constants_define_GAME_CONFIG_with_baseURL
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_PNG_tiles_with_correct_MIME_type
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_serve_test_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_with_inline_disposition
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_return_404_for_non-existent_files
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/js/non-existent.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"non-existent.js"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_game.js_has_asset_references_without_prefix
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_assets
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_set_Content-Disposition_to_inline
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_nested_files
+------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_handle_files_with_multiple_dots
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_sheet_32.png" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_sheet_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_sheet_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_CSS
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_audio_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_full_filename_with_extension
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_JavaScript_files_are_non-empty
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_nested_files
+--------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_files_with_correct_MIME_type
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_return_404_for_non-existent_files
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/non-existent.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"non-existent.css"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_CSS_files_are_non-empty
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_image_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_return_404_for_non-existent_files
+---------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/non-existent.mp3" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/non-existent.mp3"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_complex_paths_with_segments
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_sounds
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:02:30 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:02:35', '2025-11-21 10:02:35');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:02:35', '2025-11-21 10:02:35');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:02:35', '2025-11-21 10:02:35');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:02:35', '2025-11-21 10:02:35')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (0.8ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_return_404_for_non-existent_files
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/non-existent.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"non-existent.css"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 2ms (Views: 1.2ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_return_404_for_non-existent_files
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/js/non-existent.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"non-existent.js"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_core_game_module
+------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (3.7ms)
+Completed 200 OK in 4ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 2.7ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_full_filename_with_extension
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_PNG_tiles_with_correct_MIME_type
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_return_404_for_non-existent_files
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/non-existent.html" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+
+ActionController::RoutingError (No route matches [GET] "/break_escape/non-existent.html"):
+
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Content-Length
+-----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_game.js_has_asset_references_without_prefix
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_nested_files
+------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_image_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_serve_test_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_audio_with_correct_MIME_type
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_with_inline_disposition
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_CSS_files_are_non-empty
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_assets
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_CSS
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_nested_files
+--------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_constants_define_GAME_CONFIG_with_baseURL
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_JS
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_script
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_audio_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_null_byte_injection
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css%00.jpg" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JPEG
+ Parameters: {"path"=>"hud.css\u0000.jpg"}
+Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Cache-Control
+----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_files_with_correct_MIME_type
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_sounds
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_main_JS_imports_GAME_CONFIG
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_complex_paths_with_segments
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_return_404_for_non-existent_files
+---------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/non-existent.mp3" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/non-existent.mp3"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_set_Content-Disposition_to_inline
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_JavaScript_files_are_non-empty
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_handle_files_with_multiple_dots
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_sheet_32.png" for 127.0.0.1 at 2025-11-21 10:02:35 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_sheet_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_sheet_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:06:27', '2025-11-21 10:06:27');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:06:27', '2025-11-21 10:06:27');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:06:27', '2025-11-21 10:06:27');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:06:27', '2025-11-21 10:06:27')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (0.9ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_set_Content-Disposition_to_inline
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (1.1ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_CSS_files_are_non-empty
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_assets
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 4ms (Views: 4.0ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 2.7ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_script
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.2ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_return_404_for_non-existent_files
+---------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/non-existent.mp3" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/non-existent.mp3"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_serve_test_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_PNG_tiles_with_correct_MIME_type
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_constants_define_GAME_CONFIG_with_baseURL
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_with_inline_disposition
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_complex_paths_with_segments
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_main_JS_imports_GAME_CONFIG
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_return_404_for_non-existent_files
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/non-existent.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"non-existent.css"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_nested_files
+------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_audio_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_JS
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_handle_files_with_multiple_dots
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_sheet_32.png" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_sheet_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_sheet_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_files_with_correct_MIME_type
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Cache-Control
+----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_CSS
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_game.js_has_asset_references_without_prefix
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_sounds
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Content-Length
+-----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_image_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_return_404_for_non-existent_files
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/non-existent.html" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+
+ActionController::RoutingError (No route matches [GET] "/break_escape/non-existent.html"):
+
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_return_404_for_non-existent_files
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/js/non-existent.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"non-existent.js"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_nested_files
+--------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_full_filename_with_extension
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.1ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_JavaScript_files_are_non-empty
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_core_game_module
+------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_audio_with_correct_MIME_type
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:27 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.2ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:06:50', '2025-11-21 10:06:50');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:06:50', '2025-11-21 10:06:50');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:06:50', '2025-11-21 10:06:50');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:06:50', '2025-11-21 10:06:50')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (0.8ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_all_required_game_files_in_correct_order
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (1.0ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_route_constraints_correctly_capture_file_extensions
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_baseURL_prevents_duplicate_asset_paths
+-------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_complete_asset_loading_path_for_lockpicking
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_overtension.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_overtension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_overtension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_reset.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_reset.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_reset.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_set.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_set.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_set.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_tension.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_tension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_tension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+Started GET "/break_escape/assets/sounds/lockpick_wrong.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_wrong.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_wrong.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_security:_cannot_access_files_outside_break_escape_directory
+-----------------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 1ms (Views: 1.2ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_CSS_files_should_be_accessible_from_main_game
+--------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_sound_manager_module
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/sound-manager.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/sound-manager.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/sound-manager.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_minigame_starters
+-----------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/minigame-starters.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/minigame-starters.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/minigame-starters.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_all_response_headers_are_correct
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_lockpicking_minigame
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_test_asset_page_loads_correctly
+------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_asset_paths_work_without_assets_prefix_in_load_calls
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_game_core_with_asset_references
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_GAME_CONFIG_with_proper_baseURL
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:06:50 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:06:55', '2025-11-21 10:06:55');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:06:55', '2025-11-21 10:06:55');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:06:55', '2025-11-21 10:06:55');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:06:55', '2025-11-21 10:06:55')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (1.0ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_test_asset_page_loads_correctly
+------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (1.0ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_route_constraints_correctly_capture_file_extensions
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_all_response_headers_are_correct
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_security:_cannot_access_files_outside_break_escape_directory
+-----------------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 2ms (Views: 2.0ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.3ms)
+Started GET "/break_escape/js/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.2ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.2ms)
+ [1m[36mTRANSACTION (0.1ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_CSS_files_should_be_accessible_from_main_game
+--------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_all_required_game_files_in_correct_order
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_baseURL_prevents_duplicate_asset_paths
+-------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_minigame_starters
+-----------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/minigame-starters.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/minigame-starters.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/minigame-starters.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_lockpicking_minigame
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_asset_paths_work_without_assets_prefix_in_load_calls
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_complete_asset_loading_path_for_lockpicking
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_overtension.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_overtension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_overtension.mp3 (0.2ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+Started GET "/break_escape/assets/sounds/lockpick_reset.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_reset.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_reset.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_set.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_set.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_set.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_tension.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_tension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_tension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_wrong.mp3" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_wrong.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_wrong.mp3 (0.2ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.2ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_sound_manager_module
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/sound-manager.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/sound-manager.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/sound-manager.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_game_core_with_asset_references
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_GAME_CONFIG_with_proper_baseURL
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:06:55 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.2ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:07:05', '2025-11-21 10:07:05');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:07:05', '2025-11-21 10:07:05');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:07:05', '2025-11-21 10:07:05');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:07:05', '2025-11-21 10:07:05')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (1.6ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_asset_paths_work_without_assets_prefix_in_load_calls
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (1.0ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_route_constraints_correctly_capture_file_extensions
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_test_asset_page_loads_correctly
+------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_CSS_files_should_be_accessible_from_main_game
+--------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_minigame_starters
+-----------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/minigame-starters.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/minigame-starters.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/minigame-starters.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_lockpicking_minigame
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_GAME_CONFIG_with_proper_baseURL
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_all_required_game_files_in_correct_order
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_baseURL_prevents_duplicate_asset_paths
+-------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_game_core_with_asset_references
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.1ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_sound_manager_module
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/sound-manager.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/sound-manager.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/sound-manager.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_all_response_headers_are_correct
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_security:_cannot_access_files_outside_break_escape_directory
+-----------------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 1ms (Views: 1.4ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_complete_asset_loading_path_for_lockpicking
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_overtension.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_overtension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_overtension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_reset.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_reset.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_reset.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_set.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_set.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_set.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_tension.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_tension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_tension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_wrong.mp3" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_wrong.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_wrong.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:05 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:07:10', '2025-11-21 10:07:10');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:07:10', '2025-11-21 10:07:10');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:07:10', '2025-11-21 10:07:10');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:07:10', '2025-11-21 10:07:10')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (1.3ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_all_required_game_files_in_correct_order
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (1.1ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_route_constraints_correctly_capture_file_extensions
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_asset_paths_work_without_assets_prefix_in_load_calls
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_CSS_files_should_be_accessible_from_main_game
+--------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_baseURL_prevents_duplicate_asset_paths
+-------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_all_response_headers_are_correct
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_lockpicking_minigame
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_security:_cannot_access_files_outside_break_escape_directory
+-----------------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 1ms (Views: 1.2ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_game_core_with_asset_references
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_sound_manager_module
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/sound-manager.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/sound-manager.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/sound-manager.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_minigame_starters
+-----------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/minigame-starters.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/minigame-starters.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/minigame-starters.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_complete_asset_loading_path_for_lockpicking
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_overtension.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_overtension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_overtension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_reset.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_reset.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_reset.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_set.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_set.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_set.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_tension.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_tension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_tension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_wrong.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_wrong.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_wrong.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_GAME_CONFIG_with_proper_baseURL
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_test_asset_page_loads_correctly
+------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_return_404_for_non-existent_files
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/js/non-existent.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"non-existent.js"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_full_filename_with_extension
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_game.js_has_asset_references_without_prefix
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_CSS_files_are_non-empty
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_audio_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_return_404_for_non-existent_files
+---------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/non-existent.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/non-existent.mp3"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_nested_files
+--------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_serve_test_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_CSS
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_core_game_module
+------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Content-Length
+-----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_files_with_correct_MIME_type
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_sounds
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_PNG_tiles_with_correct_MIME_type
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_complex_paths_with_segments
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_audio_with_correct_MIME_type
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_nested_files
+------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_set_Content-Disposition_to_inline
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Cache-Control
+----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_constants_define_GAME_CONFIG_with_baseURL
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_handle_files_with_multiple_dots
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_sheet_32.png" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_sheet_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_sheet_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_with_inline_disposition
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_main_JS_imports_GAME_CONFIG
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_JS
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_assets
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_return_404_for_non-existent_files
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/non-existent.css" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"non-existent.css"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_script
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_image_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_return_404_for_non-existent_files
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/non-existent.html" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+
+ActionController::RoutingError (No route matches [GET] "/break_escape/non-existent.html"):
+
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_JavaScript_files_are_non-empty
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:10 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:07:38', '2025-11-21 10:07:38');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:07:38', '2025-11-21 10:07:38');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:07:38', '2025-11-21 10:07:38');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:07:38', '2025-11-21 10:07:38')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (0.9ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_asset_paths_work_without_assets_prefix_in_load_calls
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (1.1ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_CSS_files_should_be_accessible_from_main_game
+--------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_baseURL_prevents_duplicate_asset_paths
+-------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_test_asset_page_loads_correctly
+------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_all_required_game_files_in_correct_order
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_lockpicking_minigame
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 3ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 2.7ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_security:_cannot_access_files_outside_break_escape_directory
+-----------------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 2ms (Views: 1.4ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.2ms)
+Started GET "/break_escape/js/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_complete_asset_loading_path_for_lockpicking
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_overtension.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_overtension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_overtension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_reset.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_reset.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_reset.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_set.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_set.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_set.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_tension.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_tension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_tension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+Started GET "/break_escape/assets/sounds/lockpick_wrong.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_wrong.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_wrong.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_all_response_headers_are_correct
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_sound_manager_module
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/sound-manager.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/sound-manager.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/sound-manager.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_route_constraints_correctly_capture_file_extensions
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_GAME_CONFIG_with_proper_baseURL
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_game_core_with_asset_references
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_minigame_starters
+-----------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/minigame-starters.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/minigame-starters.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/minigame-starters.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_JS
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_audio_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Content-Length
+-----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_return_404_for_non-existent_files
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/js/non-existent.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"non-existent.js"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_CSS
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_game.js_has_asset_references_without_prefix
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_return_404_for_non-existent_files
+---------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/non-existent.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/non-existent.mp3"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_return_404_for_non-existent_files
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/non-existent.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"non-existent.css"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_nested_files
+------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_PNG_tiles_with_correct_MIME_type
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_sounds
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_handle_files_with_multiple_dots
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_sheet_32.png" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_sheet_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_sheet_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_serve_test_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_nested_files
+--------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_assets
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_script
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_CSS_files_are_non-empty
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_audio_with_correct_MIME_type
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_files_with_correct_MIME_type
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_JavaScript_files_are_non-empty
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_main_JS_imports_GAME_CONFIG
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_full_filename_with_extension
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_constants_define_GAME_CONFIG_with_baseURL
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_with_inline_disposition
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_core_game_module
+------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Cache-Control
+----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_image_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_return_404_for_non-existent_files
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/non-existent.html" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+
+ActionController::RoutingError (No route matches [GET] "/break_escape/non-existent.html"):
+
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_complex_paths_with_segments
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_set_Content-Disposition_to_inline
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:07:38 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:08:07', '2025-11-21 10:08:07');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:08:07', '2025-11-21 10:08:07');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:08:07', '2025-11-21 10:08:07');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:08:07', '2025-11-21 10:08:07')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (0.6ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (1.1ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_return_404_for_non-existent_files
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/js/non-existent.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"non-existent.js"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 5ms (Views: 5.2ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 3.5ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_main_JS_imports_GAME_CONFIG
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_full_filename_with_extension
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_return_404_for_non-existent_files
+---------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/non-existent.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/non-existent.mp3"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_JS
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.2ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_return_404_for_non-existent_files
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/non-existent.html" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+
+ActionController::RoutingError (No route matches [GET] "/break_escape/non-existent.html"):
+
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_complex_paths_with_segments
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_PNG_tiles_with_correct_MIME_type
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_constants_define_GAME_CONFIG_with_baseURL
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_CSS
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_serve_test_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_with_inline_disposition
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Content-Length
+-----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_core_game_module
+------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_nested_files
+--------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_set_Content-Disposition_to_inline
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_game.js_has_asset_references_without_prefix
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_handle_files_with_multiple_dots
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_sheet_32.png" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_sheet_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_sheet_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_assets
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_JavaScript_files_are_non-empty
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_sounds
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_script
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_files_with_correct_MIME_type
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_return_404_for_non-existent_files
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/non-existent.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"non-existent.css"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_CSS_files_are_non-empty
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_audio_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_nested_files
+------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_audio_with_correct_MIME_type
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Cache-Control
+----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_image_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_all_required_game_files_in_correct_order
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_all_response_headers_are_correct
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_CSS_files_should_be_accessible_from_main_game
+--------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_test_asset_page_loads_correctly
+------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_security:_cannot_access_files_outside_break_escape_directory
+-----------------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_minigame_starters
+-----------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/minigame-starters.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/minigame-starters.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/minigame-starters.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_GAME_CONFIG_with_proper_baseURL
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_route_constraints_correctly_capture_file_extensions
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_lockpicking_minigame
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_sound_manager_module
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/sound-manager.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/sound-manager.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/sound-manager.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_complete_asset_loading_path_for_lockpicking
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_overtension.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_overtension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_overtension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_reset.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_reset.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_reset.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_set.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_set.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_set.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_tension.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_tension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_tension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_wrong.mp3" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_wrong.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_wrong.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_baseURL_prevents_duplicate_asset_paths
+-------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_asset_paths_work_without_assets_prefix_in_load_calls
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_game_core_with_asset_references
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:08:07 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mActiveRecord::InternalMetadata Load (0.1ms)[0m [1m[34mSELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1[0m [[nil, "schema_sha1"]]
+ [1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1m[34mSELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+ [1m[35m (0.1ms)[0m [1m[35mPRAGMA foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = ON[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = OFF[0m
+ [1m[36mFixtures Load (0.1ms)[0m [1m[31mDELETE FROM "break_escape_demo_users";
+DELETE FROM "break_escape_missions";
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (149617800, 'test_user', '2025-11-21 10:09:28', '2025-11-21 10:09:28');
+INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-21 10:09:28', '2025-11-21 10:09:28');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (418560898, 'ceo_exfil', 'CEO Exfiltration', 'Test scenario', 1, 3, '2025-11-21 10:09:28', '2025-11-21 10:09:28');
+INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at") VALUES (636030761, 'test_unpublished', 'Unpublished Test', 'Not visible', 0, 1, '2025-11-21 10:09:28', '2025-11-21 10:09:28')[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA defer_foreign_keys = 0[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_keys = 1[0m
+ [1m[36mTRANSACTION (0.9ms)[0m [1m[36mcommit transaction[0m
+ [1m[35m (0.0ms)[0m [1m[35mPRAGMA foreign_key_check[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Cache-Control
+----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (1.0ms)
+Completed 200 OK in 2ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_nested_files
+------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_return_404_for_non-existent_files
+---------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/non-existent.mp3" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/non-existent.mp3"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 1ms (Views: 1.2ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_JS
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_serve_test_files_with_correct_MIME_type
+-------------------------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_CSS_files_are_non-empty
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_sounds
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_image_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_audio_with_correct_MIME_type
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_constants_define_GAME_CONFIG_with_baseURL
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:09:28 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_main_JS_imports_GAME_CONFIG
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Phaser:_game.js_has_asset_references_without_prefix
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_core_game_module
+------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_audio_files_are_non-empty
+---------------------------------------------------------------------------------
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Assets:_should_serve_PNG_tiles_with_correct_MIME_type
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_CSS
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_full_filename_with_extension
+------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_set_Content-Disposition_to_inline
+----------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Security:_should_prevent_directory_traversal_in_assets
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Headers:_should_include_Content-Length
+-----------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_serve_with_inline_disposition
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_nested_files
+--------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_serve_files_with_correct_MIME_type
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_JS:_should_return_404_for_non-existent_files
+-----------------------------------------------------------------------------------------
+Started GET "/break_escape/js/non-existent.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"non-existent.js"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_HTML:_should_return_404_for_non-existent_files
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/non-existent.html" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+
+ActionController::RoutingError (No route matches [GET] "/break_escape/non-existent.html"):
+
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_CSS:_should_return_404_for_non-existent_files
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/non-existent.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"non-existent.css"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Minigame:_should_serve_lockpicking_script
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_capture_complex_paths_with_segments
+-----------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Integrity:_JavaScript_files_are_non-empty
+--------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::StaticFilesControllerTest: test_Routes:_should_handle_files_with_multiple_dots
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/assets/tiles/door_sheet_32.png" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_sheet_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_sheet_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_route_constraints_correctly_capture_file_extensions
+--------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_all_response_headers_are_correct
+-------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_all_required_game_files_in_correct_order
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/main.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"main.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/main.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_lockpicking_minigame
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_sound_manager_module
+--------------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/sound-manager.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/sound-manager.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/sound-manager.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_security:_cannot_access_files_outside_break_escape_directory
+-----------------------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/js/../../config/database.yml" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/database.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/../../config/secrets.yml" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as YAML
+ Parameters: {"path"=>"../../config/secrets.yml"}
+ Rendering text template
+ Rendered text template (Duration: 0.0ms | GC: 0.0ms)
+Completed 404 Not Found in 0ms (Views: 0.1ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_baseURL_prevents_duplicate_asset_paths
+-------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+---------------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_asset_paths_work_without_assets_prefix_in_load_calls
+---------------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+--------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_CSS_files_should_be_accessible_from_main_game
+--------------------------------------------------------------------------------------------
+Started GET "/break_escape/css/hud.css" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as CSS
+ Parameters: {"path"=>"hud.css"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/css/hud.css (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_load_GAME_CONFIG_with_proper_baseURL
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/utils/constants.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"utils/constants.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/utils/constants.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_test_asset_page_loads_correctly
+------------------------------------------------------------------------------
+Started GET "/break_escape/test-assets.html" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as HTML
+ Parameters: {"filename"=>"test-assets"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/test-assets.html (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_complete_asset_loading_path_for_lockpicking
+------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"minigames/lockpicking/lockpicking-game-phaser.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_binding.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_binding.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_binding.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_click.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_click.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_click.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_overtension.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_overtension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_overtension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_reset.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_reset.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_reset.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_set.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_set.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_set.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_success.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_success.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_success.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_tension.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_tension.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_tension.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/sounds/lockpick_wrong.mp3" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as MP3
+ Parameters: {"path"=>"sounds/lockpick_wrong.mp3"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/sounds/lockpick_wrong.mp3 (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
+Started GET "/break_escape/assets/tiles/door_32.png" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as PNG
+ Parameters: {"path"=>"tiles/door_32.png"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/assets/tiles/door_32.png (0.1ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.1ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-------------------------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_game_core_with_asset_references
+-------------------------------------------------------------------------------------------
+Started GET "/break_escape/js/core/game.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"core/game.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/core/game.js (0.0ms)
+Completed 200 OK in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.2ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[36mbegin transaction[0m
+-----------------------------------------------------------------------------
+BreakEscape::AssetLoadingIntegrationTest: test_should_serve_minigame_starters
+-----------------------------------------------------------------------------
+Started GET "/break_escape/js/systems/minigame-starters.js" for 127.0.0.1 at 2025-11-21 10:09:29 +0000
+Processing by BreakEscape::StaticFilesController#serve as JS
+ Parameters: {"path"=>"systems/minigame-starters.js"}
+Sent file /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/public/break_escape/js/systems/minigame-starters.js (0.0ms)
+Completed 200 OK in 1ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.8ms)
+ [1m[36mTRANSACTION (0.0ms)[0m [1m[31mrollback transaction[0m
diff --git a/test/dummy/storage/test.sqlite3 b/test/dummy/storage/test.sqlite3
index 988655e..cad76c2 100644
Binary files a/test/dummy/storage/test.sqlite3 and b/test/dummy/storage/test.sqlite3 differ
diff --git a/test/integration/asset_loading_integration_test.rb b/test/integration/asset_loading_integration_test.rb
new file mode 100644
index 0000000..e5bc3e6
--- /dev/null
+++ b/test/integration/asset_loading_integration_test.rb
@@ -0,0 +1,142 @@
+require 'test_helper'
+
+module BreakEscape
+ class AssetLoadingIntegrationTest < ActionDispatch::IntegrationTest
+ include Engine.routes.url_helpers
+
+ test 'should load all required game files in correct order' do
+ get '/break_escape/js/main.js'
+ assert_response :success
+ assert_includes response.body, 'GAME_CONFIG'
+ end
+
+ test 'should load GAME_CONFIG with proper baseURL' do
+ get '/break_escape/js/utils/constants.js'
+ assert_response :success
+ content = response.body
+ assert_match /export const GAME_CONFIG/, content
+ assert_match /baseURL/, content
+ assert_match /\/break_escape\/assets/, content
+ end
+
+ test 'CSS files should be accessible from main game' do
+ get '/break_escape/css/hud.css'
+ assert_response :success
+ assert_equal 'text/css', response.content_type
+ end
+
+ test 'should serve game core with asset references' do
+ get '/break_escape/js/core/game.js'
+ assert_response :success
+ content = response.body
+ assert_includes content, 'preload'
+ assert_includes content, 'this.load'
+ end
+
+ test 'should serve sound manager module' do
+ get '/break_escape/js/systems/sound-manager.js'
+ assert_response :success
+ assert_equal 'application/javascript', response.content_type
+ end
+
+ test 'should serve minigame starters' do
+ get '/break_escape/js/systems/minigame-starters.js'
+ assert_response :success
+ assert_equal 'application/javascript', response.content_type
+ end
+
+ test 'should serve lockpicking minigame' do
+ get '/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js'
+ assert_response :success
+ assert_equal 'application/javascript', response.content_type
+ content = response.body
+ assert_match /baseURL/, content
+ end
+
+ test 'complete asset loading path for lockpicking' do
+ get '/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js'
+ assert_response :success
+
+ lockpick_sounds = [
+ 'lockpick_binding.mp3',
+ 'lockpick_click.mp3',
+ 'lockpick_overtension.mp3',
+ 'lockpick_reset.mp3',
+ 'lockpick_set.mp3',
+ 'lockpick_success.mp3',
+ 'lockpick_tension.mp3',
+ 'lockpick_wrong.mp3'
+ ]
+
+ lockpick_sounds.each do |sound|
+ get "/break_escape/assets/sounds/#{sound}"
+ assert_response :success, "Lockpick sound not found: #{sound}"
+ assert_equal 'audio/mpeg', response.content_type
+ end
+
+ get '/break_escape/assets/tiles/door_32.png'
+ assert_response :success
+ assert_equal 'image/png', response.content_type
+ end
+
+ test 'route constraints correctly capture file extensions' do
+ files_to_test = [
+ '/break_escape/css/hud.css',
+ '/break_escape/js/main.js',
+ '/break_escape/assets/tiles/door_32.png',
+ '/break_escape/assets/sounds/lockpick_binding.mp3'
+ ]
+
+ files_to_test.each do |file_path|
+ get file_path
+ assert_response :success, "Failed to load file with extension: #{file_path}"
+ end
+ end
+
+ test 'baseURL prevents duplicate asset paths' do
+ get '/break_escape/js/utils/constants.js'
+ assert_response :success
+ content = response.body
+ assert !content.include?('assets/assets'), "Should not have duplicate assets/ prefix"
+ end
+
+ test 'asset paths work without assets prefix in load calls' do
+ get '/break_escape/js/core/game.js'
+ assert_response :success
+ content = response.body
+ assert_match /this\.load\.audio\(['"][\w_]+['"],\s*['"]sounds\//, content
+ end
+
+ test 'security: cannot access files outside break_escape directory' do
+ get '/break_escape/css/../../config/secrets.yml'
+ assert_response :not_found
+
+ get '/break_escape/js/../../config/database.yml'
+ assert_response :not_found
+
+ get '/break_escape/assets/../../config/secrets.yml'
+ assert_response :not_found
+ end
+
+ test 'all response headers are correct' do
+ [
+ '/break_escape/css/hud.css',
+ '/break_escape/js/main.js',
+ '/break_escape/assets/sounds/lockpick_binding.mp3'
+ ].each do |path|
+ get path
+ assert_response :success
+ assert response.headers['Content-Type'], "Missing Content-Type for #{path}"
+ assert_match /inline/, response.headers['Content-Disposition']
+ assert response.headers['Content-Length']
+ end
+ end
+
+ test 'test asset page loads correctly' do
+ get '/break_escape/test-assets.html'
+ assert_response :success
+ assert_equal 'text/html', response.content_type
+ assert_includes response.body, 'Asset Loading Test'
+ end
+ end
+end
diff --git a/test/unit/static_files_controller_unit_test.rb b/test/unit/static_files_controller_unit_test.rb
new file mode 100644
index 0000000..4d05eb9
--- /dev/null
+++ b/test/unit/static_files_controller_unit_test.rb
@@ -0,0 +1,106 @@
+require 'test_helper'
+
+module BreakEscape
+ class StaticFilesControllerUnitTest < ActiveSupport::TestCase
+ # Test the content type determination logic in isolation
+
+ setup do
+ @controller = StaticFilesController.new
+ end
+
+ test 'determines CSS content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.css')
+ assert_equal 'text/css', content_type
+ end
+
+ test 'determines JavaScript content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.js')
+ assert_equal 'application/javascript', content_type
+ end
+
+ test 'determines HTML content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.html')
+ assert_equal 'text/html', content_type
+ end
+
+ test 'determines JSON content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.json')
+ assert_equal 'application/json', content_type
+ end
+
+ test 'determines PNG content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.png')
+ assert_equal 'image/png', content_type
+ end
+
+ test 'determines JPEG content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.jpg')
+ assert_equal 'image/jpeg', content_type
+ end
+
+ test 'determines GIF content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.gif')
+ assert_equal 'image/gif', content_type
+ end
+
+ test 'determines SVG content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.svg')
+ assert_equal 'image/svg+xml', content_type
+ end
+
+ test 'determines MP3 content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.mp3')
+ assert_equal 'audio/mpeg', content_type
+ end
+
+ test 'determines WAV content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.wav')
+ assert_equal 'audio/wav', content_type
+ end
+
+ test 'determines OGG content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.ogg')
+ assert_equal 'audio/ogg', content_type
+ end
+
+ test 'determines WOFF font content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/font.woff')
+ assert_equal 'font/woff', content_type
+ end
+
+ test 'determines WOFF2 font content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/font.woff2')
+ assert_equal 'font/woff2', content_type
+ end
+
+ test 'determines TTF font content type' do
+ content_type = @controller.send(:determine_content_type, '/path/to/font.ttf')
+ assert_equal 'font/ttf', content_type
+ end
+
+ test 'is case insensitive' do
+ content_type = @controller.send(:determine_content_type, '/path/to/FILE.CSS')
+ assert_equal 'text/css', content_type
+
+ content_type = @controller.send(:determine_content_type, '/path/to/FILE.JS')
+ assert_equal 'application/javascript', content_type
+
+ content_type = @controller.send(:determine_content_type, '/path/to/FILE.PNG')
+ assert_equal 'image/png', content_type
+ end
+
+ test 'handles multiple dots in filename' do
+ # Files like door_sheet_32.png should work
+ content_type = @controller.send(:determine_content_type, '/path/to/door_sheet_32.png')
+ assert_equal 'image/png', content_type
+
+ content_type = @controller.send(:determine_content_type, '/path/to/lockpick_binding.mp3')
+ assert_equal 'audio/mpeg', content_type
+ end
+
+ test 'returns octet-stream for unknown extensions' do
+ content_type = @controller.send(:determine_content_type, '/path/to/file.unknown')
+ assert_equal 'application/octet-stream', content_type
+ end
+ end
+end