From ca44cef068452415ad595be05c7c03ac353caf09 Mon Sep 17 00:00:00 2001 From: "Z. Cliffe Schreuders" Date: Fri, 28 Nov 2025 17:41:17 +0000 Subject: [PATCH] Enhance game setup for VM and standalone modes - Updated `GamesController` to use `current_player` for VM set retrieval. - Improved `MissionsController` to handle redirection for both Hacktivity and standalone modes. - Modified `new.html.erb` to include UI for standalone flag input alongside VM set selection. - Added new CSS styles for standalone mode instructions and flags input form. - Introduced new mission configuration for the SecGen VM Lab, integrating VM and flag capture elements. --- .../break_escape/games_controller.rb | 2 +- .../break_escape/missions_controller.rb | 9 +- app/views/break_escape/games/new.html.erb | 138 +- .../flag-station/flag-station-minigame.js | 2 +- .../vm-launcher/vm-launcher-minigame.js | 44 +- scenarios/secgen_vm_lab/mission.json | 20 + scenarios/secgen_vm_lab/scenario.json.erb | 109 + test/dummy/log/test.log | 2515 +++++++++++++++++ test/dummy/storage/test.sqlite3 | Bin 94208 -> 94208 bytes test/fixtures/break_escape_missions.yml | 11 + 10 files changed, 2827 insertions(+), 23 deletions(-) create mode 100644 scenarios/secgen_vm_lab/mission.json create mode 100644 scenarios/secgen_vm_lab/scenario.json.erb diff --git a/app/controllers/break_escape/games_controller.rb b/app/controllers/break_escape/games_controller.rb index 3bbb7e2..dd685c1 100644 --- a/app/controllers/break_escape/games_controller.rb +++ b/app/controllers/break_escape/games_controller.rb @@ -11,7 +11,7 @@ module BreakEscape authorize @mission, :create_game? if defined?(Pundit) if @mission.requires_vms? - @available_vm_sets = @mission.valid_vm_sets_for_user(current_user) + @available_vm_sets = @mission.valid_vm_sets_for_user(current_player) @existing_games = Game.where(player: current_player, mission: @mission) end end diff --git a/app/controllers/break_escape/missions_controller.rb b/app/controllers/break_escape/missions_controller.rb index 8e9c071..c9ea447 100644 --- a/app/controllers/break_escape/missions_controller.rb +++ b/app/controllers/break_escape/missions_controller.rb @@ -20,10 +20,11 @@ module BreakEscape @mission = Mission.find(params[:id]) authorize @mission if defined?(Pundit) - if @mission.requires_vms? && BreakEscape::Mission.hacktivity_mode? - # VM missions need explicit game creation with VM set selection - # Redirect to games#new which shows VM set selection UI - # Use explicit path instead of route helper to ensure it works in engine context + if @mission.requires_vms? + # VM missions (Hacktivity or standalone) need explicit setup + # Redirect to games#new which shows appropriate UI: + # - Hacktivity mode: VM set selection + # - Standalone mode: Flag input form redirect_to "/break_escape/games/new?mission_id=#{@mission.id}" else # Legacy behavior for non-VM missions - auto-create game diff --git a/app/views/break_escape/games/new.html.erb b/app/views/break_escape/games/new.html.erb index 4109c01..0d0cf75 100644 --- a/app/views/break_escape/games/new.html.erb +++ b/app/views/break_escape/games/new.html.erb @@ -1,4 +1,4 @@ -<%# Game Setup / VM Set Selection Page %> +<%# Game Setup / VM Set Selection or Standalone Flags Page %>

<%= @mission.display_name %>

@@ -6,10 +6,12 @@
<% if @mission.requires_vms? %> -
-

Select VM Environment

- - <% if @available_vm_sets.any? %> + <% if BreakEscape::Mission.hacktivity_mode? %> + <%# Hacktivity Mode: VM Set Selection %> +
+

Select VM Environment

+ + <% if @available_vm_sets.any? %>
<% @available_vm_sets.each do |vm_set| %> <%= form_with url: break_escape.games_path, method: :post, local: true, class: 'vm-set-form' do |f| %> @@ -48,9 +50,8 @@

Continue Existing Game

<% @existing_games.each do |game| %> - <%= link_to game_path(game), class: "btn btn-secondary existing-game-btn" do %> + <%= link_to "/break_escape/games/#{game.id}", class: "btn btn-secondary existing-game-btn" do %> Continue game started <%= time_ago_in_words(game.started_at) %> ago - <%= game.status %> <% end %> <% end %>
@@ -65,7 +66,43 @@ <%= link_to "← Back to Missions", missions_path, class: "btn btn-secondary" %>
<% end %> -
+
+ + <% else %> + <%# Standalone Mode: Flags Input Form %> +
+

Configure Test Flags

+

Enter the flags you expect to find in this scenario (comma-separated). These will be validated when you submit them at the flag station during gameplay.

+ + <%= form_with url: break_escape.games_path, method: :post, local: true, class: 'flags-form' do |f| %> + <%= f.hidden_field :mission_id, value: @mission.id %> + +
+ + <%= f.text_area :standalone_flags, + id: 'standalone_flags', + placeholder: "flag{example1}, flag{example2}, flag{example3}", + rows: 8, + class: 'flags-textarea' %> +

Format: flag{...}, separated by commas

+
+ +
+

💡 How it works:

+
    +
  • Enter the flags you plan to capture in this scenario
  • +
  • During the game, navigate to the Flag Station
  • +
  • Submit your captured flags to verify them
  • +
  • Receive rewards for correct flags
  • +
+
+ + <%= f.submit "Start Mission", class: "btn btn-primary btn-large" %> + <% end %> + + <%= link_to "← Back to Missions", missions_path, class: "btn btn-secondary" %> +
+ <% end %> <% else %> <%# Non-VM mission - just start %> @@ -108,6 +145,88 @@ padding-bottom: 10px; margin-bottom: 20px; } + + .standalone-flags h2 { + color: #00ff00; + border-bottom: 2px solid #00ff00; + padding-bottom: 10px; + margin-bottom: 20px; + } + + .flags-help { + color: #cccccc; + font-family: 'VT323', monospace; + font-size: 14px; + margin-bottom: 20px; + line-height: 1.5; + } + + .form-group { + margin-bottom: 20px; + } + + .form-group label { + display: block; + color: #00ff00; + margin-bottom: 10px; + font-size: 14px; + font-weight: bold; + } + + .flags-textarea { + width: 100%; + background: #000; + border: 2px solid #00ff00; + color: #00ff00; + padding: 12px; + font-family: 'Courier New', monospace; + font-size: 14px; + box-sizing: border-box; + resize: vertical; + } + + .flags-textarea:focus { + outline: none; + border-color: #00ff00; + box-shadow: 0 0 5px rgba(0, 255, 0, 0.5); + } + + .form-hint { + color: #888; + font-size: 12px; + margin-top: 8px; + } + + .form-hint code { + background: #1a1a1a; + padding: 2px 6px; + border-radius: 2px; + } + + .flags-info { + background: rgba(0, 255, 0, 0.05); + border: 1px solid #00ff00; + padding: 15px; + margin: 20px 0; + color: #cccccc; + font-size: 13px; + line-height: 1.5; + } + + .flags-info p { + margin: 0 0 10px 0; + color: #00ff00; + } + + .flags-info ul { + margin: 10px 0 0 20px; + padding: 0; + } + + .flags-info li { + margin: 5px 0; + color: #cccccc; + } .vm-set-list { display: flex; @@ -181,6 +300,7 @@ cursor: pointer; text-decoration: none; display: inline-block; + margin-top: 10px; } .btn:hover { @@ -196,6 +316,8 @@ background: #333; color: #00ff00; border-color: #00ff00; + width: auto; + margin-right: 10px; } .btn-secondary:hover { diff --git a/public/break_escape/js/minigames/flag-station/flag-station-minigame.js b/public/break_escape/js/minigames/flag-station/flag-station-minigame.js index d986b0e..ac8c573 100644 --- a/public/break_escape/js/minigames/flag-station/flag-station-minigame.js +++ b/public/break_escape/js/minigames/flag-station/flag-station-minigame.js @@ -14,7 +14,7 @@ export class FlagStationMinigame extends MinigameScene { this.stationName = params.stationName || 'Flag Submission Terminal'; this.expectedFlags = params.flags || []; this.submittedFlags = params.submittedFlags || window.gameState?.submittedFlags || []; - this.gameId = params.gameId || window.gameConfig?.gameId; + this.gameId = params.gameId || window.breakEscapeConfig?.gameId || window.gameConfig?.gameId; this.isSubmitting = false; } diff --git a/public/break_escape/js/minigames/vm-launcher/vm-launcher-minigame.js b/public/break_escape/js/minigames/vm-launcher/vm-launcher-minigame.js index 45e7864..c083d16 100644 --- a/public/break_escape/js/minigames/vm-launcher/vm-launcher-minigame.js +++ b/public/break_escape/js/minigames/vm-launcher/vm-launcher-minigame.js @@ -205,6 +205,28 @@ export class VmLauncherMinigame extends MinigameScene { color: #ffaa00; } + .vm-names { + display: flex; + gap: 15px; + justify-content: center; + margin: 20px 0; + } + + .vm-name-badge { + background: #00aa00; + color: #000; + padding: 12px 24px; + font-weight: bold; + font-size: 16px; + border: 2px solid #000; + font-family: 'Courier New', monospace; + } + + .standalone-instructions h3 { + color: #00ff00; + margin-top: 0; + } + .standalone-instructions ol { margin: 0; padding-left: 20px; @@ -242,9 +264,9 @@ export class VmLauncherMinigame extends MinigameScene { `; } else { return ` -
-

Standalone Mode

-

VMs are not available in standalone mode.

