import { Given, When, Then, expect } from '../fixtures/bdd-fixtures'; Given('I open the NPC chat panel', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; if (chatPanel && typeof chatPanel.open === 'function') { await chatPanel.open(); } await page.waitForTimeout(300); }); Given('the chat initializes with {string}', async ({ page }, characterName: string) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter(characterName); await page.waitForTimeout(500); }); When('I select {string} from the character selector', async ({ page }, characterName: string) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter(characterName); await page.waitForTimeout(500); }); When('I send a message {string}', async ({ page }, message: string) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.sendMessage(message); await page.waitForTimeout(500); }); When('I send another message {string}', async ({ page }, message: string) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.sendMessage(message); await page.waitForTimeout(500); }); When('I click the reset conversation button', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; if (typeof chatPanel.resetConversation === 'function') { await chatPanel.resetConversation(); await page.waitForTimeout(500); } }); When('I chat with {string}', async ({ page }, characterName: string) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter(characterName); await page.waitForTimeout(500); }); When('I chat with Frodo', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter('Frodo'); await page.waitForTimeout(500); }); When('I chat with Sam', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter('Sam'); await page.waitForTimeout(500); }); When('I chat with Gandalf', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter('Gandalf'); await page.waitForTimeout(500); }); Then('the chat should initialize with {string}', async ({ page }, characterName: string) => { const testContext = global.fixtures.testContext; expect(testContext).toBeDefined(); }); Then('an opening message should appear from {string}', async ({ page }, _character: string) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBeGreaterThan(0); }); Then('the opening message from {string} should be one of:', async ({ page }, _character: string) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); const firstMessage = messages[0]; expect(firstMessage).toBeDefined(); }); Then('I should receive another reply from {string}', async ({ page }, _character: string) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBeGreaterThanOrEqual(3); const lastMessage = messages[messages.length - 1]; expect(lastMessage).toBeDefined(); }); Then('I should receive a reply from {string}', async ({ page }, _character: string) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBeGreaterThan(1); const lastMessage = messages[messages.length - 1]; expect(lastMessage).toBeDefined(); }); Then('the conversation should flow coherently across multiple turns', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBeGreaterThanOrEqual(2); for (const msg of messages) { expect(msg.length).toBeGreaterThan(0); } }); Then('the NPC response should include a suggested action', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); // Last message should be from NPC and contain some suggested action text expect(messages.length).toBeGreaterThan(0); const lastMsg = messages[messages.length - 1]; expect(lastMsg).toBeDefined(); expect(lastMsg.length).toBeGreaterThan(0); }); Then('the suggested action should point to a valid in-app route', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const actions = await chatPanel.getAvailableActions(); expect(actions.length).toBeGreaterThan(0); }); Then('a fresh opening message should appear', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBe(1); }); Then('the previous conversation history should be cleared', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBeLessThanOrEqual(1); }); When('Frodo responds to my message, the tone should be:', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter('Frodo'); await chatPanel.sendMessage('Hello'); await page.waitForTimeout(500); const lastMessage = await chatPanel.getLastNPCMessage(); expect(lastMessage.length).toBeGreaterThan(0); }); When('Sam responds to my message, the tone should be:', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter('Sam'); await chatPanel.sendMessage('Hello'); await page.waitForTimeout(500); const lastMessage = await chatPanel.getLastNPCMessage(); expect(lastMessage.length).toBeGreaterThan(0); }); When('Gandalf responds to my message, the tone should be:', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter('Gandalf'); await chatPanel.sendMessage('Hello'); await page.waitForTimeout(500); const lastMessage = await chatPanel.getLastNPCMessage(); expect(lastMessage.length).toBeGreaterThan(0); }); Given('the Azure AI service is unavailable', async ({ page }) => { const testContext = global.fixtures.testContext; (testContext as any).azureServiceUnavailable = true; }); Given('the Azure service returns an out-of-character response', async ({ page }) => { const testContext = global.fixtures.testContext; (testContext as any).azureReturnsOOC = true; }); Then('the chat should still function', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBeGreaterThan(0); }); Then('responses should be deterministic in-character fallbacks', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); const lastMessage = messages[messages.length - 1]; expect(lastMessage.length).toBeGreaterThan(0); }); Then('feature remains usable without Azure credentials', async ({ page }) => { const testContext = global.fixtures.testContext; expect(testContext).toBeDefined(); }); When('I chat with any companion', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.selectCharacter('Gandalf'); await page.waitForTimeout(500); }); Then('the system should attempt one strict retry', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const testContext = global.fixtures.testContext; const messages = await chatPanel.getMessages(); expect(messages.length).toBeGreaterThan(0); (testContext as any).systemRetried = true; }); Then('if the second response is also out-of-character, provide an in-character fallback', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); const lastMessage = messages[messages.length - 1]; expect(lastMessage.length).toBeGreaterThan(0); }); When('I send a message', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; await chatPanel.sendMessage('Hello companion'); await page.waitForTimeout(500); }); Then('Gandalf should reference {string} in the response', async ({ page }, referredText: string) => { const chatPanel = global.fixtures.chatPanel!; const lastMessage = await chatPanel.getLastNPCMessage(); expect(lastMessage.toLowerCase()).toContain(referredText.toLowerCase()); }); Then('the conversation should demonstrate session-scoped memory', async ({ page }) => { const chatPanel = global.fixtures.chatPanel!; const messages = await chatPanel.getMessages(); expect(messages.length).toBeGreaterThanOrEqual(2); });