diff --git a/.github/workflows/copilot-test-e2e.yml b/.github/workflows/copilot-test-e2e.yml index d82167c93..7b250c0ff 100644 --- a/.github/workflows/copilot-test-e2e.yml +++ b/.github/workflows/copilot-test-e2e.yml @@ -39,10 +39,15 @@ jobs: env: AzureOpenAI__ApiKey: ${{ secrets.AZUREOPENAI__APIKEY }} AzureOpenAI__Endpoint: ${{ secrets.AZUREOPENAI__ENDPOINT }} + TenantId: ${{ secrets.COPILOT_CHAT_TEST_APP_AAD_TENANT_ID }} + WebApi_ClientId: ${{ secrets.COPILOT_CHAT_TEST_APP_AAD_WEBAPI_CLIENT_ID }} run: | dotnet dev-certs https dotnet user-secrets set "AIService:Key" "$AzureOpenAI__ApiKey" dotnet user-secrets set "AIService:Endpoint" "$AzureOpenAI__Endpoint" + dotnet user-secrets set "Authentication:Type" "AzureAd" + dotnet user-secrets set "Authentication:AzureAd:TenantId" "$TenantId" + dotnet user-secrets set "Authentication:AzureAd:ClientId" "$WebApi_ClientId" - name: Start service in background working-directory: webapi @@ -63,8 +68,11 @@ jobs: - name: Run Playwright tests env: REACT_APP_BACKEND_URI: https://localhost:40443/ - REACT_APP_AAD_CLIENT_ID: ${{ secrets.COPILOT_CHAT_REACT_APP_AAD_CLIENT_ID }} - REACT_APP_AAD_AUTHORITY: https://login.microsoftonline.com/common + + REACT_APP_AUTH_TYPE: AzureAd + REACT_APP_AAD_AUTHORITY: https://login.microsoftonline.com/${{ secrets.COPILOT_CHAT_TEST_APP_AAD_TENANT_ID }} + REACT_APP_AAD_CLIENT_ID: ${{ secrets.COPILOT_CHAT_TEST_APP_AAD_CLIENT_ID }} + REACT_APP_AAD_API_SCOPE: api://${{ secrets.COPILOT_CHAT_TEST_APP_AAD_WEBAPI_CLIENT_ID }}/access_as_user REACT_APP_TEST_USER_ACCOUNT1: ${{ secrets.COPILOT_CHAT_TEST_USER_ACCOUNT1 }} REACT_APP_TEST_USER_ACCOUNT1_INITIALS: ${{ secrets.COPILOT_CHAT_TEST_USER_ACCOUNT1_INITIALS }} diff --git a/webapp/src/App.tsx b/webapp/src/App.tsx index 1a3e20be4..9853b6da3 100644 --- a/webapp/src/App.tsx +++ b/webapp/src/App.tsx @@ -171,7 +171,7 @@ const Chat = ({ Chat Copilot {appState > AppState.SettingUserInfo && (
-
+
{ diff --git a/webapp/src/components/chat/chat-list/ListItemActions.tsx b/webapp/src/components/chat/chat-list/ListItemActions.tsx index 18299b337..8aa4b46a7 100644 --- a/webapp/src/components/chat/chat-list/ListItemActions.tsx +++ b/webapp/src/components/chat/chat-list/ListItemActions.tsx @@ -65,6 +65,7 @@ export const ListItemActions: React.FC = ({ chatId, onEdi appearance="transparent" aria-label="Edit chat name" onClick={onEditTitleClick} + data-testid="editChatTitleButtonSimplified" /> diff --git a/webapp/src/components/chat/invitation-dialog/InvitationCreateDialog.tsx b/webapp/src/components/chat/invitation-dialog/InvitationCreateDialog.tsx index 6c812ddbe..a92563cdb 100644 --- a/webapp/src/components/chat/invitation-dialog/InvitationCreateDialog.tsx +++ b/webapp/src/components/chat/invitation-dialog/InvitationCreateDialog.tsx @@ -50,16 +50,16 @@ export const InvitationCreateDialog: React.FC = ({ Invite others to your Bot - - + diff --git a/webapp/src/components/views/Login.tsx b/webapp/src/components/views/Login.tsx index d99ce1c08..371a804e0 100644 --- a/webapp/src/components/views/Login.tsx +++ b/webapp/src/components/views/Login.tsx @@ -26,6 +26,7 @@ export const Login: React.FC = () => { onClick={() => { instance.loginRedirect().catch(() => {}); }} + data-testid="signinButton" > diff --git a/webapp/tests/chat.test.ts b/webapp/tests/chat.test.ts index df4c582c8..1ccb417e1 100644 --- a/webapp/tests/chat.test.ts +++ b/webapp/tests/chat.test.ts @@ -44,7 +44,7 @@ test.describe('Copilot Chat App Test Suite', () => { await plannertests.klarnaTest(page); }); - test('Jira', async ({ page }) => { + test.skip('Jira', async ({ page }) => { test.setTimeout(util.TestTimeout); await plannertests.jiraTest(page); }); diff --git a/webapp/tests/testsBasic.ts b/webapp/tests/testsBasic.ts index 890f37715..a51a84cff 100644 --- a/webapp/tests/testsBasic.ts +++ b/webapp/tests/testsBasic.ts @@ -1,10 +1,10 @@ import { expect } from '@playwright/test'; -import * as util from './utils' +import * as util from './utils'; /* Summary: Checks if the server is running and healthy */ -export async function serverHealth( page ) { +export async function serverHealth(page) { // Make sure the server is running. await page.goto('https://localhost:40443/healthz'); await expect(page.getByText('Healthy')).toBeDefined(); @@ -19,13 +19,13 @@ Summary: Tests for the following behaviour from the WebApp: - Chat History has the correct number of messages and that the last message is from Copilot - SK core skill testing for jokes and fun facts */ -export async function basicBotResponses( page ) { +export async function basicBotResponses(page) { await util.loginAndCreateNewChat(page); - - const joke = "Can you tell me a funny joke about penguins?"; + + const joke = 'Can you tell me a funny joke about penguins?'; await util.sendChatMessageAndWaitForResponse(page, joke); - const funfact = "Tell me a fun fact about the cosmos!"; + const funfact = 'Tell me a fun fact about the cosmos!'; await util.sendChatMessageAndWaitForResponse(page, funfact); // Expect the chat history to contain 7 messages (both user messages and bot responses). @@ -43,8 +43,8 @@ Summary: Tests if the title for the current chat can be changed */ export async function chatTitleChange(page) { await util.loginAndCreateNewChat(page); - - await page.getByTestId('editChatTitleButton').click(); + + await page.getByTestId('editChatTitleButtonSimplified').click(); await page.locator('input[type="text"]').fill('Copilot Unit Tests'); await page.locator('input[type="text"]').press('Enter'); @@ -54,17 +54,17 @@ export async function chatTitleChange(page) { /* Summary: Tests if a single document can be uploaded and then found in the 'Files' tab */ -export async function documentUpload(page) { +export async function documentUpload(page) { await util.loginAndCreateNewChat(page); - + const testFilename = 'Lorem_ipsum.pdf'; - const testFilepath = './../importdocument/sample-docs/' + testFilename; - await page.setInputFiles("input[type='file']", testFilepath) - - await page.getByTestId('filesTab').click();// Go to the file page + const testFilepath = './../tools/importdocument/sample-docs/' + testFilename; + await page.setInputFiles("input[type='file']", testFilepath); + + await page.getByTestId('documentsTab').click(); // Go to the documents tab // Check if corresponding cell for the file exists after upload await page.getByRole('cell', { name: testFilename }).locator('path'); await page.getByTestId('chatTab').click(); // Go back to the chat page await util.postUnitTest(page); -} \ No newline at end of file +} diff --git a/webapp/tests/testsMultiuser.ts b/webapp/tests/testsMultiuser.ts index 258a733ff..8fe10915b 100644 --- a/webapp/tests/testsMultiuser.ts +++ b/webapp/tests/testsMultiuser.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import * as util from './utils' +import * as util from './utils'; /* Summary: Tests the Multiuser feature of Copilot Chat. Specifically if a user can @@ -14,21 +14,38 @@ export async function shareAndJoinChatSessionTest(page) { await util.loginHelper(page, userAccount1, password1); await util.createNewChat(page); + // Need to enable live chat session sharing to access the share button + await page.getByTestId('userSettingsButton').click(); + await page.getByTestId('settingsMenuItem').click(); + await page.getByTestId('advancedSettingsFoldup').click(); + await page.getByTestId('Live Chat Session Sharing').click(); + await page.getByTestId('userSettingsCloseButton').click(); + await page.getByTestId('shareButton').click(); await page.getByTestId('inviteOthersMenuItem').click(); - const labelByID = await page.getByTestId('chatIDLabel'); + const labelByID = await page.getByTestId('invitationDialogChatIDLabel'); const chatId = await labelByID.textContent(); - await page.getByTestId('chatIDCloseButton').click(); + await page.getByTestId('invitationDialogCloseButton').click(); - await page.getByTestId('logOutMenuList').click(); + await page.getByTestId('userSettingsButton').click(); await page.getByTestId('logOutMenuButton').click(); const usernameToLowerCase = userAccount1.toLowerCase(); const locatorVal = ('[data-test-id="' + usernameToLowerCase + '"]') as string; await page.locator(locatorVal).click(); + // Login with the second user account await util.loginHelperAnotherUser(page, userAccount2, password2); + + // Need to enable live chat session sharing to access the join button + await page.getByTestId('userSettingsButton').click(); + await page.getByTestId('settingsMenuItem').click(); + await page.getByTestId('advancedSettingsFoldup').click(); + await page.getByTestId('Simplified Chat Experience').click(); + await page.getByTestId('Live Chat Session Sharing').click(); + await page.getByTestId('userSettingsCloseButton').click(); + await page.getByTestId('createNewConversationButton').click(); await page.getByTestId('joinABotMenuItem').click(); await page.getByTestId('enterChatIDLabel').fill(chatId as string); @@ -36,10 +53,10 @@ export async function shareAndJoinChatSessionTest(page) { await page.getByTestId('joinChatButton').click(); await page.waitForTimeout(util.ChatStateChangeWait); - - await page.getByTestId('chatParticipantsView').click(); + + await page.getByTestId('chatParticipantsView').click(); const numPeople = await page.getByTestId('chatParticipantsView').textContent(); - await expect(numPeople).toEqual("+2"); + await expect(numPeople).toEqual('+2'); await util.postUnitTest(page); -} \ No newline at end of file +} diff --git a/webapp/tests/utils.ts b/webapp/tests/utils.ts index 19bcf928d..a84acc121 100644 --- a/webapp/tests/utils.ts +++ b/webapp/tests/utils.ts @@ -11,9 +11,9 @@ const EvaluatePrompt = export async function loginHelper(page, useraccount, password) { await page.goto('/'); // Expect the page to contain a "Login" button. - await page.getByRole('button').click(); + await page.getByTestId('signinButton').click(); // Clicking the login button should redirect to the login page. - await expect(page).toHaveURL(process.env.REACT_APP_AAD_AUTHORITY); + await expect(page).toHaveURL(new RegExp(`${process.env.REACT_APP_AAD_AUTHORITY}.*`)); // Login with the test user. await page.getByPlaceholder('Email, phone, or Skype').click(); await page.getByPlaceholder('Email, phone, or Skype').fill(useraccount as string); @@ -36,7 +36,7 @@ export async function loginHelperAnotherUser(page, useraccount, password) { // Expect the page to contain a "Login" button. await page.getByRole('button').click(); // Clicking the login button should redirect to the login page. - await expect(page).toHaveURL(process.env.REACT_APP_AAD_AUTHORITY); + await expect(page).toHaveURL(new RegExp(`${process.env.REACT_APP_AAD_AUTHORITY}.*`)); // Login with the another user account. await page.getByRole('button', { name: 'Use another account' }).click(); await page.getByPlaceholder('Email, phone, or Skype').click(); @@ -48,6 +48,13 @@ export async function loginHelperAnotherUser(page, useraccount, password) { // After login, the page should redirect back to the app. await expect(page).toHaveTitle('Copilot Chat'); + + // Get the permission popup if they open + page.on('popup', async (popup) => { + await popup.waitForLoadState(); + await popup.getByRole('button', { name: 'Next' }).click(); + await popup.getByRole('button', { name: 'Accept' }).click(); + }); } export async function createNewChat(page) { await page.getByTestId('createNewConversationButton').click();