diff --git a/src/backend/app/auth/auth_routes.py b/src/backend/app/auth/auth_routes.py index 0482e2b4e4..91df93c4a0 100644 --- a/src/backend/app/auth/auth_routes.py +++ b/src/backend/app/auth/auth_routes.py @@ -315,7 +315,6 @@ async def temp_login( setting it as a cookie. Args: - request (Request): The incoming request object. email: email of non-osm user. Returns: diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore index 4ea574bbeb..2c08d8c2b4 100755 --- a/src/frontend/.gitignore +++ b/src/frontend/.gitignore @@ -122,5 +122,5 @@ dist /playwright-report/ /blob-report/ /playwright/.cache/ - -playwright/.auth +/e2e/.cache/ +e2e/.auth diff --git a/src/frontend/e2e/01-create-new-project.spec.ts b/src/frontend/e2e/01-create-new-project.spec.ts index 2d72ad9e88..184875f308 100644 --- a/src/frontend/e2e/01-create-new-project.spec.ts +++ b/src/frontend/e2e/01-create-new-project.spec.ts @@ -3,18 +3,14 @@ import { test, expect } from '@playwright/test'; -import { tempLogin } from './helpers'; - test('create new project', async ({ browserName, page }) => { // Specific for this large test, only run in one browser // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); - await page.getByRole('button', { name: '+ Create New Project' }).click(); - // 1. Project Details Step + await page.goto('/'); + await page.getByRole('button', { name: '+ Create New Project' }).click(); await page.getByRole('button', { name: 'NEXT' }).click(); await expect(page.getByText('Project Name is Required.')).toBeVisible(); await expect(page.getByText('Short Description is Required.', { exact: true })).toBeVisible(); diff --git a/src/frontend/e2e/02-mapper-flow.spec.ts b/src/frontend/e2e/02-mapper-flow.spec.ts index 942ff9d347..7ad4450089 100644 --- a/src/frontend/e2e/02-mapper-flow.spec.ts +++ b/src/frontend/e2e/02-mapper-flow.spec.ts @@ -3,7 +3,7 @@ import { test, expect } from '@playwright/test'; -import { tempLogin, openTestProject } from './helpers'; +import { openTestProject } from './helpers'; test.describe('mapper flow', () => { test('task actions', async ({ browserName, page }) => { @@ -11,11 +11,8 @@ test.describe('mapper flow', () => { // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); - await openTestProject(page); - // 1. Click on task area on map + await openTestProject(page); await page.locator('canvas').click({ position: { x: 445, @@ -35,8 +32,8 @@ test.describe('mapper flow', () => { }); // 2. Lock task for mapping - await expect(page.getByRole('button', { name: 'START MAPPING' })).toBeVisible(); - await page.getByRole('button', { name: 'START MAPPING' }).click(); + await expect(page.getByTestId('StartMapping')).toBeVisible(); + await page.getByTestId('StartMapping').click(); await page.waitForSelector('div:has-text("updated to LOCKED_FOR_MAPPING"):nth-of-type(1)'); await expect( page @@ -107,12 +104,9 @@ test.describe('mapper flow', () => { // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); - await openTestProject(page); - // 1. Click on task area on map // click on task & assert task popup visibility + await openTestProject(page); await page.locator('canvas').click({ position: { x: 388, @@ -120,7 +114,7 @@ test.describe('mapper flow', () => { }, }); await expect(page.getByText('Status: UNLOCKED_TO_MAP')).toBeVisible(); - await expect(page.getByRole('button', { name: 'START MAPPING' })).toBeVisible(); + await expect(page.getByTestId('StartMapping')).toBeVisible(); // 2. Click on a specific feature / Entity within a task // assert feature popup visibility @@ -176,10 +170,7 @@ test.describe('mapper flow', () => { // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); await openTestProject(page); - await page.locator('canvas').click({ position: { x: 475, diff --git a/src/frontend/e2e/auth.setup.ts b/src/frontend/e2e/auth.setup.ts new file mode 100644 index 0000000000..da517e29a6 --- /dev/null +++ b/src/frontend/e2e/auth.setup.ts @@ -0,0 +1,23 @@ +import { test as setup } from '@playwright/test'; +import path from 'path'; + +const authFile = path.join(__dirname, './.auth/user.json'); + +setup('authenticate', async ({ browserName, page }) => { + // Note here we only run in chromium, to avoid running this setup step + // for Firefox and Webkit. + // This is because Webkit does not respect 'secure' cookies on http contexts. + // For this to work we would need to configure https for testing + // https://github.com/hotosm/fmtm/pull/1920 + setup.skip(browserName !== 'chromium', 'Test only for chromium!'); + + // Note this sets a token so we can proceed, but the login will be + // overwritten by svcfmtm localadmin user (as DEBUG=True) + await page.goto('/playwright-temp-login/'); + + // Now check we are signed in as localadmin + await page.waitForSelector('text=localadmin'); + + // Save authentication state + await page.context().storageState({ path: authFile }); +}); diff --git a/src/frontend/e2e/helpers.ts b/src/frontend/e2e/helpers.ts index 5c5a3d26da..7c11160181 100644 --- a/src/frontend/e2e/helpers.ts +++ b/src/frontend/e2e/helpers.ts @@ -1,12 +1,7 @@ import { Page } from '@playwright/test'; -export async function tempLogin(page: Page) { - await page.goto('/'); - await page.getByRole('button', { name: 'Sign in' }).click(); - await page.getByText('Temporary Account').click(); -} - export async function openTestProject(page: Page) { + await page.goto('/'); // open project card with regex text 'Project Create Playwright xxx' await page .getByText(/^Project Create Playwright/) diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index dfa5cf7cbf..0ae733f208 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -28,18 +28,32 @@ export default defineConfig({ /* Configure projects for major browsers */ projects: [ + // Setup project + { name: 'setup', testMatch: /.*\.setup\.ts/ }, { name: 'chromium', - use: { browserName: 'chromium' }, - }, - { - name: 'firefox', - use: { browserName: 'firefox' }, - }, - { - name: 'webkit', - use: { browserName: 'webkit' }, + use: { + browserName: 'chromium', + storageState: 'e2e/.auth/user.json', + }, + dependencies: ['setup'], }, + // { + // name: 'firefox', + // use: { + // browserName: 'firefox', + // storageState: 'e2e/.auth/user.json', + // }, + // dependencies: ['setup'], + // }, + // { + // name: 'webkit', + // use: { + // browserName: 'webkit', + // storageState: 'playwright/.auth/user.json', + // }, + // dependencies: ['setup'], + // }, /* Test against mobile viewports. */ // { diff --git a/src/frontend/src/api/Login.ts b/src/frontend/src/api/Login.ts deleted file mode 100644 index e954220ffb..0000000000 --- a/src/frontend/src/api/Login.ts +++ /dev/null @@ -1,30 +0,0 @@ -import axios from 'axios'; -import { getUserDetailsFromApi } from '@/utilfunctions/login'; -import { CommonActions } from '@/store/slices/CommonSlice'; -import { LoginActions } from '@/store/slices/LoginSlice'; - -export const TemporaryLoginService: Function = (url: string) => { - return async (dispatch) => { - const getTemporaryLogin = async (url: string) => { - // Sets a cookie in the browser that is used for auth - await axios.get(url); - - const apiUser = await getUserDetailsFromApi(); - if (!apiUser) { - dispatch( - CommonActions.SetSnackBar({ - open: true, - message: 'Temp login failed. Try OSM.', - variant: 'error', - duration: 2000, - }), - ); - return; - } - - dispatch(LoginActions.setAuthDetails(apiUser)); - }; - - await getTemporaryLogin(url); - }; -}; diff --git a/src/frontend/src/components/DialogTaskActions.tsx b/src/frontend/src/components/DialogTaskActions.tsx index e44b203134..a81d211feb 100755 --- a/src/frontend/src/components/DialogTaskActions.tsx +++ b/src/frontend/src/components/DialogTaskActions.tsx @@ -184,6 +184,7 @@ export default function Dialog({ taskId, feature }: dialogPropType) { return list_of_task_actions?.length != 0 ? (