diff --git a/samples/msal-angular-v3-samples/angular-standalone-sample/test/home.spec.ts b/samples/msal-angular-v3-samples/angular-standalone-sample/test/home.spec.ts new file mode 100644 index 0000000000..6169e8e0db --- /dev/null +++ b/samples/msal-angular-v3-samples/angular-standalone-sample/test/home.spec.ts @@ -0,0 +1,158 @@ +import * as puppeteer from "puppeteer"; +import {Screenshot, setupCredentials, enterCredentials, RETRY_TIMES} from "e2e-test-utils/src/TestUtils"; +import { LabClient } from "e2e-test-utils/src/LabClient"; +import { LabApiQueryParams } from "e2e-test-utils/src/LabApiQueryParams"; +import { AzureEnvironments, AppTypes } from "e2e-test-utils/src/Constants"; +import { BrowserCacheUtils } from "e2e-test-utils/src/BrowserCacheTestUtils"; + +const SCREENSHOT_BASE_FOLDER_NAME = `${__dirname}/screenshots/home-tests`; + +async function verifyTokenStore(BrowserCache: BrowserCacheUtils, scopes: string[]): Promise { + const tokenStore = await BrowserCache.getTokens(); + expect(tokenStore.idTokens.length).toBe(1); + expect(tokenStore.accessTokens.length).toBe(1); + expect(tokenStore.refreshTokens.length).toBe(1); + expect(await BrowserCache.getAccountFromCache(tokenStore.idTokens[0])).not.toBeNull(); + expect(await BrowserCache.accessTokenForScopesExists(tokenStore.accessTokens, scopes)).toBeTruthy; + const storage = await BrowserCache.getWindowStorage(); + expect(Object.keys(storage).length).toBe(8); +} + +describe('/ (Home Page)', () => { + jest.retryTimes(RETRY_TIMES); + let browser: puppeteer.Browser; + let context: puppeteer.BrowserContext; + let page: puppeteer.Page; + let port: number; + let username: string; + let accountPwd: string; + let BrowserCache: BrowserCacheUtils; + + beforeAll(async () => { + // @ts-ignore + browser = await global.__BROWSER__; + // @ts-ignore + port = global.__PORT__; + + const labApiParams: LabApiQueryParams = { + azureEnvironment: AzureEnvironments.CLOUD, + appType: AppTypes.CLOUD + }; + + const labClient = new LabClient(); + const envResponse = await labClient.getVarsByCloudEnvironment(labApiParams); + + [username, accountPwd] = await setupCredentials(envResponse[0], labClient); + }); + + beforeEach(async () => { + context = await browser.createIncognitoBrowserContext(); + page = await context.newPage(); + page.setDefaultTimeout(5000); + BrowserCache = new BrowserCacheUtils(page, "localStorage"); + await page.goto(`http://localhost:${port}`); + }); + + afterEach(async () => { + await page.close(); + await context.close(); + }); + + it("Home page - children are rendered after logging in with loginRedirect", async (): Promise => { + const testName = "redirectBaseCase"; + const screenshot = new Screenshot(`${SCREENSHOT_BASE_FOLDER_NAME}/${testName}`); + await screenshot.takeScreenshot(page, "Page loaded"); + + // Initiate Login + const signInButton = await page.waitForSelector("xpath=//button[contains(., 'Login')]"); + if (signInButton) { + await signInButton.click(); + } + + await screenshot.takeScreenshot(page, "Login button clicked"); + const loginRedirectButton = await page.waitForSelector("xpath=//button[contains(., 'Login using Redirect')]"); + if (loginRedirectButton) { + await loginRedirectButton.click(); + } + + await enterCredentials(page, screenshot, username, accountPwd); + + // Verify UI now displays logged in content + await page.waitForXPath("//p[contains(., 'Login successful!')]"); + const logoutButton = await page.waitForSelector("xpath=//button[contains(., 'Logout')]"); + if (logoutButton) { + await logoutButton.click(); + } + await page.waitForXPath("//button[contains(., 'Logout using')]"); + const logoutButtons = await page.$x("//button[contains(., 'Logout using')]"); + expect(logoutButtons.length).toBe(2); + if (logoutButton) { + await logoutButton.click(); + } + await screenshot.takeScreenshot(page, "App signed in"); + + // Verify tokens are in cache + await verifyTokenStore(BrowserCache, ["User.Read"]); + + // Navigate to profile page + const profileButton = await page.waitForSelector("xpath=//span[contains(., 'Profile')]"); + if (profileButton) { + await profileButton.click(); + } + await screenshot.takeScreenshot(page, "Profile page loaded"); + + // Verify displays profile page without activating MsalGuard + await page.waitForXPath("//strong[contains(., 'First Name: ')]"); + }); + + it("Home page - children are rendered after logging in with loginPopup", async (): Promise => { + const testName = "popupBaseCase"; + const screenshot = new Screenshot(`${SCREENSHOT_BASE_FOLDER_NAME}/${testName}`); + await screenshot.takeScreenshot(page, "Page loaded"); + + // Initiate Login + const signInButton = await page.waitForSelector("xpath=//button[contains(., 'Login')]"); + await signInButton?.click(); + await screenshot.takeScreenshot(page, "Login button clicked"); + const loginPopupButton = await page.waitForSelector("xpath=//button[contains(., 'Login using Popup')]"); + const newPopupWindowPromise = new Promise(resolve => page.once("popup", resolve)); + if (loginPopupButton) { + await loginPopupButton.click(); + } + const popupPage = await newPopupWindowPromise; + const popupWindowClosed = new Promise(resolve => popupPage.once("close", resolve)); + + await enterCredentials(popupPage, screenshot, username, accountPwd); + await popupWindowClosed; + + await page.waitForXPath("//p[contains(., 'Login successful!')]", {timeout: 3000}); + await screenshot.takeScreenshot(page, "Popup closed"); + + // Verify UI now displays logged in content + await page.waitForXPath("//p[contains(., 'Login successful!')]"); + const logoutButton = await page.waitForSelector("xpath=//button[contains(., 'Logout')]"); + if (logoutButton) { + await logoutButton.click(); + } + const logoutButtons = await page.$x("//button[contains(., 'Logout using')]"); + expect(logoutButtons.length).toBe(2); + if (logoutButton) { + await logoutButton.click(); + } + await screenshot.takeScreenshot(page, "App signed in"); + + // Verify tokens are in cache + await verifyTokenStore(BrowserCache, ["User.Read"]); + + // Navigate to profile page + const profileButton = await page.waitForSelector("xpath=//span[contains(., 'Profile')]"); + if (profileButton) { + await profileButton.click(); + } + await screenshot.takeScreenshot(page, "Profile page loaded"); + + // Verify displays profile page without activating MsalGuard + await page.waitForXPath("//strong[contains(., 'First Name: ')]"); + }); + } +); diff --git a/samples/msal-angular-v3-samples/angular-standalone-sample/test/profile.spec.ts b/samples/msal-angular-v3-samples/angular-standalone-sample/test/profile.spec.ts new file mode 100644 index 0000000000..6f5504ac73 --- /dev/null +++ b/samples/msal-angular-v3-samples/angular-standalone-sample/test/profile.spec.ts @@ -0,0 +1,107 @@ +import * as puppeteer from "puppeteer"; +import {Screenshot, setupCredentials, enterCredentials, RETRY_TIMES} from "e2e-test-utils/src/TestUtils"; +import { LabClient } from "e2e-test-utils/src/LabClient"; +import { LabApiQueryParams } from "e2e-test-utils/src/LabApiQueryParams"; +import { AzureEnvironments, AppTypes } from "e2e-test-utils/src/Constants"; +import { BrowserCacheUtils } from "e2e-test-utils/src/BrowserCacheTestUtils"; + +const SCREENSHOT_BASE_FOLDER_NAME = `${__dirname}/screenshots/profile-tests`; + +async function verifyTokenStore(BrowserCache: BrowserCacheUtils, scopes: string[]): Promise { + const tokenStore = await BrowserCache.getTokens(); + expect(tokenStore.idTokens.length).toBe(1); + expect(tokenStore.accessTokens.length).toBe(1); + expect(tokenStore.refreshTokens.length).toBe(1); + expect(await BrowserCache.getAccountFromCache(tokenStore.idTokens[0])).not.toBeNull(); + expect(await BrowserCache.accessTokenForScopesExists(tokenStore.accessTokens, scopes)).toBeTruthy; + const storage = await BrowserCache.getWindowStorage(); + expect(Object.keys(storage).length).toBe(9); +} + +describe('/ (Profile Page)', () => { + jest.retryTimes(RETRY_TIMES); + let browser: puppeteer.Browser; + let context: puppeteer.BrowserContext; + let page: puppeteer.Page; + let port: number; + let username: string; + let accountPwd: string; + let BrowserCache: BrowserCacheUtils; + + beforeAll(async () => { + // @ts-ignore + browser = await global.__BROWSER__; + // @ts-ignore + port = global.__PORT__; + + const labApiParams: LabApiQueryParams = { + azureEnvironment: AzureEnvironments.CLOUD, + appType: AppTypes.CLOUD + }; + + const labClient = new LabClient(); + const envResponse = await labClient.getVarsByCloudEnvironment(labApiParams); + + [username, accountPwd] = await setupCredentials(envResponse[0], labClient); + }); + + beforeEach(async () => { + context = await browser.createIncognitoBrowserContext(); + page = await context.newPage(); + page.setDefaultTimeout(5000); + BrowserCache = new BrowserCacheUtils(page, "localStorage"); + }); + + afterEach(async () => { + await page.close(); + await context.close(); + }); + + it("Profile page - children are rendered after profile button clicked and logging in with loginRedirect", async (): Promise => { + await page.goto(`http://localhost:${port}`); + + const testName = "profileButtonRedirectCase"; + const screenshot = new Screenshot(`${SCREENSHOT_BASE_FOLDER_NAME}/${testName}`); + await screenshot.takeScreenshot(page, "Page loaded"); + + // Initiate Login via MsalGuard by clicking Profile + const profileButton = await page.waitForSelector("xpath=//span[contains(., 'Profile')]"); + if (profileButton) { + await profileButton.click(); + } + + await enterCredentials(page, screenshot, username, accountPwd); + + // Verify UI now displays logged in content + await page.waitForXPath("//button[contains(., 'Logout')]"); + await screenshot.takeScreenshot(page, "Profile page signed in"); + + // Verify tokens are in cache + await verifyTokenStore(BrowserCache, ["User.Read"]); + + // Verify displays profile page without activating MsalGuard + await page.waitForXPath("//strong[contains(., 'First Name: ')]"); + }); + + it("Profile page - children are rendered after initial navigation to profile before login ", async () => { + // Initiate login via MsalGuard by navigating directly to profile route + await page.goto(`http://localhost:${port}/profile`); + + const testName = "profileNavigationRedirectCase"; + const screenshot = new Screenshot(`${SCREENSHOT_BASE_FOLDER_NAME}/${testName}`); + await screenshot.takeScreenshot(page, "No home page load"); + + await enterCredentials(page, screenshot, username, accountPwd); + + // Verify UI now displays logged in content + await page.waitForXPath("//button[contains(., 'Logout')]"); + await screenshot.takeScreenshot(page, "Profile page signed in directly"); + + // Verify tokens are in cache + await verifyTokenStore(BrowserCache, ["User.Read"]); + + // Verify displays profile page without activating MsalGuard + await page.waitForXPath("//strong[contains(., 'First Name: ')]"); + }); + } +);