+
+

VM Terminal

+

You've discovered a computer terminal in the game. To interact with it, you need to launch the virtual machines on your local system.

${this.buildStandaloneInstructions()}
`; @@ -300,13 +322,17 @@ export class VmLauncherMinigame extends MinigameScene { buildStandaloneInstructions() { return `
-

VirtualBox Instructions

+

Load These VMs in VirtualBox:

+
+
kali
+
desktop
+
    -
  1. Open VirtualBox on your local machine
  2. -
  3. Import the mission VM file (.ova)
  4. -
  5. Start the VM and wait for it to boot
  6. -
  7. Note the VM's IP address (shown on login screen)
  8. -
  9. Return to this game and complete objectives
  10. +
  11. Open VirtualBox on your local machine
  12. +
  13. Import the kali and desktop VMs (.ova files)
  14. +
  15. Start both VMs and wait for them to boot
  16. +
  17. Note their IP addresses
  18. +
  19. Return to this game to complete the mission
`; diff --git a/scenarios/secgen_vm_lab/mission.json b/scenarios/secgen_vm_lab/mission.json new file mode 100644 index 0000000..050cd60 --- /dev/null +++ b/scenarios/secgen_vm_lab/mission.json @@ -0,0 +1,20 @@ +{ + "display_name": "SecGen VM Lab - Linux Introduction", + "description": "This mission demonstrates VM integration with BreakEscape. Launch the provided VMs (desktop and kali) and capture flags from the SecGen environment. Learn basic Linux attack techniques in a controlled lab setting.", + "difficulty_level": 2, + "secgen_scenario": "labs/introducing_attacks/1_intro_linux.xml", + "collection": "vm_labs", + "cybok": [ + { + "ka": "SS", + "topic": "System Security", + "keywords": ["Virtual machines", "Linux security", "Attack vectors"] + }, + { + "ka": "F", + "topic": "Forensics", + "keywords": ["Evidence collection", "Log analysis"] + } + ] +} + diff --git a/scenarios/secgen_vm_lab/scenario.json.erb b/scenarios/secgen_vm_lab/scenario.json.erb new file mode 100644 index 0000000..d3f1614 --- /dev/null +++ b/scenarios/secgen_vm_lab/scenario.json.erb @@ -0,0 +1,109 @@ +{ + "scenario_brief": "Welcome to the SecGen VM Lab! This environment is designed to teach you about Linux security and attack techniques. You have access to two VMs:\n\n• **kali** - Attacker machine with penetration testing tools\n• **desktop** - Target system running vulnerable services\n\nYour mission is to launch these VMs, exploit vulnerabilities, and capture flags demonstrating your understanding of the attack vectors.", + "endGoal": "Successfully launch the 'kali' and 'desktop' VMs, perform attacks, and capture all available flags to complete the lab.", + "startRoom": "lab_entrance", + "startItemsInInventory": [], + "rooms": { + "lab_entrance": { + "type": "room_reception", + "connections": { + "north": "lab_workstation" + }, + "locked": false, + "objects": [ + { + "type": "notes", + "name": "Lab Welcome Guide", + "takeable": true, + "readable": true, + "text": "Welcome to the SecGen Linux Introduction Lab!\n\nSTART HERE:\n1. Interact with the VM LAUNCHER TERMINAL\n2. Select and launch the 'kali' VM first\n3. Then launch the 'desktop' VM\n\nWhat each VM does:\n • kali - Your attack platform (Kali Linux with hacking tools)\n • desktop - The target system (vulnerable Linux services)\n\nOnce running:\n1. Connect to the desktop VM from kali\n2. Find and exploit vulnerabilities\n3. Capture flags along the way\n4. Submit flags at the FLAG STATION TERMINAL\n\nEach flag you submit will unlock rewards and progression.\n\nGood luck, and learn responsibly!", + "observations": "A comprehensive guide to the lab environment" + }, + { + "type": "notes", + "name": "Lab Rules", + "takeable": true, + "readable": true, + "text": "Lab Rules & Information:\n\n- VMs are automatically destroyed after 1 hour of inactivity\n- Screenshots and evidence capture recommended\n- All traffic is logged for learning purposes\n- Contact lab administrator if VMs fail to start\n- Estimated time: 30-45 minutes\n- Difficulty: Beginner to Intermediate", + "observations": "Important lab operational information" + } + ] + }, + "lab_workstation": { + "type": "room_office", + "connections": { + "south": "lab_entrance", + "east": "flag_room" + }, + "locked": false, + "objects": [ + { + "type": "vm-launcher", + "id": "vm_launcher_1", + "name": "Kali Console Terminal", + "takeable": false, + "observations": "A terminal interface for accessing the Kali Linux VM. Ready to launch.", + "hacktivityMode": <%= vm_context && vm_context['hacktivity_mode'] ? 'true' : 'false' %>, + "vms": <%= vm_context && vm_context['vms'] ? vm_context['vms'].to_json : '[{"id":1,"title":"kali","ip":"192.168.1.10","enable_console":true}]' %> + }, + { + "type": "vm-launcher", + "id": "vm_launcher_2", + "name": "Desktop Lab Terminal", + "takeable": false, + "observations": "A terminal interface for accessing the Desktop Linux VM. Ready to launch.", + "hacktivityMode": <%= vm_context && vm_context['hacktivity_mode'] ? 'true' : 'false' %>, + "vms": <%= vm_context && vm_context['vms'] ? vm_context['vms'].to_json : '[{"id":2,"title":"desktop","ip":"192.168.1.20","enable_console":true}]' %> + }, + { + "type": "notes", + "name": "Attack Hints", + "takeable": true, + "readable": true, + "text": "Attack Strategy for kali → desktop:\n\n1. FROM KALI - Reconnaissance:\n - Use 'nmap' on desktop to scan open ports\n - Example: nmap -sV \n - Identify running services and versions\n - Research known vulnerabilities\n\n2. FROM KALI - Exploitation:\n - Look for weak credentials on desktop\n - Try common default passwords\n - Use Metasploit or manual exploitation\n - Escalate privileges if needed\n\n3. ON DESKTOP - Flag Capture:\n - Flags typically located in:\n /flag.txt (root flag)\n /home/*/flag.txt (user flags)\n /etc/shadow or /etc/passwd\n Database files (/var/lib/mysql/)\n\n4. Submit Flags:\n - Return to this game\n - Find the FLAG STATION TERMINAL\n - Enter captured flags (format: flag{...})\n - Receive points and unlock rewards", + "observations": "Strategic guidance for completing the lab objectives" + } + ] + }, + "flag_room": { + "type": "room_office", + "connections": { + "west": "lab_workstation" + }, + "locked": false, + "objects": [ + { + "type": "flag-station", + "id": "flag_station_1", + "name": "Flag Submission Terminal", + "takeable": false, + "observations": "A secure terminal for submitting captured flags. All submissions are verified against the lab database.", + "flags": <%= vm_context && vm_context['flags'] ? vm_context['flags'].map { |f| f['value'] }.to_json : '[]' %>, + "flagRewards": { + "default_reward": { + "type": "emit_event", + "event_name": "flag_captured" + } + } + }, + { + "type": "notes", + "name": "Flag Format", + "takeable": true, + "readable": true, + "text": "Flag Format Information:\n\nFlags in this lab follow the standard CTF format:\n flag{...}\n\nCommon flag locations:\n - /flag.txt\n - /root/flag.txt\n - /home/user/flag.txt\n - Environment variables\n - Application data\n\nWhen submitting:\n1. Enter the complete flag text (including 'flag{}' wrapper)\n2. Click SUBMIT\n3. Wait for verification\n4. Receive confirmation and rewards\n\nYou may submit multiple flags.\nAlready-submitted flags cannot be re-submitted.", + "observations": "Guide on flag capture and submission" + }, + { + "type": "notes", + "name": "Progress Tracker", + "takeable": true, + "readable": true, + "text": "Lab Progress Tracking:\n\nTotal Flags Available: Multiple (see Flag Station for exact count)\n\nObjectives:\n□ Launch Kali VM\n□ Launch Desktop VM\n□ Complete reconnaissance\n□ Identify vulnerabilities\n□ Perform exploitation\n□ Capture flags\n□ Submit all flags\n\nEstimated Points:\n- Each flag: 10-50 points (varies by difficulty)\n- Lab completion bonus: 25 points\n- Documentation bonus: 10 points\n\nYour progress is auto-saved with each flag submission.", + "observations": "Real-time progress tracking for lab completion" + } + ] + } + } +} + diff --git a/test/dummy/log/test.log b/test/dummy/log/test.log index 5b24ebc..b88e53f 100644 --- a/test/dummy/log/test.log +++ b/test/dummy/log/test.log @@ -50838,3 +50838,2518 @@ BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:26:18.667896"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:26:18.667838"], ["updated_at", "2025-11-28 16:26:18.667838"], ["objectives_completed", 0], ["tasks_completed", 0]] TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "environment"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC +Migrating to CreateSecgenVmLabMission (20251128000002) + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "environment"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC +Migrating to CreateSecgenVmLabMission (20251128000002) + ActiveRecord::InternalMetadata Load (0.0ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "environment"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC +Migrating to CreateSecgenVmLabMission (20251128000002) + TRANSACTION (0.0ms) begin transaction +  (0.1ms) SELECT COUNT(*) FROM break_escape_missions WHERE name = 'secgen_vm_lab' + TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.0ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + TRANSACTION (0.0ms) begin transaction +  (0.1ms) PRAGMA foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys = ON +  (0.0ms) PRAGMA foreign_keys = OFF + Fixtures Load (0.1ms) DELETE 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-28 16:48:23', '2025-11-28 16:48:23'); +INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-28 16:48:23', '2025-11-28 16:48:23'); +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-28 16:48:23', '2025-11-28 16:48:23'); +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-28 16:48:23', '2025-11-28 16:48:23'); +INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at", "secgen_scenario", "collection") VALUES (899573729, 'secgen_vm_lab', 'SecGen VM Lab - Linux Introduction', 'Test VM and flag integration with SecGen scenario', 1, 2, '2025-11-28 16:48:23', '2025-11-28 16:48:23', 'labs/introducing_attacks/1_intro_linux.xml', 'vm_labs') +  (0.0ms) PRAGMA defer_foreign_keys = 0 +  (0.0ms) PRAGMA foreign_keys = 1 + TRANSACTION (0.8ms) commit transaction +  (0.0ms) PRAGMA foreign_key_check + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_ink_endpoint_should_require_npc_parameter +-------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.1ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.085461"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.085377"], ["updated_at", "2025-11-28 16:48:23.085377"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 400 Bad Request in 3ms (Views: 0.1ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.097138"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.097086"], ["updated_at", "2025-11-28 16:48:23.097086"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------- +BreakEscape::GamesControllerTest: test_should_show_game +------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.098414"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.098374"], ["updated_at", "2025-11-28 16:48:23.098374"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 1.5ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.7ms | GC: 0.0ms) +Completed 200 OK in 5ms (Views: 2.9ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_inject_game_configuration +---------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.106121"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.106077"], ["updated_at", "2025-11-28 16:48:23.106077"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.2ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_non-existent_NPC +------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.109021"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.108956"], ["updated_at", "2025-11-28 16:48:23.108956"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=non-existent" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"non-existent", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: non-existent +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_inventory_endpoint_should_add_items +-------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.111283"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.111242"], ["updated_at", "2025-11-28 16:48:23.111242"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Update (0.1ms) UPDATE "break_escape_games" SET "scenario_data" = ?, "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[{\"id\":\"note_1\",\"type\":\"note\",\"name\":\"Test Note\",\"takeable\":true}]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:48:23.111864"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/inventory" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#inventory as HTML + Parameters: {"action_type"=>"add", "item"=>{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}, "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] inventory endpoint: action=add, item=#"note", "name"=>"Test Note", "id"=>"note_1"} permitted: false> +[BreakEscape] validate_item_collectible: type=note, id=note_1, name=Test Note +[BreakEscape] Item collection valid: note +[BreakEscape] Adding item to inventory: note / Test Note + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"note\",\"name\":\"Test Note\",\"id\":\"note_1\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:48:23.115356"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +[BreakEscape] Item added successfully. Current inventory: [{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_reject_invalid_attempts +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.116700"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.116660"], ["updated_at", "2025-11-28 16:48:23.116660"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"room", "targetId"=>"office", "attempt"=>"wrong_code", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=room, id=office, attempt=wrong_code, method=pin +[BreakEscape] Object not found: office +Completed 422 Unprocessable Content in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_scenario_endpoint_should_return_JSON +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.118793"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.118755"], ["updated_at", "2025-11-28 16:48:23.118755"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/scenario" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#scenario as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_sync_state_should_update_player_state_for_current_room +--------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.120868"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.120831"], ["updated_at", "2025-11-28 16:48:23.120831"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started PUT "/break_escape/games/1/sync_state" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#sync_state as HTML + Parameters: {"currentRoom"=>"reception", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_NPC_without_story_file +------------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.123571"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.123532"], ["updated_at", "2025-11-28 16:48:23.123532"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=missing-npc" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"missing-npc", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: missing-npc +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_return_HTML_with_game_container +---------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.125816"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.125774"], ["updated_at", "2025-11-28 16:48:23.125774"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.2ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_accept_correct_pin_code +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.129004"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.128960"], ["updated_at", "2025-11-28 16:48:23.128960"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"door", "targetId"=>"office", "attempt"=>"1234", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=door, id=office, attempt=1234, method=pin +[BreakEscape] Room data: locked=true, lockType=pin, requires=1234 +[BreakEscape] Room is LOCKED, method must be valid: pin +[BreakEscape] pin validation result: true +[BreakEscape] validate_unlock returning: true + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\",\"office\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:48:23.130658"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------ +BreakEscape::MissionsControllerTest: test_index_should_return_HTML_with_mission_list +------------------------------------------------------------------------------------ +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.2ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 8.9ms | GC: 2.7ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 8.9ms | GC: 2.7ms) +Completed 200 OK in 10ms (Views: 8.8ms | ActiveRecord: 0.3ms (5 queries, 1 cached) | GC: 2.7ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_get_index +---------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.9ms | GC: 0.1ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.0ms | GC: 0.1ms) +Completed 200 OK in 1ms (Views: 1.0ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +----------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_show_published_mission +----------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.147458"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.146776"], ["updated_at", "2025-11-28 16:48:23.146776"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 2ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_index_should_display_published_missions +--------------------------------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.0ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.9ms | GC: 0.1ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.9ms | GC: 0.1ms) +Completed 200 OK in 1ms (Views: 0.9ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_create_game_and_redirect_when_showing_mission +---------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:48:23 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.1ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:48:23.159614"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:48:23.158518"], ["updated_at", "2025-11-28 16:48:23.158518"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 4ms (ActiveRecord: 0.4ms (4 queries, 0 cached) | GC: 0.1ms) + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" + TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + TRANSACTION (0.0ms) begin transaction +  (0.1ms) PRAGMA foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys = ON +  (0.0ms) PRAGMA foreign_keys = OFF + Fixtures Load (0.1ms) DELETE 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-28 16:49:48', '2025-11-28 16:49:48'); +INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-28 16:49:48', '2025-11-28 16:49:48'); +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-28 16:49:48', '2025-11-28 16:49:48'); +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-28 16:49:48', '2025-11-28 16:49:48'); +INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at", "secgen_scenario", "collection") VALUES (899573729, 'secgen_vm_lab', 'SecGen VM Lab - Linux Introduction', 'Test VM and flag integration with SecGen scenario', 1, 2, '2025-11-28 16:49:48', '2025-11-28 16:49:48', 'labs/introducing_attacks/1_intro_linux.xml', 'vm_labs') +  (0.0ms) PRAGMA defer_foreign_keys = 0 +  (0.0ms) PRAGMA foreign_keys = 1 + TRANSACTION (1.1ms) commit transaction +  (0.0ms) PRAGMA foreign_key_check + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.320534"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.320450"], ["updated_at", "2025-11-28 16:49:48.320450"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_sync_state_should_update_player_state_for_current_room +--------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.321984"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.321944"], ["updated_at", "2025-11-28 16:49:48.321944"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started PUT "/break_escape/games/1/sync_state" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#sync_state as HTML + Parameters: {"currentRoom"=>"reception", "id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 4ms (Views: 0.1ms | ActiveRecord: 0.2ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_NPC_without_story_file +------------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.335111"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.335068"], ["updated_at", "2025-11-28 16:49:48.335068"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=missing-npc" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"missing-npc", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: missing-npc +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_inject_game_configuration +---------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.337407"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.337368"], ["updated_at", "2025-11-28 16:49:48.337368"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 1.5ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.7ms | GC: 0.0ms) +Completed 200 OK in 5ms (Views: 2.9ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_scenario_endpoint_should_return_JSON +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.344684"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.344639"], ["updated_at", "2025-11-28 16:49:48.344639"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/scenario" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#scenario as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 200 OK in 1ms (Views: 0.1ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_reject_invalid_attempts +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.347076"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.347038"], ["updated_at", "2025-11-28 16:49:48.347038"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"room", "targetId"=>"office", "attempt"=>"wrong_code", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=room, id=office, attempt=wrong_code, method=pin +[BreakEscape] Object not found: office +Completed 422 Unprocessable Content in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------- +BreakEscape::GamesControllerTest: test_should_show_game +------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.349280"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.349241"], ["updated_at", "2025-11-28 16:49:48.349241"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.1ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_accept_correct_pin_code +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.351770"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.351731"], ["updated_at", "2025-11-28 16:49:48.351731"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"door", "targetId"=>"office", "attempt"=>"1234", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=door, id=office, attempt=1234, method=pin +[BreakEscape] Room data: locked=true, lockType=pin, requires=1234 +[BreakEscape] Room is LOCKED, method must be valid: pin +[BreakEscape] pin validation result: true +[BreakEscape] validate_unlock returning: true + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\",\"office\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:49:48.353333"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_inventory_endpoint_should_add_items +-------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.354684"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.354644"], ["updated_at", "2025-11-28 16:49:48.354644"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Update (0.1ms) UPDATE "break_escape_games" SET "scenario_data" = ?, "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[{\"id\":\"note_1\",\"type\":\"note\",\"name\":\"Test Note\",\"takeable\":true}]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:49:48.355207"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/inventory" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#inventory as HTML + Parameters: {"action_type"=>"add", "item"=>{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}, "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] inventory endpoint: action=add, item=#"note", "name"=>"Test Note", "id"=>"note_1"} permitted: false> +[BreakEscape] validate_item_collectible: type=note, id=note_1, name=Test Note +[BreakEscape] Item collection valid: note +[BreakEscape] Adding item to inventory: note / Test Note + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"note\",\"name\":\"Test Note\",\"id\":\"note_1\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:49:48.356787"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +[BreakEscape] Item added successfully. Current inventory: [{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_return_HTML_with_game_container +---------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.358132"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.358092"], ["updated_at", "2025-11-28 16:49:48.358092"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.1ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_ink_endpoint_should_require_npc_parameter +-------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.361350"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.361306"], ["updated_at", "2025-11-28 16:49:48.361306"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 400 Bad Request in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_non-existent_NPC +------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.363478"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.363438"], ["updated_at", "2025-11-28 16:49:48.363438"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=non-existent" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"non-existent", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: non-existent +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +----------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_show_published_mission +----------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.370518"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.369637"], ["updated_at", "2025-11-28 16:49:48.369637"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 3ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 0.2ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_create_game_and_redirect_when_showing_mission +---------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:49:48.374180"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:49:48.373384"], ["updated_at", "2025-11-28 16:49:48.373384"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 2ms (ActiveRecord: 0.2ms (4 queries, 0 cached) | GC: 0.1ms) + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_index_should_display_published_missions +--------------------------------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.2ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 5.9ms | GC: 0.1ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 6.0ms | GC: 0.1ms) +Completed 200 OK in 6ms (Views: 5.9ms | ActiveRecord: 0.3ms (5 queries, 1 cached) | GC: 0.1ms) + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------ +BreakEscape::MissionsControllerTest: test_index_should_return_HTML_with_mission_list +------------------------------------------------------------------------------------ +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.1ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 1.2ms | GC: 0.1ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.3ms | GC: 0.1ms) +Completed 200 OK in 2ms (Views: 1.3ms | ActiveRecord: 0.2ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_get_index +---------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:49:48 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.1ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 1.0ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.1ms | GC: 0.0ms) +Completed 200 OK in 2ms (Views: 1.1ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + TRANSACTION (0.0ms) begin transaction +  (0.1ms) PRAGMA foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys = ON +  (0.0ms) PRAGMA foreign_keys = OFF + Fixtures Load (0.1ms) DELETE 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-28 16:52:52', '2025-11-28 16:52:52'); +INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-28 16:52:52', '2025-11-28 16:52:52'); +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-28 16:52:52', '2025-11-28 16:52:52'); +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-28 16:52:52', '2025-11-28 16:52:52'); +INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at", "secgen_scenario", "collection") VALUES (899573729, 'secgen_vm_lab', 'SecGen VM Lab - Linux Introduction', 'Test VM and flag integration with SecGen scenario', 1, 2, '2025-11-28 16:52:52', '2025-11-28 16:52:52', 'labs/introducing_attacks/1_intro_linux.xml', 'vm_labs') +  (0.0ms) PRAGMA defer_foreign_keys = 0 +  (0.0ms) PRAGMA foreign_keys = 1 + TRANSACTION (0.9ms) commit transaction +  (0.0ms) PRAGMA foreign_key_check + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_ink_endpoint_should_require_npc_parameter +-------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.527844"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.527757"], ["updated_at", "2025-11-28 16:52:52.527757"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.1ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 400 Bad Request in 3ms (Views: 0.1ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_inventory_endpoint_should_add_items +-------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.539327"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.539273"], ["updated_at", "2025-11-28 16:52:52.539273"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Update (0.1ms) UPDATE "break_escape_games" SET "scenario_data" = ?, "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[{\"id\":\"note_1\",\"type\":\"note\",\"name\":\"Test Note\",\"takeable\":true}]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:52:52.539962"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/inventory" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#inventory as HTML + Parameters: {"action_type"=>"add", "item"=>{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}, "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] inventory endpoint: action=add, item=#"note", "name"=>"Test Note", "id"=>"note_1"} permitted: false> +[BreakEscape] validate_item_collectible: type=note, id=note_1, name=Test Note +[BreakEscape] Item collection valid: note +[BreakEscape] Adding item to inventory: note / Test Note + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"note\",\"name\":\"Test Note\",\"id\":\"note_1\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:52:52.543958"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +[BreakEscape] Item added successfully. Current inventory: [{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}] +Completed 200 OK in 2ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.1ms) begin transaction +------------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_NPC_without_story_file +------------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.545477"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.545437"], ["updated_at", "2025-11-28 16:52:52.545437"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=missing-npc" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"missing-npc", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: missing-npc +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_reject_invalid_attempts +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.547834"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.547788"], ["updated_at", "2025-11-28 16:52:52.547788"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"room", "targetId"=>"office", "attempt"=>"wrong_code", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=room, id=office, attempt=wrong_code, method=pin +[BreakEscape] Object not found: office +Completed 422 Unprocessable Content in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_non-existent_NPC +------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.550003"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.549965"], ["updated_at", "2025-11-28 16:52:52.549965"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=non-existent" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"non-existent", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: non-existent +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_scenario_endpoint_should_return_JSON +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.552052"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.552012"], ["updated_at", "2025-11-28 16:52:52.552012"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/scenario" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#scenario as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_sync_state_should_update_player_state_for_current_room +--------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.554126"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.554088"], ["updated_at", "2025-11-28 16:52:52.554088"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started PUT "/break_escape/games/1/sync_state" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#sync_state as HTML + Parameters: {"currentRoom"=>"reception", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_inject_game_configuration +---------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.556876"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.556815"], ["updated_at", "2025-11-28 16:52:52.556815"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 1.5ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.7ms | GC: 0.0ms) +Completed 200 OK in 5ms (Views: 2.9ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------- +BreakEscape::GamesControllerTest: test_should_show_game +------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.564012"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.563970"], ["updated_at", "2025-11-28 16:52:52.563970"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.1ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_return_HTML_with_game_container +---------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.566559"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.566520"], ["updated_at", "2025-11-28 16:52:52.566520"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.1ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_accept_correct_pin_code +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.569471"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.569431"], ["updated_at", "2025-11-28 16:52:52.569431"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"door", "targetId"=>"office", "attempt"=>"1234", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=door, id=office, attempt=1234, method=pin +[BreakEscape] Room data: locked=true, lockType=pin, requires=1234 +[BreakEscape] Room is LOCKED, method must be valid: pin +[BreakEscape] pin validation result: true +[BreakEscape] validate_unlock returning: true + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\",\"office\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:52:52.571122"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.572565"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.572525"], ["updated_at", "2025-11-28 16:52:52.572525"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_get_index +---------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.3ms | GC: 0.1ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 8.8ms | GC: 2.8ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 8.8ms | GC: 2.8ms) +Completed 200 OK in 10ms (Views: 8.7ms | ActiveRecord: 0.3ms (5 queries, 1 cached) | GC: 2.8ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +----------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_show_published_mission +----------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.586192"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.585546"], ["updated_at", "2025-11-28 16:52:52.585546"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 2ms (ActiveRecord: 0.2ms (4 queries, 0 cached) | GC: 0.2ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_create_game_and_redirect_when_showing_mission +---------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:52:52.589408"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:52:52.588746"], ["updated_at", "2025-11-28 16:52:52.588746"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 2ms (ActiveRecord: 0.2ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------ +BreakEscape::MissionsControllerTest: test_index_should_return_HTML_with_mission_list +------------------------------------------------------------------------------------ +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 1.0ms | GC: 0.1ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.0ms | GC: 0.1ms) +Completed 200 OK in 1ms (Views: 1.1ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_index_should_display_published_missions +--------------------------------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:52:52 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.9ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.9ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.9ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + TRANSACTION (0.0ms) begin transaction +  (0.1ms) PRAGMA foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys = ON +  (0.0ms) PRAGMA foreign_keys = OFF + Fixtures Load (0.1ms) DELETE 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-28 16:54:55', '2025-11-28 16:54:55'); +INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-28 16:54:55', '2025-11-28 16:54: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-28 16:54:55', '2025-11-28 16:54: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-28 16:54:55', '2025-11-28 16:54:55'); +INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at", "secgen_scenario", "collection") VALUES (899573729, 'secgen_vm_lab', 'SecGen VM Lab - Linux Introduction', 'Test VM and flag integration with SecGen scenario', 1, 2, '2025-11-28 16:54:55', '2025-11-28 16:54:55', 'labs/introducing_attacks/1_intro_linux.xml', 'vm_labs') +  (0.0ms) PRAGMA defer_foreign_keys = 0 +  (0.0ms) PRAGMA foreign_keys = 1 + TRANSACTION (0.9ms) commit transaction +  (0.0ms) PRAGMA foreign_key_check + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_scenario_endpoint_should_return_JSON +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.1ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.733377"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.733294"], ["updated_at", "2025-11-28 16:54:55.733294"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/scenario" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#scenario as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.1ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 200 OK in 5ms (Views: 0.1ms | ActiveRecord: 0.2ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_inject_game_configuration +---------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.749126"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.749050"], ["updated_at", "2025-11-28 16:54:55.749050"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 2.3ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 2.5ms | GC: 0.0ms) +Completed 200 OK in 9ms (Views: 4.6ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_return_HTML_with_game_container +---------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.761618"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.761569"], ["updated_at", "2025-11-28 16:54:55.761569"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.1ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.765004"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.764961"], ["updated_at", "2025-11-28 16:54:55.764961"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_reject_invalid_attempts +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.766134"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.766096"], ["updated_at", "2025-11-28 16:54:55.766096"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"room", "targetId"=>"office", "attempt"=>"wrong_code", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=room, id=office, attempt=wrong_code, method=pin +[BreakEscape] Object not found: office +Completed 422 Unprocessable Content in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_NPC_without_story_file +------------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.770101"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.770061"], ["updated_at", "2025-11-28 16:54:55.770061"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=missing-npc" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"missing-npc", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: missing-npc +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_non-existent_NPC +------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.772655"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.772604"], ["updated_at", "2025-11-28 16:54:55.772604"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=non-existent" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"non-existent", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: non-existent +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_ink_endpoint_should_require_npc_parameter +-------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.775743"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.775682"], ["updated_at", "2025-11-28 16:54:55.775682"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 400 Bad Request in 1ms (Views: 0.1ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------- +BreakEscape::GamesControllerTest: test_should_show_game +------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.779637"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.779560"], ["updated_at", "2025-11-28 16:54:55.779560"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.2ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.2ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.4ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_inventory_endpoint_should_add_items +-------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.783773"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.783723"], ["updated_at", "2025-11-28 16:54:55.783723"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Update (0.1ms) UPDATE "break_escape_games" SET "scenario_data" = ?, "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[{\"id\":\"note_1\",\"type\":\"note\",\"name\":\"Test Note\",\"takeable\":true}]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:54:55.784424"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/inventory" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#inventory as HTML + Parameters: {"action_type"=>"add", "item"=>{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}, "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] inventory endpoint: action=add, item=#"note", "name"=>"Test Note", "id"=>"note_1"} permitted: false> +[BreakEscape] validate_item_collectible: type=note, id=note_1, name=Test Note +[BreakEscape] Item collection valid: note +[BreakEscape] Adding item to inventory: note / Test Note + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"note\",\"name\":\"Test Note\",\"id\":\"note_1\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:54:55.786396"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +[BreakEscape] Item added successfully. Current inventory: [{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_accept_correct_pin_code +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.787796"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.787755"], ["updated_at", "2025-11-28 16:54:55.787755"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"door", "targetId"=>"office", "attempt"=>"1234", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=door, id=office, attempt=1234, method=pin +[BreakEscape] Room data: locked=true, lockType=pin, requires=1234 +[BreakEscape] Room is LOCKED, method must be valid: pin +[BreakEscape] pin validation result: true +[BreakEscape] validate_unlock returning: true + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\",\"office\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 16:54:55.789536"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_sync_state_should_update_player_state_for_current_room +--------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.790954"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.790913"], ["updated_at", "2025-11-28 16:54:55.790913"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started PUT "/break_escape/games/1/sync_state" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::GamesController#sync_state as HTML + Parameters: {"currentRoom"=>"reception", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +----------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_show_published_mission +----------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.796243"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.795563"], ["updated_at", "2025-11-28 16:54:55.795563"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 3ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_index_should_display_published_missions +--------------------------------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.3ms | GC: 0.1ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 6.6ms | GC: 0.5ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 6.6ms | GC: 0.5ms) +Completed 200 OK in 7ms (Views: 6.5ms | ActiveRecord: 0.3ms (5 queries, 1 cached) | GC: 0.5ms) + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_get_index +---------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 1.4ms | GC: 0.1ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.4ms | GC: 0.1ms) +Completed 200 OK in 2ms (Views: 1.5ms | ActiveRecord: 0.2ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_create_game_and_redirect_when_showing_mission +---------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 16:54:55.816852"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 16:54:55.816115"], ["updated_at", "2025-11-28 16:54:55.816115"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 3ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 0.1ms) + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------ +BreakEscape::MissionsControllerTest: test_index_should_return_HTML_with_mission_list +------------------------------------------------------------------------------------ +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 16:54:55 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.0ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.9ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.9ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.9ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + TRANSACTION (0.0ms) begin transaction +  (0.1ms) PRAGMA foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys = ON +  (0.0ms) PRAGMA foreign_keys = OFF + Fixtures Load (0.1ms) DELETE 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-28 17:17:22', '2025-11-28 17:17:22'); +INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-28 17:17:22', '2025-11-28 17:17:22'); +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-28 17:17:22', '2025-11-28 17:17:22'); +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-28 17:17:22', '2025-11-28 17:17:22'); +INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at", "secgen_scenario", "collection") VALUES (899573729, 'secgen_vm_lab', 'SecGen VM Lab - Linux Introduction', 'Test VM and flag integration with SecGen scenario', 1, 2, '2025-11-28 17:17:22', '2025-11-28 17:17:22', 'labs/introducing_attacks/1_intro_linux.xml', 'vm_labs') +  (0.0ms) PRAGMA defer_foreign_keys = 0 +  (0.0ms) PRAGMA foreign_keys = 1 + TRANSACTION (0.9ms) commit transaction +  (0.0ms) PRAGMA foreign_key_check + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_inventory_endpoint_should_add_items +-------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.452407"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.452313"], ["updated_at", "2025-11-28 17:17:22.452313"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Update (0.1ms) UPDATE "break_escape_games" SET "scenario_data" = ?, "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[{\"id\":\"note_1\",\"type\":\"note\",\"name\":\"Test Note\",\"takeable\":true}]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:17:22.453314"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/inventory" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#inventory as HTML + Parameters: {"action_type"=>"add", "item"=>{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}, "id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] inventory endpoint: action=add, item=#"note", "name"=>"Test Note", "id"=>"note_1"} permitted: false> +[BreakEscape] validate_item_collectible: type=note, id=note_1, name=Test Note +[BreakEscape] Item collection valid: note +[BreakEscape] Adding item to inventory: note / Test Note + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"note\",\"name\":\"Test Note\",\"id\":\"note_1\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:17:22.464858"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +[BreakEscape] Item added successfully. Current inventory: [{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}] +Completed 200 OK in 4ms (Views: 0.1ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_ink_endpoint_should_require_npc_parameter +-------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.467228"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.467185"], ["updated_at", "2025-11-28 17:17:22.467185"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 400 Bad Request in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_sync_state_should_update_player_state_for_current_room +--------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.469663"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.469623"], ["updated_at", "2025-11-28 17:17:22.469623"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started PUT "/break_escape/games/1/sync_state" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#sync_state as HTML + Parameters: {"currentRoom"=>"reception", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_accept_correct_pin_code +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.472437"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.472397"], ["updated_at", "2025-11-28 17:17:22.472397"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"door", "targetId"=>"office", "attempt"=>"1234", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=door, id=office, attempt=1234, method=pin +[BreakEscape] Room data: locked=true, lockType=pin, requires=1234 +[BreakEscape] Room is LOCKED, method must be valid: pin +[BreakEscape] pin validation result: true +[BreakEscape] validate_unlock returning: true + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\",\"office\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:17:22.474080"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_return_HTML_with_game_container +---------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.475335"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.475298"], ["updated_at", "2025-11-28 17:17:22.475298"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 1.6ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.7ms | GC: 0.0ms) +Completed 200 OK in 5ms (Views: 3.0ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------- +BreakEscape::GamesControllerTest: test_should_show_game +------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.483017"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.482972"], ["updated_at", "2025-11-28 17:17:22.482972"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.2ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_non-existent_NPC +------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.486034"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.485994"], ["updated_at", "2025-11-28 17:17:22.485994"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=non-existent" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"non-existent", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: non-existent +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_NPC_without_story_file +------------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.488311"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.488271"], ["updated_at", "2025-11-28 17:17:22.488271"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=missing-npc" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"missing-npc", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: missing-npc +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_scenario_endpoint_should_return_JSON +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.490464"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.490426"], ["updated_at", "2025-11-28 17:17:22.490426"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/scenario" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#scenario as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_reject_invalid_attempts +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.492535"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.492499"], ["updated_at", "2025-11-28 17:17:22.492499"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"room", "targetId"=>"office", "attempt"=>"wrong_code", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=room, id=office, attempt=wrong_code, method=pin +[BreakEscape] Object not found: office +Completed 422 Unprocessable Content in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_inject_game_configuration +---------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.494551"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.494513"], ["updated_at", "2025-11-28 17:17:22.494513"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.1ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.497168"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.497129"], ["updated_at", "2025-11-28 17:17:22.497129"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_create_game_and_redirect_when_showing_mission +---------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.503662"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.502940"], ["updated_at", "2025-11-28 17:17:22.502940"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 5ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 2.7ms) + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------ +BreakEscape::MissionsControllerTest: test_index_should_return_HTML_with_mission_list +------------------------------------------------------------------------------------ +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.2ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 5.9ms | GC: 0.2ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 6.1ms | GC: 0.3ms) +Completed 200 OK in 7ms (Views: 5.9ms | ActiveRecord: 0.3ms (5 queries, 1 cached) | GC: 0.3ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_get_index +---------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.0ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.8ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.9ms | GC: 0.1ms) +Completed 200 OK in 1ms (Views: 0.9ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_index_should_display_published_missions +--------------------------------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.0ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.8ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.9ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.9ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.0ms) + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +----------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_show_published_mission +----------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 17:17:22 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:17:22.522635"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:17:22.521563"], ["updated_at", "2025-11-28 17:17:22.521563"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 4ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 0.2ms) + TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + TRANSACTION (0.0ms) begin transaction +  (0.1ms) PRAGMA foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys = ON +  (0.0ms) PRAGMA foreign_keys = OFF + Fixtures Load (0.1ms) DELETE 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-28 17:20:23', '2025-11-28 17:20:23'); +INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-28 17:20:23', '2025-11-28 17:20:23'); +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-28 17:20:23', '2025-11-28 17:20:23'); +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-28 17:20:23', '2025-11-28 17:20:23'); +INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at", "secgen_scenario", "collection") VALUES (899573729, 'secgen_vm_lab', 'SecGen VM Lab - Linux Introduction', 'Test VM and flag integration with SecGen scenario', 1, 2, '2025-11-28 17:20:23', '2025-11-28 17:20:23', 'labs/introducing_attacks/1_intro_linux.xml', 'vm_labs') +  (0.0ms) PRAGMA defer_foreign_keys = 0 +  (0.0ms) PRAGMA foreign_keys = 1 + TRANSACTION (1.1ms) commit transaction +  (0.0ms) PRAGMA foreign_key_check + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------- +BreakEscape::GamesControllerTest: test_should_show_game +------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.846057"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.845959"], ["updated_at", "2025-11-28 17:20:23.845959"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 1.6ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.8ms | GC: 0.0ms) +Completed 200 OK in 8ms (Views: 3.0ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_NPC_without_story_file +------------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.863123"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.863046"], ["updated_at", "2025-11-28 17:20:23.863046"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=missing-npc" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"missing-npc", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: missing-npc +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.1ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_ink_endpoint_should_require_npc_parameter +-------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.865804"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.865762"], ["updated_at", "2025-11-28 17:20:23.865762"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 400 Bad Request in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_scenario_endpoint_should_return_JSON +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.868033"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.867994"], ["updated_at", "2025-11-28 17:20:23.867994"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/scenario" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#scenario as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_non-existent_NPC +------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.870333"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.870294"], ["updated_at", "2025-11-28 17:20:23.870294"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=non-existent" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"non-existent", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: non-existent +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_return_HTML_with_game_container +---------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.872557"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.872520"], ["updated_at", "2025-11-28 17:20:23.872520"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.2ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_accept_correct_pin_code +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.875692"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.875655"], ["updated_at", "2025-11-28 17:20:23.875655"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"door", "targetId"=>"office", "attempt"=>"1234", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=door, id=office, attempt=1234, method=pin +[BreakEscape] Room data: locked=true, lockType=pin, requires=1234 +[BreakEscape] Room is LOCKED, method must be valid: pin +[BreakEscape] pin validation result: true +[BreakEscape] validate_unlock returning: true + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\",\"office\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:20:23.879283"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_inject_game_configuration +---------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.880765"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.880720"], ["updated_at", "2025-11-28 17:20:23.880720"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.2ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_sync_state_should_update_player_state_for_current_room +--------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.883705"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.883661"], ["updated_at", "2025-11-28 17:20:23.883661"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started PUT "/break_escape/games/1/sync_state" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#sync_state as HTML + Parameters: {"currentRoom"=>"reception", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_reject_invalid_attempts +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.886515"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.886474"], ["updated_at", "2025-11-28 17:20:23.886474"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"room", "targetId"=>"office", "attempt"=>"wrong_code", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=room, id=office, attempt=wrong_code, method=pin +[BreakEscape] Object not found: office +Completed 422 Unprocessable Content in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_inventory_endpoint_should_add_items +-------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.888730"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.888693"], ["updated_at", "2025-11-28 17:20:23.888693"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Update (0.1ms) UPDATE "break_escape_games" SET "scenario_data" = ?, "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[{\"id\":\"note_1\",\"type\":\"note\",\"name\":\"Test Note\",\"takeable\":true}]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:20:23.889234"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/inventory" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::GamesController#inventory as HTML + Parameters: {"action_type"=>"add", "item"=>{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}, "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] inventory endpoint: action=add, item=#"note", "name"=>"Test Note", "id"=>"note_1"} permitted: false> +[BreakEscape] validate_item_collectible: type=note, id=note_1, name=Test Note +[BreakEscape] Item collection valid: note +[BreakEscape] Adding item to inventory: note / Test Note + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"note\",\"name\":\"Test Note\",\"id\":\"note_1\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:20:23.890751"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +[BreakEscape] Item added successfully. Current inventory: [{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.892037"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.892001"], ["updated_at", "2025-11-28 17:20:23.892001"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_get_index +---------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.4ms | GC: 0.2ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 9.2ms | GC: 3.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 9.3ms | GC: 3.0ms) +Completed 200 OK in 10ms (Views: 9.1ms | ActiveRecord: 0.3ms (5 queries, 1 cached) | GC: 3.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_create_game_and_redirect_when_showing_mission +---------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.906446"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.905778"], ["updated_at", "2025-11-28 17:20:23.905778"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 2ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 0.1ms) + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------ +BreakEscape::MissionsControllerTest: test_index_should_return_HTML_with_mission_list +------------------------------------------------------------------------------------ +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.9ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.0ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 1.0ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +----------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_show_published_mission +----------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:20:23.912128"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:20:23.911501"], ["updated_at", "2025-11-28 17:20:23.911501"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 2ms (ActiveRecord: 0.2ms (4 queries, 0 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_index_should_display_published_missions +--------------------------------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:20:23 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.0ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.9ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.9ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 1.0ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + ActiveRecord::InternalMetadata Load (0.1ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 [[nil, "schema_sha1"]] + ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC + TRANSACTION (0.0ms) begin transaction +  (0.1ms) PRAGMA foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys +  (0.0ms) PRAGMA defer_foreign_keys = ON +  (0.0ms) PRAGMA foreign_keys = OFF + Fixtures Load (0.1ms) DELETE 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-28 17:25:47', '2025-11-28 17:25:47'); +INSERT INTO "break_escape_demo_users" ("id", "handle", "created_at", "updated_at") VALUES (618102942, 'other_user', '2025-11-28 17:25:47', '2025-11-28 17:25:47'); +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-28 17:25:47', '2025-11-28 17:25:47'); +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-28 17:25:47', '2025-11-28 17:25:47'); +INSERT INTO "break_escape_missions" ("id", "name", "display_name", "description", "published", "difficulty_level", "created_at", "updated_at", "secgen_scenario", "collection") VALUES (899573729, 'secgen_vm_lab', 'SecGen VM Lab - Linux Introduction', 'Test VM and flag integration with SecGen scenario', 1, 2, '2025-11-28 17:25:47', '2025-11-28 17:25:47', 'labs/introducing_attacks/1_intro_linux.xml', 'vm_labs') +  (0.0ms) PRAGMA defer_foreign_keys = 0 +  (0.0ms) PRAGMA foreign_keys = 1 + TRANSACTION (1.1ms) commit transaction +  (0.0ms) PRAGMA foreign_key_check + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_sync_state_should_update_player_state_for_current_room +--------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.1ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.154361"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.154275"], ["updated_at", "2025-11-28 17:25:47.154275"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started PUT "/break_escape/games/1/sync_state" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#sync_state as HTML + Parameters: {"currentRoom"=>"reception", "id"=>"1"} + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 4ms (Views: 0.1ms | ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_game_setup_has_correct_scenario_data +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.168361"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.168309"], ["updated_at", "2025-11-28 17:25:47.168309"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_NPC_without_story_file +------------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.169640"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.169599"], ["updated_at", "2025-11-28 17:25:47.169599"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=missing-npc" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"missing-npc", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: missing-npc +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_accept_correct_pin_code +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.171990"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.171952"], ["updated_at", "2025-11-28 17:25:47.171952"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"door", "targetId"=>"office", "attempt"=>"1234", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=door, id=office, attempt=1234, method=pin +[BreakEscape] Room data: locked=true, lockType=pin, requires=1234 +[BreakEscape] Room is LOCKED, method must be valid: pin +[BreakEscape] pin validation result: true +[BreakEscape] validate_unlock returning: true + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\",\"office\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:25:47.173694"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------- +BreakEscape::GamesControllerTest: test_should_show_game +------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.175148"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.175110"], ["updated_at", "2025-11-28 17:25:47.175110"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 1.5ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.7ms | GC: 0.0ms) +Completed 200 OK in 5ms (Views: 2.9ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_unlock_endpoint_should_reject_invalid_attempts +------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.182677"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.182630"], ["updated_at", "2025-11-28 17:25:47.182630"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/unlock" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#unlock as HTML + Parameters: {"targetType"=>"room", "targetId"=>"office", "attempt"=>"wrong_code", "method"=>"pin", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] validate_unlock: type=room, id=office, attempt=wrong_code, method=pin +[BreakEscape] Object not found: office +Completed 422 Unprocessable Content in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_ink_endpoint_should_require_npc_parameter +-------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.185095"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.185054"], ["updated_at", "2025-11-28 17:25:47.185054"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 400 Bad Request in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------------ +BreakEscape::GamesControllerTest: test_ink_endpoint_should_return_404_for_non-existent_NPC +------------------------------------------------------------------------------------------ + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.187298"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.187253"], ["updated_at", "2025-11-28 17:25:47.187253"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/ink?npc=non-existent" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#ink as HTML + Parameters: {"npc"=>"non-existent", "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] Loading ink for NPC: non-existent +[BreakEscape] No NPCs found in scenario data +Completed 404 Not Found in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_return_HTML_with_game_container +---------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.189375"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.189337"], ["updated_at", "2025-11-28 17:25:47.189337"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.1ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +-------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_inventory_endpoint_should_add_items +-------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.192575"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.192533"], ["updated_at", "2025-11-28 17:25:47.192533"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Update (0.1ms) UPDATE "break_escape_games" SET "scenario_data" = ?, "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[{\"id\":\"note_1\",\"type\":\"note\",\"name\":\"Test Note\",\"takeable\":true}]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:25:47.193121"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started POST "/break_escape/games/1/inventory" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#inventory as HTML + Parameters: {"action_type"=>"add", "item"=>{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}, "id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +[BreakEscape] inventory endpoint: action=add, item=#"note", "name"=>"Test Note", "id"=>"note_1"} permitted: false> +[BreakEscape] validate_item_collectible: type=note, id=note_1, name=Test Note +[BreakEscape] Item collection valid: note +[BreakEscape] Adding item to inventory: note / Test Note + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Mission Load (0.1ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Update (0.0ms) UPDATE "break_escape_games" SET "player_state" = ?, "updated_at" = ? WHERE "break_escape_games"."id" = ? [["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"note\",\"name\":\"Test Note\",\"id\":\"note_1\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["updated_at", "2025-11-28 17:25:47.194853"], ["id", 1]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +[BreakEscape] Item added successfully. Current inventory: [{"type"=>"note", "name"=>"Test Note", "id"=>"note_1"}] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.2ms (5 queries, 0 cached) | GC: 0.0ms) + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_scenario_endpoint_should_return_JSON +--------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.196271"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.196231"], ["updated_at", "2025-11-28 17:25:47.196231"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1/scenario" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#scenario as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] +Completed 200 OK in 1ms (Views: 0.0ms | ActiveRecord: 0.1ms (3 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------- +BreakEscape::GamesControllerTest: test_show_should_inject_game_configuration +---------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.1ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office\"},\"locked\":false,\"objects\":[]},\"office\":{\"type\":\"office\",\"connections\":{\"south\":\"reception\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"1234\",\"objects\":[]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"lockpick\",\"name\":\"Lockpick\",\"id\":\"lockpick_1\",\"takeable\":true}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.198506"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.198468"], ["updated_at", "2025-11-28 17:25:47.198468"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Started GET "/break_escape/games/1" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::GamesController#show as HTML + Parameters: {"id"=>"1"} + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" WHERE "break_escape_demo_users"."id" = ? LIMIT ? [["id", 149617800], ["LIMIT", 1]] + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/games/show.html.erb within layouts/break_escape/application (Duration: 0.1ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.2ms | GC: 0.0ms) +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.1ms (4 queries, 0 cached) | GC: 0.0ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_create_game_and_redirect_when_showing_mission +---------------------------------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.1ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.206542"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.203241"], ["updated_at", "2025-11-28 17:25:47.203241"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 5ms (ActiveRecord: 0.3ms (4 queries, 0 cached) | GC: 2.6ms) + BreakEscape::Game Count (0.0ms) SELECT COUNT(*) FROM "break_escape_games" + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +------------------------------------------------------------------------------------ +BreakEscape::MissionsControllerTest: test_index_should_return_HTML_with_mission_list +------------------------------------------------------------------------------------ +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.2ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 6.3ms | GC: 0.3ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 6.4ms | GC: 0.3ms) +Completed 200 OK in 7ms (Views: 6.3ms | ActiveRecord: 0.3ms (5 queries, 1 cached) | GC: 0.3ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +----------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_show_published_mission +----------------------------------------------------------------------- + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] +Started GET "/break_escape/missions/418560898" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::MissionsController#show as HTML + Parameters: {"id"=>"418560898"} + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + BreakEscape::Game Load (0.0ms) SELECT "break_escape_games".* FROM "break_escape_games" WHERE "break_escape_games"."player_type" = ? AND "break_escape_games"."player_id" = ? AND "break_escape_games"."mission_id" = ? LIMIT ? [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.1ms) SAVEPOINT active_record_1 + BreakEscape::Game Create (0.2ms) INSERT INTO "break_escape_games" ("player_type", "player_id", "mission_id", "scenario_data", "player_state", "status", "started_at", "completed_at", "score", "created_at", "updated_at", "objectives_completed", "tasks_completed") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [["player_type", "BreakEscape::DemoUser"], ["player_id", 149617800], ["mission_id", 418560898], ["scenario_data", "{\"scenario_brief\":\"Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.\",\"startRoom\":\"reception\",\"startItemsInInventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"rooms\":{\"reception\":{\"type\":\"room_reception\",\"connections\":{\"north\":\"office1\"},\"npcs\":[{\"id\":\"neye_eve\",\"displayName\":\"Neye Eve\",\"storyPath\":\"scenarios/ink/neye-eve.json\",\"avatar\":\"assets/npc/avatars/npc_adversary.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\"},{\"id\":\"gossip_girl\",\"displayName\":\"Gossip Girl\",\"storyPath\":\"scenarios/ink/gossip-girl.json\",\"avatar\":\"assets/npc/avatars/npc_neutral.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"timedMessages\":[{\"delay\":5000,\"message\":\"Hey! 👋 Got any juicy gossip for me today?\",\"type\":\"text\"}]},{\"id\":\"helper_npc\",\"displayName\":\"Helpful Contact\",\"storyPath\":\"scenarios/ink/helper-npc.json\",\"avatar\":\"assets/npc/avatars/npc_helper.png\",\"phoneId\":\"player_phone\",\"currentKnot\":\"start\",\"npcType\":\"phone\",\"unlockable\":[\"secure_vault\",\"ceo\"],\"eventMappings\":[{\"eventPattern\":\"item_picked_up:lockpick\",\"targetKnot\":\"on_lockpick_pickup\",\"onceOnly\":true,\"cooldown\":0},{\"eventPattern\":\"minigame_completed\",\"targetKnot\":\"on_lockpick_success\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":10000},{\"eventPattern\":\"minigame_failed\",\"targetKnot\":\"on_lockpick_failed\",\"condition\":\"data.minigameName \\u0026\\u0026 data.minigameName.includes('Lockpick')\",\"cooldown\":15000},{\"eventPattern\":\"door_unlocked\",\"targetKnot\":\"on_door_unlocked\",\"cooldown\":8000},{\"eventPattern\":\"door_unlock_attempt\",\"targetKnot\":\"on_door_attempt\",\"cooldown\":12000},{\"eventPattern\":\"object_interacted\",\"targetKnot\":\"on_ceo_desk_interact\",\"condition\":\"data.objectType === 'desk_ceo'\",\"cooldown\":10000},{\"eventPattern\":\"item_picked_up:*\",\"targetKnot\":\"on_item_found\",\"cooldown\":20000},{\"eventPattern\":\"room_entered\",\"targetKnot\":\"on_room_entered\",\"cooldown\":45000,\"maxTriggers\":3},{\"eventPattern\":\"room_discovered\",\"targetKnot\":\"on_room_discovered\",\"cooldown\":15000,\"maxTriggers\":5},{\"eventPattern\":\"room_entered:ceo\",\"targetKnot\":\"on_ceo_office_entered\",\"onceOnly\":true}]}],\"objects\":[{\"type\":\"phone\",\"name\":\"Reception Phone\",\"takeable\":false,\"readable\":true,\"voice\":\"Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.\",\"sender\":\"IT Team\",\"timestamp\":\"2:15 AM\",\"observations\":\"The reception phone's message light is blinking urgently\"},{\"type\":\"notes\",\"name\":\"Security Log\",\"takeable\":true,\"readable\":true,\"text\":\"Unusual after-hours access detected:\\n- CEO office: 11:30 PM\\n- Server room: 2:15 AM\\n- CEO office again: 3:45 AM\",\"observations\":\"A concerning security log from last night\"},{\"type\":\"pc\",\"name\":\"Reception Computer\",\"takeable\":false,\"lockType\":\"password\",\"passwordHint\":\"Optional hint text\",\"showHint\":true,\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"requires\":\"secret123\",\"observations\":\"The reception's computer, currently locked\",\"postitNote\":\"Password: secret123\",\"showPostit\":true,\"contents\":[{\"type\":\"text_file\",\"name\":\"Private\",\"takeable\":false,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\"}]},{\"type\":\"tablet\",\"name\":\"Tablet Device\",\"takeable\":true,\"locked\":true,\"lockType\":\"bluetooth\",\"requires\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"A locked tablet device that requires Bluetooth pairing\"},{\"type\":\"bluetooth_scanner\",\"name\":\"Bluetooth Scanner\",\"takeable\":true,\"observations\":\"A device for detecting nearby Bluetooth signals\",\"canScanBluetooth\":true},{\"type\":\"key\",\"name\":\"Office Key\",\"takeable\":true,\"key_id\":\"office1_key\",\"keyPins\":[65,25,65,25],\"observations\":\"A key to access the office areas\"},{\"type\":\"pin-cracker\",\"name\":\"PIN Cracker\",\"takeable\":true,\"observations\":\"A sophisticated device that can analyze PIN entry patterns and provide feedback on attempts\"},{\"type\":\"safe\",\"name\":\"Reception Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"pin\",\"requires\":\"9573\",\"observations\":\"A small wall safe behind the reception desk. Looks like it needs a 4-digit code.\",\"contents\":[{\"type\":\"notes\",\"name\":\"IT Access Credentials\",\"takeable\":true,\"readable\":true,\"text\":\"Emergency IT Admin Credentials:\\nUsername: admin\\nPassword: ITsecure2024\\n\\nServer Room Backup Code: 4829\\nCEO Office Alarm Override: 1337\",\"observations\":\"Sensitive IT credentials that could be very useful\"}]}]},\"office1\":{\"type\":\"room_office\",\"locked\":true,\"lockType\":\"key\",\"requires\":\"office1_key\",\"keyPins\":[65,25,65,25],\"difficulty\":\"easy\",\"door_sign\":\"4A Hot Desks\",\"connections\":{\"north\":[\"office2\",\"office3\"],\"south\":\"reception\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"requires\":\"password\",\"hasFingerprint\":true,\"fingerprintOwner\":\"ceo\",\"fingerprintDifficulty\":\"medium\",\"observations\":\"A computer with a cybersecurity alert on screen. There might be fingerprints on the keyboard.\"},{\"type\":\"notes\",\"name\":\"IT Memo\",\"takeable\":true,\"readable\":true,\"text\":\"URGENT: Multiple unauthorized access attempts detected from CEO's office IP address\",\"observations\":\"A concerning IT department memo\"},{\"type\":\"fingerprint_kit\",\"name\":\"Fingerprint Kit\",\"takeable\":true,\"observations\":\"A kit used for collecting fingerprints from surfaces\"}]},\"office2\":{\"type\":\"room_office\",\"connections\":{\"north\":\"ceo\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"Office Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"office2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: office2024\",\"showPostit\":true,\"observations\":\"A standard office computer with a sticky note on the monitor\"},{\"type\":\"notes\",\"name\":\"Shredded Document\",\"takeable\":true,\"readable\":true,\"text\":\"Partially readable: '...offshore account...transfer complete...delete all traces...'\",\"observations\":\"A partially shredded document that someone failed to dispose of properly\"},{\"type\":\"key\",\"name\":\"CEO Office Key\",\"takeable\":true,\"key_id\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"observations\":\"A spare key to the CEO's office, carelessly left behind\"}]},\"office3\":{\"type\":\"room_office\",\"connections\":{\"north\":\"server1\",\"south\":\"office1\"},\"objects\":[{\"type\":\"pc\",\"name\":\"IT Staff Computer\",\"takeable\":false,\"requires\":\"bluetooth\",\"lockType\":\"bluetooth\",\"mac\":\"00:11:22:33:44:55\",\"observations\":\"An IT staff computer showing network security logs\"},{\"type\":\"notes\",\"name\":\"Network Logs\",\"takeable\":true,\"readable\":true,\"text\":\"Large data transfers detected to unknown external IPs - All originating from CEO's office\",\"observations\":\"Suspicious network activity logs\"}]},\"ceo\":{\"type\":\"room_ceo\",\"connections\":{\"north\":\"closet\",\"south\":\"office2\"},\"locked\":true,\"lockType\":\"key\",\"requires\":\"ceo_office_key\",\"keyPins\":[25,45,65,75],\"difficulty\":\"easy\",\"objects\":[{\"type\":\"pc\",\"name\":\"CEO Computer\",\"takeable\":false,\"lockType\":\"password\",\"requires\":\"ceo2024\",\"showKeyboard\":true,\"maxAttempts\":3,\"locked\":true,\"postitNote\":\"Password: ceo2024\",\"showPostit\":true,\"observations\":\"The CEO's laptop, still warm - recently used. A sticky note is attached to the screen.\"},{\"type\":\"suitcase\",\"name\":\"CEO Briefcase\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"difficulty\":\"medium\",\"observations\":\"An expensive leather briefcase with a sturdy lock\",\"contents\":[{\"type\":\"notes\",\"name\":\"Private Note\",\"takeable\":true,\"readable\":true,\"text\":\"Closet keypad code: 7391 - Must move evidence to safe before audit\",\"observations\":\"A hastily written note on expensive paper\"},{\"type\":\"key\",\"name\":\"Safe Key\",\"takeable\":true,\"key_id\":\"safe_key\",\"keyPins\":[52,29,44,37],\"observations\":\"A heavy-duty safe key hidden behind server equipment\"}]},{\"type\":\"phone\",\"name\":\"CEO Phone\",\"takeable\":false,\"readable\":true,\"text\":\"Recent calls: 'Offshore Bank', 'Unknown', 'Data Buyer'\",\"sender\":\"Call Log\",\"timestamp\":\"Last 24 hours\",\"observations\":\"The CEO's phone shows suspicious recent calls\"}]},\"closet\":{\"type\":\"room_closet\",\"connections\":{\"south\":\"ceo\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"7391\",\"objects\":[{\"type\":\"safe\",\"name\":\"Hidden Safe\",\"takeable\":false,\"locked\":true,\"lockType\":\"key\",\"requires\":\"safe_key\",\"keyPins\":[52,29,44,37],\"difficulty\":\"hard\",\"observations\":\"A well-hidden wall safe behind a painting\",\"contents\":[{\"type\":\"notes\",\"name\":\"Incriminating Documents\",\"takeable\":true,\"readable\":true,\"text\":\"Contract for sale of proprietary technology\\nBank transfers from competing companies\\nDetails of upcoming corporate espionage operations\",\"observations\":\"A folder containing damning evidence of corporate espionage. Congratulations! You've recovered the incriminating documents. flag{ceo_exfil_flag}\"}]}]},\"server1\":{\"type\":\"room_servers\",\"connections\":{\"south\":\"office3\"},\"locked\":true,\"lockType\":\"pin\",\"requires\":\"4829\",\"objects\":[{\"type\":\"pc\",\"name\":\"Server Terminal\",\"takeable\":false,\"observations\":\"The main server terminal showing massive data exfiltration\"},{\"type\":\"key\",\"name\":\"Briefcase Key\",\"takeable\":true,\"key_id\":\"briefcase_key\",\"keyPins\":[45,35,25,55],\"observations\":\"A small key labeled 'Personal - Do Not Copy'\"}]}}}"], ["player_state", "{\"currentRoom\":\"reception\",\"unlockedRooms\":[\"reception\"],\"unlockedObjects\":[],\"inventory\":[{\"type\":\"phone\",\"name\":\"Your Phone\",\"takeable\":true,\"phoneId\":\"player_phone\",\"npcIds\":[\"neye_eve\",\"gossip_girl\",\"helper_npc\"],\"observations\":\"Your personal phone with some interesting contacts\"},{\"type\":\"workstation\",\"name\":\"Crypto Analysis Station\",\"takeable\":true,\"observations\":\"A powerful workstation for cryptographic analysis\"},{\"type\":\"lockpick\",\"name\":\"Lock Pick Kit\",\"takeable\":true,\"observations\":\"A professional lock picking kit with various picks and tension wrenches\"}],\"encounteredNPCs\":[],\"globalVariables\":{},\"biometricSamples\":[],\"biometricUnlocks\":[],\"bluetoothDevices\":[],\"notes\":[],\"health\":100,\"submitted_flags\":[],\"flag_rewards_claimed\":[],\"pending_events\":[]}"], ["status", "in_progress"], ["started_at", "2025-11-28 17:25:47.218534"], ["completed_at", nil], ["score", 0], ["created_at", "2025-11-28 17:25:47.217906"], ["updated_at", "2025-11-28 17:25:47.217906"], ["objectives_completed", 0], ["tasks_completed", 0]] + TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1 +Redirected to http://www.example.com/break_escape/games/1 +Completed 302 Found in 2ms (ActiveRecord: 0.4ms (4 queries, 0 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +--------------------------------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_index_should_display_published_missions +--------------------------------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 0.9ms | GC: 0.1ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 0.9ms | GC: 0.1ms) +Completed 200 OK in 1ms (Views: 1.0ms | ActiveRecord: 0.1ms (5 queries, 1 cached) | GC: 0.1ms) + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."id" = ? LIMIT ? [["id", 418560898], ["LIMIT", 1]] + TRANSACTION (0.0ms) rollback transaction + TRANSACTION (0.0ms) begin transaction +---------------------------------------------------------- +BreakEscape::MissionsControllerTest: test_should_get_index +---------------------------------------------------------- +Started GET "/break_escape/missions" for 127.0.0.1 at 2025-11-28 17:25:47 +0000 +Processing by BreakEscape::MissionsController#index as HTML + BreakEscape::DemoUser Load (0.0ms) SELECT "break_escape_demo_users".* FROM "break_escape_demo_users" ORDER BY "break_escape_demo_users"."id" ASC LIMIT ? [["LIMIT", 1]] + Rendering layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb + Rendering /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application + BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + CACHE BreakEscape::Mission Pluck (0.0ms) SELECT DISTINCT "break_escape_missions"."collection" FROM "break_escape_missions" + BreakEscape::Mission Load (0.0ms) SELECT "break_escape_missions".* FROM "break_escape_missions" WHERE "break_escape_missions"."published" = ? [["published", 1]] + BreakEscape::Cybok Load (0.1ms) SELECT "break_escape_cyboks".* FROM "break_escape_cyboks" WHERE "break_escape_cyboks"."cybokable_type" = ? AND "break_escape_cyboks"."cybokable_id" IN (?, ?) [["cybokable_type", "BreakEscape::Mission"], ["cybokable_id", 418560898], ["cybokable_id", 899573729]] + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/shared/_cybok_label.html.erb (Duration: 0.0ms | GC: 0.0ms) + Rendered /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/break_escape/missions/index.html.erb within layouts/break_escape/application (Duration: 1.3ms | GC: 0.0ms) + Rendered layout /home/cliffe/Files/Projects/Code/BreakEscape/BreakEscape/app/views/layouts/break_escape/application.html.erb (Duration: 1.4ms | GC: 0.0ms) +Completed 200 OK in 2ms (Views: 1.4ms | ActiveRecord: 0.2ms (5 queries, 1 cached) | GC: 0.1ms) + TRANSACTION (0.0ms) rollback transaction diff --git a/test/dummy/storage/test.sqlite3 b/test/dummy/storage/test.sqlite3 index c107f676f419204e43d383509b1c866e24710d54..3b32bcf728658fa5f853a9bd174b4f85ee79abb3 100644 GIT binary patch delta 491 zcmZp8z}oPDb;D78PSbhm59OGctyv~Fa*J<%s(;vC%G}Dx)XK!%$iT={*U(Vc$U?yo zDm3{}z6u`cO$96oT+DnK4E(eCjrcM)3kpQ>)i*jfuladCk()t1FrSmr*f>$TI5jyv zH7~v_H$EpZDL6IRJvC1u%vZrDF-bvJ!6!4Xv_io%ucRnHr8K!DGe0jRwYUT%pO}}T zkd~8}u8^5mlA2zW2$EAM&n(GMfSOU9oSK(dl$p~e41z5&`^tPeB{Y*S`ldVFF@ zNn&z#vA$tESTsHd*KaAB{eOvG^d1%fq{XU|1tyr zNB&3rmw{n)l%JoES(*iE2Pi%!KYFjk#ms+*f&V@KA^z(?HCy;aMVQrDP(lu@^7?;W gpvo5v{2%y#@V@}6yv5JK&dkXIlHC4*pHUzI0IFu0j{pDw delta 232 zcmZp8z}oPDb;D78PSuzEnsQ9c)-017xy3g>)jw=6WoBh$W@Tt$WME{fYiOuzWT9XP z6`Fh~Uj>i!rUI4(4kmsh2L9RnMwj(>>jFhSFz|oi{{a+v!oU3kKcheb E03wV*g8%>k diff --git a/test/fixtures/break_escape_missions.yml b/test/fixtures/break_escape_missions.yml index ffd7fb0..864153f 100644 --- a/test/fixtures/break_escape_missions.yml +++ b/test/fixtures/break_escape_missions.yml @@ -15,3 +15,14 @@ unpublished: difficulty_level: 1 created_at: <%= Time.now %> updated_at: <%= Time.now %> + +secgen_vm_lab: + name: secgen_vm_lab + display_name: SecGen VM Lab - Linux Introduction + description: Test VM and flag integration with SecGen scenario + published: true + difficulty_level: 2 + secgen_scenario: labs/introducing_attacks/1_intro_linux.xml + collection: vm_labs + created_at: <%= Time.now %> + updated_at: <%= Time.now %>