mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	[CI] Playwright improvements (#9395)
* Allow port 4173 (vite preview) * Change 'base' attr based on vite command * Allow api_host to be specified separately * Harden API host functionality * Adjust server selections * Cleanup vite.config.ts * Adjust playwright configuration - Allow to run in "production" mode - Builds the code first - Runs only the backend web server - Not suitable for coverage * Tweak github actions * Tweak QC file * Reduce number of steps * Tweak CI file * Fix typo * Ensure translation before build * Fix hard-coded test * Test tweaks * uncomment * Revert some changes * Run with gunicorn, single worker * Reduce log output in DEBUG mode * Update deps * Add global-setup func * Fix for .gitignore file * Cached auth state * Tweak login func * Updated tests * Enable parallel workers again * Simplify config * Try with a single worker again * Single retry mode * Run auth setup first - Prevent issues with parallel test doing login * Improve test setup process * Tweaks * Bump to 3 workers * Tweak playwright settings * Revert change * Revert change
This commit is contained in:
		| @@ -86,8 +86,7 @@ export const navigate = async (page, url: string) => { | ||||
|     url = `${baseUrl}/${url}`; | ||||
|   } | ||||
|  | ||||
|   await page.goto(url, { waitUntil: 'domcontentloaded' }); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
|   await page.goto(url); | ||||
| }; | ||||
|  | ||||
| /** | ||||
| @@ -98,7 +97,6 @@ export const loadTab = async (page, tabName) => { | ||||
|     .getByLabel(/panel-tabs-/) | ||||
|     .getByRole('tab', { name: tabName }) | ||||
|     .click(); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
| }; | ||||
|  | ||||
| // Activate "table" view in certain contexts | ||||
| @@ -121,5 +119,4 @@ export const globalSearch = async (page, query) => { | ||||
|   await page.getByLabel('global-search-input').clear(); | ||||
|   await page.getByPlaceholder('Enter search text').fill(query); | ||||
|   await page.waitForTimeout(300); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
| }; | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| import type { Browser, Page } from '@playwright/test'; | ||||
| import { expect } from './baseFixtures.js'; | ||||
| import { baseUrl, logoutUrl, user } from './defaults'; | ||||
| import { user } from './defaults'; | ||||
| import { navigate } from './helpers.js'; | ||||
|  | ||||
| import fs from 'node:fs'; | ||||
| import path from 'node:path'; | ||||
|  | ||||
| /* | ||||
|  * Perform form based login operation from the "login" URL | ||||
|  */ | ||||
| @@ -9,7 +13,8 @@ export const doLogin = async (page, username?: string, password?: string) => { | ||||
|   username = username ?? user.username; | ||||
|   password = password ?? user.password; | ||||
|  | ||||
|   await navigate(page, logoutUrl); | ||||
|   await page.goto('http://localhost:8000/web/logout', { waituntil: 'load' }); | ||||
|  | ||||
|   await expect(page).toHaveTitle(/^InvenTree.*$/); | ||||
|   await page.waitForURL('**/web/login'); | ||||
|   await page.getByLabel('username').fill(username); | ||||
| @@ -19,31 +24,74 @@ export const doLogin = async (page, username?: string, password?: string) => { | ||||
|   await page.waitForTimeout(250); | ||||
| }; | ||||
|  | ||||
| export interface CachedLoginOptions { | ||||
|   username?: string; | ||||
|   password?: string; | ||||
|   url?: string; | ||||
| } | ||||
|  | ||||
| // Set of users allowed to do cached login | ||||
| // This is to prevent tests from running with the wrong user | ||||
| const ALLOWED_USERS: string[] = ['admin', 'allaccess', 'reader', 'steven']; | ||||
|  | ||||
| /* | ||||
|  * Perform a quick login based on passing URL parameters | ||||
|  */ | ||||
| export const doQuickLogin = async ( | ||||
|   page, | ||||
|   username?: string, | ||||
|   password?: string, | ||||
|   url?: string | ||||
| ) => { | ||||
|   username = username ?? user.username; | ||||
|   password = password ?? user.password; | ||||
|   url = url ?? baseUrl; | ||||
| export const doCachedLogin = async ( | ||||
|   browser: Browser, | ||||
|   options?: CachedLoginOptions | ||||
| ): Promise<Page> => { | ||||
|   const username = options?.username ?? user.username; | ||||
|   const password = options?.password ?? user.password; | ||||
|   const url = options?.url ?? ''; | ||||
|  | ||||
|   await navigate(page, `${url}/login?login=${username}&password=${password}`); | ||||
|   await page.waitForURL('**/web/home'); | ||||
|   // FAIL if an unsupported username is provided | ||||
|   if (!ALLOWED_USERS.includes(username)) { | ||||
|     throw new Error(`Invalid username provided to doCachedLogin: ${username}`); | ||||
|   } | ||||
|  | ||||
|   // Cache the login state locally - and share between tests | ||||
|   const fn = path.resolve(`./playwright/auth/${username}.json`); | ||||
|  | ||||
|   if (fs.existsSync(fn)) { | ||||
|     const page = await browser.newPage({ | ||||
|       storageState: fn | ||||
|     }); | ||||
|     console.log(`Using cached login state for ${username}`); | ||||
|     await navigate(page, url); | ||||
|     await page.waitForURL('**/web/**'); | ||||
|     await page.waitForLoadState('load'); | ||||
|     return page; | ||||
|   } | ||||
|  | ||||
|   // Create a new blank page | ||||
|   const page = await browser.newPage(); | ||||
|  | ||||
|   console.log(`No cache found - logging in for ${username}`); | ||||
|  | ||||
|   // Ensure we start from the login page | ||||
|   await page.goto('http://localhost:8000/web/', { waitUntil: 'load' }); | ||||
|  | ||||
|   await doLogin(page, username, password); | ||||
|   await page.getByLabel('navigation-menu').waitFor({ timeout: 5000 }); | ||||
|   await page.getByText(/InvenTree Demo Server -/).waitFor(); | ||||
|   await page.waitForURL('**/web/**'); | ||||
|  | ||||
|   // Wait for the dashboard to load | ||||
|   await page.getByText('No widgets selected').waitFor(); | ||||
|   await page.waitForTimeout(250); | ||||
|   await page.waitForLoadState('load'); | ||||
|  | ||||
|   // Cache the login state | ||||
|   await page.context().storageState({ path: fn }); | ||||
|  | ||||
|   if (url) { | ||||
|     await navigate(page, url); | ||||
|   } | ||||
|  | ||||
|   return page; | ||||
| }; | ||||
|  | ||||
| export const doLogout = async (page) => { | ||||
|   await navigate(page, 'logout'); | ||||
|   await page.goto('http://localhost:8000/web/logout', { waitUntil: 'load' }); | ||||
|   await page.waitForURL('**/web/login'); | ||||
| }; | ||||
|   | ||||
| @@ -1,52 +0,0 @@ | ||||
| import { test } from './baseFixtures.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
|  | ||||
| test('Modals - Admin', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
|  | ||||
|   // use server info | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'Server Information About this InvenTree instance' | ||||
|     }) | ||||
|     .click(); | ||||
|   await page.getByRole('cell', { name: 'Instance Name' }).waitFor(); | ||||
|   await page.getByRole('button', { name: 'Close' }).click(); | ||||
|  | ||||
|   await page.waitForURL('**/web/home'); | ||||
|  | ||||
|   // use license info | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'License Information Licenses for dependencies of the service' | ||||
|     }) | ||||
|     .click(); | ||||
|   await page.getByText('License Information').first().waitFor(); | ||||
|   await page.getByRole('tab', { name: 'backend Packages' }).click(); | ||||
|   await page.getByRole('button', { name: 'Babel BSD License' }).click(); | ||||
|   await page | ||||
|     .getByText('by the Babel Team, see AUTHORS for more information') | ||||
|     .waitFor(); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'frontend Packages' }).click(); | ||||
|   await page.getByRole('button', { name: '@sentry/core MIT' }).click(); | ||||
|   await page | ||||
|     .getByLabel('@sentry/coreMIT') | ||||
|     .getByText('Copyright (c) 2019') | ||||
|     .waitFor(); | ||||
|  | ||||
|   await page | ||||
|     .getByLabel('License Information') | ||||
|     .getByRole('button') | ||||
|     .first() | ||||
|     .click(); | ||||
|  | ||||
|   // use about | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { name: 'About InvenTree About the InvenTree org' }) | ||||
|     .click(); | ||||
|   await page.getByRole('cell', { name: 'InvenTree Version' }).click(); | ||||
| }); | ||||
| @@ -8,13 +8,15 @@ import { | ||||
|   navigate, | ||||
|   setTableChoiceFilter | ||||
| } from '../helpers.ts'; | ||||
| import { doQuickLogin } from '../login.ts'; | ||||
| import { doCachedLogin } from '../login.ts'; | ||||
|  | ||||
| test('Build Order - Basic Tests', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Build Order - Basic Tests', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   // Navigate to the correct build order | ||||
|   await page.getByRole('tab', { name: 'Manufacturing', exact: true }).click(); | ||||
|   await page.getByRole('tab', { name: 'Manufacturing' }).click(); | ||||
|   await page.waitForURL('**/manufacturing/index/**'); | ||||
|  | ||||
|   await loadTab(page, 'Build Orders'); | ||||
|  | ||||
|   await clearTableFilters(page); | ||||
| @@ -91,8 +93,8 @@ test('Build Order - Basic Tests', async ({ page }) => { | ||||
|     .waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Build Order - Calendar', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Build Order - Calendar', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await navigate(page, 'manufacturing/index/buildorders'); | ||||
|   await activateCalendarView(page); | ||||
| @@ -114,8 +116,8 @@ test('Build Order - Calendar', async ({ page }) => { | ||||
|   await page.context().close(); | ||||
| }); | ||||
|  | ||||
| test('Build Order - Edit', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Build Order - Edit', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await navigate(page, 'manufacturing/build-order/22/'); | ||||
|  | ||||
| @@ -141,8 +143,8 @@ test('Build Order - Edit', async ({ page }) => { | ||||
|   await page.getByRole('button', { name: 'Cancel' }).click(); | ||||
| }); | ||||
|  | ||||
| test('Build Order - Build Outputs', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Build Order - Build Outputs', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await navigate(page, 'manufacturing/index/'); | ||||
|   await loadTab(page, 'Build Orders'); | ||||
| @@ -217,8 +219,8 @@ test('Build Order - Build Outputs', async ({ page }) => { | ||||
|   await page.getByText('Build outputs have been completed').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Build Order - Allocation', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Build Order - Allocation', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await navigate(page, 'manufacturing/build-order/1/line-items'); | ||||
|  | ||||
| @@ -317,8 +319,8 @@ test('Build Order - Allocation', async ({ page }) => { | ||||
|     .waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Build Order - Filters', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Build Order - Filters', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await navigate(page, 'manufacturing/index/buildorders'); | ||||
|  | ||||
| @@ -351,8 +353,8 @@ test('Build Order - Filters', async ({ page }) => { | ||||
|   await page.getByText('Pending Approval').first().waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Build Order - Duplicate', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Build Order - Duplicate', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await navigate(page, 'manufacturing/build-order/24/details'); | ||||
|   await page.getByLabel('action-menu-build-order-').click(); | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import { test } from '../baseFixtures.js'; | ||||
| import { loadTab, navigate } from '../helpers.js'; | ||||
| import { doQuickLogin } from '../login.js'; | ||||
| import { doCachedLogin } from '../login.js'; | ||||
|  | ||||
| test('Company', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Company', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await navigate(page, 'company/1/details'); | ||||
|   await page.getByLabel('Details').getByText('DigiKey Electronics').waitFor(); | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| import { test } from '../baseFixtures.js'; | ||||
| import { loadTab, navigate } from '../helpers.js'; | ||||
| import { doQuickLogin } from '../login.js'; | ||||
| import { doCachedLogin } from '../login.js'; | ||||
|  | ||||
| test('Core User/Group/Contact', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Core User/Group/Contact', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   // groups | ||||
|   await navigate(page, '/core'); | ||||
|   await page.getByText('System Overview', { exact: true }).click(); | ||||
|   await page.getByText('System Overview', { exact: true }).first().click(); | ||||
|   await loadTab(page, 'Groups'); | ||||
|   await page.getByRole('cell', { name: 'all access' }).click(); | ||||
|   await page.getByText('Group: all access', { exact: true }).click(); | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import { test } from '../baseFixtures.js'; | ||||
| import { doQuickLogin } from '../login.js'; | ||||
| import { doCachedLogin } from '../login.js'; | ||||
| import { setPluginState } from '../settings.js'; | ||||
|  | ||||
| test('Dashboard - Basic', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Dashboard - Basic', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByText('Use the menu to add widgets').waitFor(); | ||||
|  | ||||
| @@ -35,7 +35,7 @@ test('Dashboard - Basic', async ({ page }) => { | ||||
|   await page.getByLabel('dashboard-accept-layout').click(); | ||||
| }); | ||||
|  | ||||
| test('Dashboard - Plugins', async ({ page, request }) => { | ||||
| test('Dashboard - Plugins', async ({ browser, request }) => { | ||||
|   // Ensure that the "SampleUI" plugin is enabled | ||||
|   await setPluginState({ | ||||
|     request, | ||||
| @@ -43,7 +43,7 @@ test('Dashboard - Plugins', async ({ page, request }) => { | ||||
|     state: true | ||||
|   }); | ||||
|  | ||||
|   await doQuickLogin(page); | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   // Add a dashboard widget from the SampleUI plugin | ||||
|   await page.getByLabel('dashboard-menu').click(); | ||||
|   | ||||
| @@ -5,15 +5,17 @@ import { | ||||
|   loadTab, | ||||
|   navigate | ||||
| } from '../helpers'; | ||||
| import { doQuickLogin } from '../login'; | ||||
| import { doCachedLogin } from '../login'; | ||||
|  | ||||
| /** | ||||
|  * CHeck each panel tab for the "Parts" page | ||||
|  */ | ||||
| test('Parts - Tabs', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Parts - Tabs', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Parts' }).click(); | ||||
|   await page.waitForURL('**/part/category/index/**'); | ||||
|  | ||||
|   await page | ||||
|     .getByLabel('panel-tabs-partcategory') | ||||
|     .getByRole('tab', { name: 'Parts' }) | ||||
| @@ -56,10 +58,8 @@ test('Parts - Tabs', async ({ page }) => { | ||||
|   await loadTab(page, 'Build Orders'); | ||||
| }); | ||||
|  | ||||
| test('Parts - Manufacturer Parts', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/84/suppliers'); | ||||
| test('Parts - Manufacturer Parts', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/84/suppliers' }); | ||||
|  | ||||
|   await loadTab(page, 'Suppliers'); | ||||
|   await page.getByText('Hammond Manufacturing').click(); | ||||
| @@ -69,10 +69,8 @@ test('Parts - Manufacturer Parts', async ({ page }) => { | ||||
|   await page.getByText('1551ACLR - 1551ACLR').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Supplier Parts', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/15/suppliers'); | ||||
| test('Parts - Supplier Parts', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/15/suppliers' }); | ||||
|  | ||||
|   await loadTab(page, 'Suppliers'); | ||||
|   await page.getByRole('cell', { name: 'DIG-84670-SJI' }).click(); | ||||
| @@ -82,11 +80,8 @@ test('Parts - Supplier Parts', async ({ page }) => { | ||||
|   await page.getByText('DIG-84670-SJI - R_550R_0805_1%').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Locking', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   // Navigate to a known assembly which is *not* locked | ||||
|   await navigate(page, 'part/104/bom'); | ||||
| test('Parts - Locking', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/104/bom' }); | ||||
|   await loadTab(page, 'Bill of Materials'); | ||||
|   await page.getByLabel('action-button-add-bom-item').waitFor(); | ||||
|   await loadTab(page, 'Parameters'); | ||||
| @@ -108,11 +103,9 @@ test('Parts - Locking', async ({ page }) => { | ||||
|   await page.getByText('Part parameters cannot be').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Allocations', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
| test('Parts - Allocations', async ({ browser }) => { | ||||
|   // Let's look at the allocations for a single stock item | ||||
|   await navigate(page, 'stock/item/324/'); | ||||
|   const page = await doCachedLogin(browser, { url: 'stock/item/324/' }); | ||||
|   await loadTab(page, 'Allocations'); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Build Order Allocations' }).waitFor(); | ||||
| @@ -173,11 +166,9 @@ test('Parts - Allocations', async ({ page }) => { | ||||
|   await page.keyboard.press('Escape'); | ||||
| }); | ||||
|  | ||||
| test('Parts - Pricing (Nothing, BOM)', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
| test('Parts - Pricing (Nothing, BOM)', async ({ browser }) => { | ||||
|   // Part with no history | ||||
|   await navigate(page, 'part/82/pricing'); | ||||
|   const page = await doCachedLogin(browser, { url: 'part/82/pricing' }); | ||||
|  | ||||
|   await page.getByText('Small plastic enclosure, black').waitFor(); | ||||
|   await loadTab(page, 'Part Pricing'); | ||||
| @@ -223,11 +214,9 @@ test('Parts - Pricing (Nothing, BOM)', async ({ page }) => { | ||||
|   await page.waitForURL('**/part/98/**'); | ||||
| }); | ||||
|  | ||||
| test('Parts - Pricing (Supplier)', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Parts - Pricing (Supplier)', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/55/pricing' }); | ||||
|  | ||||
|   // Part | ||||
|   await navigate(page, 'part/55/pricing'); | ||||
|   await page.getByText('Ceramic capacitor, 100nF in').waitFor(); | ||||
|   await loadTab(page, 'Part Pricing'); | ||||
|   await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor(); | ||||
| @@ -249,11 +238,8 @@ test('Parts - Pricing (Supplier)', async ({ page }) => { | ||||
|   // await page.waitForURL('**/purchasing/supplier-part/697/'); | ||||
| }); | ||||
|  | ||||
| test('Parts - Pricing (Variant)', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   // Part | ||||
|   await navigate(page, 'part/106/pricing'); | ||||
| test('Parts - Pricing (Variant)', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/106/pricing' }); | ||||
|   await page.getByText('A chair - available in multiple colors').waitFor(); | ||||
|   await loadTab(page, 'Part Pricing'); | ||||
|   await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor(); | ||||
| @@ -275,11 +261,8 @@ test('Parts - Pricing (Variant)', async ({ page }) => { | ||||
|   await page.waitForURL('**/part/109/**'); | ||||
| }); | ||||
|  | ||||
| test('Parts - Pricing (Internal)', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   // Part | ||||
|   await navigate(page, 'part/65/pricing'); | ||||
| test('Parts - Pricing (Internal)', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/65/pricing' }); | ||||
|   await page.getByText('Socket head cap screw, M2').waitFor(); | ||||
|   await loadTab(page, 'Part Pricing'); | ||||
|   await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor(); | ||||
| @@ -300,11 +283,9 @@ test('Parts - Pricing (Internal)', async ({ page }) => { | ||||
|   await page.getByText('Part *M2x4 SHCSSocket head').click(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Pricing (Purchase)', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Parts - Pricing (Purchase)', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/69/pricing' }); | ||||
|  | ||||
|   // Part | ||||
|   await navigate(page, 'part/69/pricing'); | ||||
|   await page.getByText('1.25mm Pitch, PicoBlade PCB').waitFor(); | ||||
|   await loadTab(page, 'Part Pricing'); | ||||
|   await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor(); | ||||
| @@ -322,10 +303,8 @@ test('Parts - Pricing (Purchase)', async ({ page }) => { | ||||
|   await page.getByText('2022-04-29').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Attachments', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/69/attachments'); | ||||
| test('Parts - Attachments', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/69/attachments' }); | ||||
|  | ||||
|   // Submit a new external link | ||||
|   await page.getByLabel('action-button-add-external-').click(); | ||||
| @@ -344,10 +323,8 @@ test('Parts - Attachments', async ({ page }) => { | ||||
|   await page.getByRole('button', { name: 'Cancel' }).click(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Parameters', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/69/parameters'); | ||||
| test('Parts - Parameters', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/69/parameters' }); | ||||
|  | ||||
|   // Create a new template | ||||
|   await page.getByLabel('action-button-add-parameter').click(); | ||||
| @@ -371,10 +348,8 @@ test('Parts - Parameters', async ({ page }) => { | ||||
|   await page.getByRole('button', { name: 'Cancel' }).click(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Notes', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/69/notes'); | ||||
| test('Parts - Notes', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/69/notes' }); | ||||
|  | ||||
|   // Enable editing | ||||
|   await page.getByLabel('Enable Editing').waitFor(); | ||||
| @@ -393,20 +368,16 @@ test('Parts - Notes', async ({ page }) => { | ||||
|   await page.getByLabel('Close Editor').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Parts - 404', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/99999/'); | ||||
| test('Parts - 404', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/99999/' }); | ||||
|   await page.getByText('Page Not Found', { exact: true }).waitFor(); | ||||
|  | ||||
|   // Clear out any console error messages | ||||
|   await page.evaluate(() => console.clear()); | ||||
| }); | ||||
|  | ||||
| test('Parts - Revision', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/906/details'); | ||||
| test('Parts - Revision', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'part/906/details' }); | ||||
|  | ||||
|   await page.getByText('Revision of').waitFor(); | ||||
|   await page.getByText('Select Part Revision').waitFor(); | ||||
| @@ -421,10 +392,10 @@ test('Parts - Revision', async ({ page }) => { | ||||
|   await page.getByText('Select Part Revision').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Parts - Bulk Edit', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'part/category/index/parts'); | ||||
| test('Parts - Bulk Edit', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     url: 'part/category/index/parts' | ||||
|   }); | ||||
|  | ||||
|   // Edit the category for multiple parts | ||||
|   await page.getByLabel('Select record 1', { exact: true }).click(); | ||||
|   | ||||
| @@ -11,12 +11,14 @@ import { | ||||
|   openFilterDrawer, | ||||
|   setTableChoiceFilter | ||||
| } from '../helpers.ts'; | ||||
| import { doQuickLogin } from '../login.ts'; | ||||
| import { doCachedLogin } from '../login.ts'; | ||||
|  | ||||
| test('Purchase Orders - Table', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Purchase Orders - Table', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.waitForURL('**/purchasing/index/**'); | ||||
|  | ||||
|   await loadTab(page, 'Purchase Orders'); | ||||
|   await activateTableView(page); | ||||
|  | ||||
| @@ -42,10 +44,11 @@ test('Purchase Orders - Table', async ({ page }) => { | ||||
|   await page.getByText('2025-07-17').waitFor(); // Target Date | ||||
| }); | ||||
|  | ||||
| test('Purchase Orders - Calendar', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Purchase Orders - Calendar', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.waitForURL('**/purchasing/index/**'); | ||||
|   await loadTab(page, 'Purchase Orders'); | ||||
|  | ||||
|   // Ensure view is in "calendar" mode | ||||
| @@ -66,10 +69,11 @@ test('Purchase Orders - Calendar', async ({ page }) => { | ||||
|   await activateTableView(page); | ||||
| }); | ||||
|  | ||||
| test('Purchase Orders - Barcodes', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Purchase Orders - Barcodes', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     url: 'purchasing/purchase-order/13/detail' | ||||
|   }); | ||||
|  | ||||
|   await navigate(page, 'purchasing/purchase-order/13/detail'); | ||||
|   await page.getByRole('button', { name: 'Issue Order' }).waitFor(); | ||||
|  | ||||
|   // Display QR code | ||||
| @@ -126,10 +130,11 @@ test('Purchase Orders - Barcodes', async ({ page }) => { | ||||
|   await page.getByRole('button', { name: 'Issue Order' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Purchase Orders - General', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Purchase Orders - General', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.waitForURL('**/purchasing/index/**'); | ||||
|  | ||||
|   await page.getByRole('cell', { name: 'PO0012' }).click(); | ||||
|   await page.waitForTimeout(200); | ||||
| @@ -179,10 +184,15 @@ test('Purchase Orders - General', async ({ page }) => { | ||||
|   await page.getByRole('tab', { name: 'Details' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Purchase Orders - Filters', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'reader', 'readonly'); | ||||
| test('Purchase Orders - Filters', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'reader', | ||||
|     password: 'readonly' | ||||
|   }); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.waitForURL('**/purchasing/index/**'); | ||||
|  | ||||
|   await loadTab(page, 'Purchase Orders'); | ||||
|   await activateTableView(page); | ||||
|  | ||||
| @@ -204,11 +214,13 @@ test('Purchase Orders - Filters', async ({ page }) => { | ||||
|   await page.getByRole('option', { name: 'Target Date After' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Purchase Orders - Order Parts', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Purchase Orders - Order Parts', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   // Open "Order Parts" wizard from the "parts" table | ||||
|   await page.getByRole('tab', { name: 'Parts' }).click(); | ||||
|   await page.waitForURL('**/part/category/index/**'); | ||||
|  | ||||
|   await page | ||||
|     .getByLabel('panel-tabs-partcategory') | ||||
|     .getByRole('tab', { name: 'Parts' }) | ||||
| @@ -284,10 +296,12 @@ test('Purchase Orders - Order Parts', async ({ page }) => { | ||||
| /** | ||||
|  * Tests for receiving items against a purchase order | ||||
|  */ | ||||
| test('Purchase Orders - Receive Items', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Purchase Orders - Receive Items', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.waitForURL('**/purchasing/index/**'); | ||||
|  | ||||
|   await page.getByRole('cell', { name: 'PO0014' }).click(); | ||||
|  | ||||
|   await loadTab(page, 'Order Details'); | ||||
| @@ -351,10 +365,11 @@ test('Purchase Orders - Receive Items', async ({ page }) => { | ||||
|   await page.getByRole('cell', { name: 'bucket' }).first().waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Purchase Orders - Duplicate', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Purchase Orders - Duplicate', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     url: 'purchasing/purchase-order/13/detail' | ||||
|   }); | ||||
|  | ||||
|   await navigate(page, 'purchasing/purchase-order/13/detail'); | ||||
|   await page.getByLabel('action-menu-order-actions').click(); | ||||
|   await page.getByLabel('action-menu-order-actions-duplicate').click(); | ||||
|  | ||||
|   | ||||
| @@ -4,15 +4,13 @@ import { | ||||
|   clearTableFilters, | ||||
|   globalSearch, | ||||
|   loadTab, | ||||
|   navigate, | ||||
|   setTableChoiceFilter | ||||
| } from '../helpers.ts'; | ||||
| import { doQuickLogin } from '../login.ts'; | ||||
| import { doCachedLogin } from '../login.ts'; | ||||
|  | ||||
| test('Sales Orders - Tabs', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Sales Orders - Tabs', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'sales/index/' }); | ||||
|  | ||||
|   await navigate(page, 'sales/index/'); | ||||
|   await page.waitForURL('**/web/sales/**'); | ||||
|  | ||||
|   await loadTab(page, 'Sales Orders'); | ||||
| @@ -63,10 +61,12 @@ test('Sales Orders - Tabs', async ({ page }) => { | ||||
|   await loadTab(page, 'Notes'); | ||||
| }); | ||||
|  | ||||
| test('Sales Orders - Basic Tests', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Sales Orders - Basic Tests', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Sales' }).click(); | ||||
|   await page.waitForURL('**/sales/index/**'); | ||||
|  | ||||
|   await loadTab(page, 'Sales Orders'); | ||||
|  | ||||
|   await clearTableFilters(page); | ||||
| @@ -102,10 +102,12 @@ test('Sales Orders - Basic Tests', async ({ page }) => { | ||||
|   await page.getByRole('button', { name: 'Issue Order' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Sales Orders - Shipments', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Sales Orders - Shipments', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Sales' }).click(); | ||||
|   await page.waitForURL('**/sales/index/**'); | ||||
|  | ||||
|   await loadTab(page, 'Sales Orders'); | ||||
|  | ||||
|   await clearTableFilters(page); | ||||
| @@ -131,7 +133,7 @@ test('Sales Orders - Shipments', async ({ page }) => { | ||||
|   await page.getByRole('menuitem', { name: 'Edit' }).click(); | ||||
|  | ||||
|   // Ensure the form has loaded | ||||
|   await page.waitForTimeout(500); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
|  | ||||
|   let tracking_number = await page | ||||
|     .getByLabel('text-field-tracking_number') | ||||
| @@ -201,10 +203,11 @@ test('Sales Orders - Shipments', async ({ page }) => { | ||||
|     .click(); | ||||
| }); | ||||
|  | ||||
| test('Sales Orders - Duplicate', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Sales Orders - Duplicate', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     url: 'sales/sales-order/11/detail' | ||||
|   }); | ||||
|  | ||||
|   await navigate(page, 'sales/sales-order/11/detail'); | ||||
|   await page.getByLabel('action-menu-order-actions').click(); | ||||
|   await page.getByLabel('action-menu-order-actions-duplicate').click(); | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import { test } from '../baseFixtures'; | ||||
| import { navigate } from '../helpers'; | ||||
| import { doQuickLogin } from '../login'; | ||||
| import { doCachedLogin } from '../login'; | ||||
|  | ||||
| const scan = async (page, barcode) => { | ||||
|   await page.getByLabel('barcode-input-scanner').click(); | ||||
| @@ -8,8 +7,8 @@ const scan = async (page, barcode) => { | ||||
|   await page.getByRole('button', { name: 'Scan', exact: true }).click(); | ||||
| }; | ||||
|  | ||||
| test('Scanning - Dialog', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Scanning - Dialog', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Open Barcode Scanner' }).click(); | ||||
|   await scan(page, '{"part": 15}'); | ||||
| @@ -19,8 +18,8 @@ test('Scanning - Dialog', async ({ page }) => { | ||||
|   await page.getByText('Required:').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - Basic', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Scanning - Basic', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   // Navigate to the 'scan' page | ||||
|   await page.getByLabel('navigation-menu').click(); | ||||
| @@ -40,9 +39,8 @@ test('Scanning - Basic', async ({ page }) => { | ||||
|   await page.getByText('No match found for barcode').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - Part', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await navigate(page, 'scan/'); | ||||
| test('Scanning - Part', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'scan/' }); | ||||
|  | ||||
|   await scan(page, '{"part": 1}'); | ||||
|  | ||||
| @@ -51,9 +49,8 @@ test('Scanning - Part', async ({ page }) => { | ||||
|   await page.getByRole('cell', { name: 'part', exact: true }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - Stockitem', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await navigate(page, 'scan/'); | ||||
| test('Scanning - Stockitem', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'scan/' }); | ||||
|   await scan(page, '{"stockitem": 408}'); | ||||
|  | ||||
|   await page.getByText('1551ABK').waitFor(); | ||||
| @@ -61,9 +58,9 @@ test('Scanning - Stockitem', async ({ page }) => { | ||||
|   await page.getByRole('cell', { name: 'Quantity: 100' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - StockLocation', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await navigate(page, 'scan/'); | ||||
| test('Scanning - StockLocation', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'scan/' }); | ||||
|  | ||||
|   await scan(page, '{"stocklocation": 3}'); | ||||
|  | ||||
|   // stocklocation: 3 | ||||
| @@ -74,20 +71,17 @@ test('Scanning - StockLocation', async ({ page }) => { | ||||
|     .waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - SupplierPart', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await navigate(page, 'scan/'); | ||||
| test('Scanning - SupplierPart', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'scan/' }); | ||||
|   await scan(page, '{"supplierpart": 204}'); | ||||
|  | ||||
|   // supplierpart: 204 | ||||
|   await page.waitForTimeout(1000); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
|   await page.getByText('1551ABK').first().waitFor(); | ||||
|   await page.getByRole('cell', { name: 'supplierpart', exact: true }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - PurchaseOrder', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await navigate(page, 'scan/'); | ||||
| test('Scanning - PurchaseOrder', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'scan/' }); | ||||
|   await scan(page, '{"purchaseorder": 12}'); | ||||
|  | ||||
|   // purchaseorder: 12 | ||||
| @@ -98,9 +92,9 @@ test('Scanning - PurchaseOrder', async ({ page }) => { | ||||
|     .waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - SalesOrder', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await navigate(page, 'scan/'); | ||||
| test('Scanning - SalesOrder', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'scan/' }); | ||||
|  | ||||
|   await scan(page, '{"salesorder": 6}'); | ||||
|  | ||||
|   // salesorder: 6 | ||||
| @@ -109,9 +103,8 @@ test('Scanning - SalesOrder', async ({ page }) => { | ||||
|   await page.getByRole('cell', { name: 'salesorder', exact: true }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Scanning - Build', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await navigate(page, 'scan/'); | ||||
| test('Scanning - Build', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'scan/' }); | ||||
|   await scan(page, '{"build": 8}'); | ||||
|  | ||||
|   // build: 8 | ||||
|   | ||||
| @@ -7,12 +7,11 @@ import { | ||||
|   openFilterDrawer, | ||||
|   setTableChoiceFilter | ||||
| } from '../helpers.js'; | ||||
| import { doQuickLogin } from '../login.js'; | ||||
| import { doCachedLogin } from '../login.js'; | ||||
|  | ||||
| test('Stock - Basic Tests', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Stock - Basic Tests', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'stock/location/index/' }); | ||||
|  | ||||
|   await navigate(page, 'stock/location/index/'); | ||||
|   await page.waitForURL('**/web/stock/location/**'); | ||||
|  | ||||
|   await loadTab(page, 'Location Details'); | ||||
| @@ -39,10 +38,9 @@ test('Stock - Basic Tests', async ({ page }) => { | ||||
|   await loadTab(page, 'Installed Items'); | ||||
| }); | ||||
|  | ||||
| test('Stock - Location Tree', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Stock - Location Tree', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'stock/location/index/' }); | ||||
|  | ||||
|   await navigate(page, 'stock/location/index/'); | ||||
|   await page.waitForURL('**/web/stock/location/**'); | ||||
|   await loadTab(page, 'Location Details'); | ||||
|  | ||||
| @@ -56,10 +54,13 @@ test('Stock - Location Tree', async ({ page }) => { | ||||
|   await page.getByRole('cell', { name: 'Factory' }).first().waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Stock - Filters', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'steven', 'wizardstaff'); | ||||
| test('Stock - Filters', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'steven', | ||||
|     password: 'wizardstaff', | ||||
|     url: '/stock/location/index/' | ||||
|   }); | ||||
|  | ||||
|   await navigate(page, 'stock/location/index/'); | ||||
|   await loadTab(page, 'Stock Items'); | ||||
|  | ||||
|   await openFilterDrawer(page); | ||||
| @@ -101,8 +102,8 @@ test('Stock - Filters', async ({ page }) => { | ||||
|   await clearTableFilters(page); | ||||
| }); | ||||
|  | ||||
| test('Stock - Serial Numbers', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Stock - Serial Numbers', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   // Use the "global search" functionality to find a part we are interested in | ||||
|   // This is to exercise the search functionality and ensure it is working as expected | ||||
| @@ -167,10 +168,8 @@ test('Stock - Serial Numbers', async ({ page }) => { | ||||
| /** | ||||
|  * Test various 'actions' on the stock detail page | ||||
|  */ | ||||
| test('Stock - Stock Actions', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await navigate(page, 'stock/item/1225/details'); | ||||
| test('Stock - Stock Actions', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'stock/item/1225/details' }); | ||||
|  | ||||
|   // Helper function to launch a stock action | ||||
|   const launchStockAction = async (action: string) => { | ||||
| @@ -231,11 +230,9 @@ test('Stock - Stock Actions', async ({ page }) => { | ||||
|   await page.getByLabel('action-menu-stock-operations-return').click(); | ||||
| }); | ||||
|  | ||||
| test('Stock - Tracking', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Stock - Tracking', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'stock/item/176/details' }); | ||||
|  | ||||
|   // Navigate to the "stock item" page | ||||
|   await navigate(page, 'stock/item/176/details/'); | ||||
|   await page.getByRole('link', { name: 'Widget Assembly # 2' }).waitFor(); | ||||
|  | ||||
|   // Navigate to the "stock tracking" tab | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import test from '@playwright/test'; | ||||
| import { globalSearch, loadTab, navigate } from './helpers'; | ||||
| import { doQuickLogin } from './login'; | ||||
| import { doCachedLogin } from './login'; | ||||
|  | ||||
| // Helper function to open the export data dialog | ||||
| const openExportDialog = async (page) => { | ||||
| @@ -11,11 +11,12 @@ const openExportDialog = async (page) => { | ||||
| }; | ||||
|  | ||||
| // Test data export for various order types | ||||
| test('Exporting - Orders', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'steven', 'wizardstaff'); | ||||
|  | ||||
|   // Download list of purchase orders | ||||
|   await navigate(page, 'purchasing/index/purchase-orders'); | ||||
| test('Exporting - Orders', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'steven', | ||||
|     password: 'wizardstaff', | ||||
|     url: 'purchasing/index/purchase-orders' | ||||
|   }); | ||||
|  | ||||
|   await openExportDialog(page); | ||||
|  | ||||
| @@ -69,8 +70,11 @@ test('Exporting - Orders', async ({ page }) => { | ||||
| }); | ||||
|  | ||||
| // Test for custom BOM exporter | ||||
| test('Exporting - BOM', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'steven', 'wizardstaff'); | ||||
| test('Exporting - BOM', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'steven', | ||||
|     password: 'wizardstaff' | ||||
|   }); | ||||
|  | ||||
|   await globalSearch(page, 'MAST'); | ||||
|   await page.getByLabel('search-group-results-part').locator('a').click(); | ||||
|   | ||||
| @@ -1,11 +1,15 @@ | ||||
| /** Unit tests for form validation, rendering, etc */ | ||||
| import test from 'playwright/test'; | ||||
| import { navigate } from './helpers'; | ||||
| import { doQuickLogin } from './login'; | ||||
| import { doCachedLogin } from './login'; | ||||
|  | ||||
| test('Forms - Stock Item Validation', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'steven', | ||||
|     password: 'wizardstaff', | ||||
|     url: 'stock/location/index/stock-items' | ||||
|   }); | ||||
|  | ||||
| test('Forms - Stock Item Validation', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'steven', 'wizardstaff'); | ||||
|   await navigate(page, 'stock/location/index/stock-items'); | ||||
|   await page.waitForURL('**/web/stock/location/**'); | ||||
|  | ||||
|   // Create new stock item form | ||||
| @@ -74,9 +78,12 @@ test('Forms - Stock Item Validation', async ({ page }) => { | ||||
|   await page.getByRole('cell', { name: 'Electronics Lab' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Forms - Supplier Validation', async ({ page, request }) => { | ||||
|   await doQuickLogin(page, 'steven', 'wizardstaff'); | ||||
|   await navigate(page, 'purchasing/index/suppliers'); | ||||
| test('Forms - Supplier Validation', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'steven', | ||||
|     password: 'wizardstaff', | ||||
|     url: 'purchasing/index/suppliers' | ||||
|   }); | ||||
|   await page.waitForURL('**/purchasing/index/**'); | ||||
|  | ||||
|   await page.getByLabel('action-button-add-company').click(); | ||||
|   | ||||
| @@ -1,13 +1,16 @@ | ||||
| import { test } from './baseFixtures.js'; | ||||
| import { globalSearch, navigate } from './helpers.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
| import { globalSearch } from './helpers.js'; | ||||
| import { doCachedLogin } from './login.js'; | ||||
|  | ||||
| /** | ||||
|  * Test for integration of django admin button | ||||
|  */ | ||||
| test('Admin Button', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
|   await navigate(page, 'company/1/details'); | ||||
| test('Admin Button', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree', | ||||
|     url: 'company/1/details' | ||||
|   }); | ||||
|  | ||||
|   // Click on the admin button | ||||
|   await page.getByLabel(/action-button-open-in-admin/).click(); | ||||
| @@ -18,8 +21,11 @@ test('Admin Button', async ({ page }) => { | ||||
| }); | ||||
|  | ||||
| // Tests for the global search functionality | ||||
| test('Search', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'steven', 'wizardstaff'); | ||||
| test('Search', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'steven', | ||||
|     password: 'wizardstaff' | ||||
|   }); | ||||
|  | ||||
|   await globalSearch(page, 'another customer'); | ||||
|  | ||||
|   | ||||
| @@ -1,41 +1,7 @@ | ||||
| import { expect, test } from './baseFixtures.js'; | ||||
| import { logoutUrl, user } from './defaults.js'; | ||||
| import { logoutUrl } from './defaults.js'; | ||||
| import { navigate } from './helpers.js'; | ||||
| import { doLogin, doQuickLogin } from './login.js'; | ||||
|  | ||||
| test('Login - Basic Test', async ({ page }) => { | ||||
|   await doLogin(page); | ||||
|  | ||||
|   // Check that the username is provided | ||||
|   await page.getByText(user.username); | ||||
|  | ||||
|   // Logout (via menu) | ||||
|   await page.getByRole('button', { name: 'Ally Access' }).click(); | ||||
|   await page.getByRole('menuitem', { name: 'Logout' }).click(); | ||||
|  | ||||
|   await page.waitForURL('**/web/login'); | ||||
|   await page.getByLabel('username'); | ||||
| }); | ||||
|  | ||||
| test('Login - Quick Test', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   // Check that the username is provided | ||||
|   await page.getByText(user.username); | ||||
|  | ||||
|   await expect(page).toHaveTitle(/^InvenTree/); | ||||
|  | ||||
|   // Go to the dashboard | ||||
|   await navigate(page, ''); | ||||
|   await page.waitForURL('**/web'); | ||||
|  | ||||
|   await page.getByText('InvenTree Demo Server - ').waitFor(); | ||||
|  | ||||
|   // Logout (via URL) | ||||
|   await navigate(page, 'logout'); | ||||
|   await page.waitForURL('**/web/login'); | ||||
|   await page.getByLabel('username'); | ||||
| }); | ||||
| import { doLogin } from './login.js'; | ||||
|  | ||||
| /** | ||||
|  * Test various types of login failure | ||||
| @@ -79,7 +45,7 @@ test('Login - Failures', async ({ page }) => { | ||||
| }); | ||||
|  | ||||
| test('Login - Change Password', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'noaccess', 'youshallnotpass'); | ||||
|   await doLogin(page, 'noaccess', 'youshallnotpass'); | ||||
|  | ||||
|   // Navigate to the 'change password' page | ||||
|   await navigate(page, 'settings/user/account'); | ||||
| @@ -105,6 +71,4 @@ test('Login - Change Password', async ({ page }) => { | ||||
|  | ||||
|   await page.getByText('Password Changed').waitFor(); | ||||
|   await page.getByText('The password was set successfully').waitFor(); | ||||
|  | ||||
|   await page.waitForTimeout(1000); | ||||
| }); | ||||
|   | ||||
| @@ -1,8 +1,61 @@ | ||||
| import { systemKey, test } from './baseFixtures.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
| import { doCachedLogin } from './login.js'; | ||||
| 
 | ||||
| test('Quick Command', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Modals - Admin', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
| 
 | ||||
|   // use server info
 | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'Server Information About this InvenTree instance' | ||||
|     }) | ||||
|     .click(); | ||||
|   await page.getByRole('cell', { name: 'Instance Name' }).waitFor(); | ||||
|   await page.getByRole('button', { name: 'Close' }).click(); | ||||
| 
 | ||||
|   // use license info
 | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'License Information Licenses for dependencies of the service' | ||||
|     }) | ||||
|     .click(); | ||||
|   await page.getByText('License Information').first().waitFor(); | ||||
|   await page.getByRole('tab', { name: 'backend Packages' }).click(); | ||||
|   await page.getByRole('button', { name: 'Babel BSD License' }).click(); | ||||
|   await page | ||||
|     .getByText('by the Babel Team, see AUTHORS for more information') | ||||
|     .waitFor(); | ||||
| 
 | ||||
|   await page.getByRole('tab', { name: 'frontend Packages' }).click(); | ||||
|   await page.getByRole('button', { name: '@sentry/core MIT' }).click(); | ||||
|   await page | ||||
|     .getByLabel('@sentry/coreMIT') | ||||
|     .getByText('Copyright (c) 2019') | ||||
|     .waitFor(); | ||||
| 
 | ||||
|   await page | ||||
|     .getByLabel('License Information') | ||||
|     .getByRole('button') | ||||
|     .first() | ||||
|     .click(); | ||||
| 
 | ||||
|   // use about
 | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { name: 'About InvenTree About the InvenTree org' }) | ||||
|     .click(); | ||||
|   await page.getByRole('cell', { name: 'InvenTree Version' }).click(); | ||||
| }); | ||||
| 
 | ||||
| test('Quick Command', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
| 
 | ||||
|   await page.waitForLoadState('networkidle'); | ||||
| 
 | ||||
|   // Open Spotlight with Keyboard Shortcut and Search
 | ||||
|   await page.locator('body').press(`${systemKey}+k`); | ||||
| @@ -10,11 +63,12 @@ test('Quick Command', async ({ page }) => { | ||||
|   await page.getByPlaceholder('Search...').fill('Dashboard'); | ||||
|   await page.getByPlaceholder('Search...').press('Tab'); | ||||
|   await page.getByPlaceholder('Search...').press('Enter'); | ||||
|   await page.waitForURL('**/web/home'); | ||||
| }); | ||||
| 
 | ||||
| test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Quick Command - No Keys', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser); | ||||
| 
 | ||||
|   await page.waitForLoadState('networkidle'); | ||||
| 
 | ||||
|   // Open Spotlight with Button
 | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
| @@ -23,15 +77,15 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|     .click(); | ||||
| 
 | ||||
|   await page.getByText('InvenTree Demo Server - ').waitFor(); | ||||
|   await page.waitForURL('**/web/home'); | ||||
| 
 | ||||
|   // Use navigation menu
 | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { name: 'Open Navigation Open the main' }) | ||||
|     .click(); | ||||
| 
 | ||||
|   await page.waitForTimeout(1000); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
| 
 | ||||
|   await page.getByRole('button', { name: 'Open Navigation' }).click(); | ||||
| 
 | ||||
|   await page.waitForTimeout(250); | ||||
| 
 | ||||
|   // assert the nav headers are visible
 | ||||
|   await page.getByText('Navigation').waitFor(); | ||||
| @@ -55,8 +109,6 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await page.getByRole('cell', { name: 'Instance Name' }).waitFor(); | ||||
|   await page.getByRole('button', { name: 'Close' }).click(); | ||||
| 
 | ||||
|   await page.waitForURL('**/web/home'); | ||||
| 
 | ||||
|   // use license info
 | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
| @@ -6,12 +6,15 @@ import { | ||||
|   loadTab, | ||||
|   navigate | ||||
| } from './helpers.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
| import { doCachedLogin } from './login.js'; | ||||
| import { setPluginState, setSettingState } from './settings.js'; | ||||
|  | ||||
| // Unit test for plugin settings | ||||
| test('Plugins - Settings', async ({ page, request }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
| test('Plugins - Settings', async ({ browser, request }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|  | ||||
|   // Ensure that the SampleIntegration plugin is enabled | ||||
|   await setPluginState({ | ||||
| @@ -57,11 +60,14 @@ test('Plugins - Settings', async ({ page, request }) => { | ||||
| }); | ||||
|  | ||||
| // Test base plugin functionality | ||||
| test('Plugins - Functionality', async ({ page, request }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
|  | ||||
| test('Plugins - Functionality', async ({ browser }) => { | ||||
|   // Navigate and select the plugin | ||||
|   await navigate(page, 'settings/admin/plugin/'); | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree', | ||||
|     url: 'settings/admin/plugin/' | ||||
|   }); | ||||
|  | ||||
|   await clearTableFilters(page); | ||||
|   await page.getByPlaceholder('Search').fill('sample'); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
| @@ -80,8 +86,11 @@ test('Plugins - Functionality', async ({ page, request }) => { | ||||
|   await page.getByText('The plugin was deactivated').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Plugins - Panels', async ({ page, request }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
| test('Plugins - Panels', async ({ browser, request }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|  | ||||
|   // Ensure that UI plugins are enabled | ||||
|   await setSettingState({ | ||||
| @@ -108,7 +117,7 @@ test('Plugins - Panels', async ({ page, request }) => { | ||||
|   await loadTab(page, 'Part Details'); | ||||
|  | ||||
|   // Allow time for the plugin panels to load (they are loaded asynchronously) | ||||
|   await page.waitForTimeout(1000); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
|  | ||||
|   // Check out each of the plugin panels | ||||
|   await loadTab(page, 'Broken Panel'); | ||||
| @@ -139,8 +148,11 @@ test('Plugins - Panels', async ({ page, request }) => { | ||||
| /** | ||||
|  * Unit test for custom admin integration for plugins | ||||
|  */ | ||||
| test('Plugins - Custom Admin', async ({ page, request }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
| test('Plugins - Custom Admin', async ({ browser, request }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|  | ||||
|   // Ensure that the SampleUI plugin is enabled | ||||
|   await setPluginState({ | ||||
| @@ -170,8 +182,11 @@ test('Plugins - Custom Admin', async ({ page, request }) => { | ||||
|   await page.getByText('hello: world').waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Plugins - Locate Item', async ({ page, request }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
| test('Plugins - Locate Item', async ({ browser, request }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|  | ||||
|   // Ensure that the sample location plugin is enabled | ||||
|   await setPluginState({ | ||||
| @@ -184,6 +199,7 @@ test('Plugins - Locate Item', async ({ page, request }) => { | ||||
|  | ||||
|   // Navigate to the "stock item" page | ||||
|   await navigate(page, 'stock/item/287/'); | ||||
|   await page.waitForLoadState('networkidle'); | ||||
|  | ||||
|   // "Locate" this item | ||||
|   await page.getByLabel('action-button-locate-item').click(); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { expect, test } from './baseFixtures.js'; | ||||
| import { activateTableView, loadTab, navigate } from './helpers.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
| import { activateTableView, loadTab } from './helpers.js'; | ||||
| import { doCachedLogin } from './login.js'; | ||||
| import { setPluginState } from './settings.js'; | ||||
|  | ||||
| /* | ||||
| @@ -8,10 +8,9 @@ import { setPluginState } from './settings.js'; | ||||
|  * Select a number of stock items from the table, | ||||
|  * and print labels against them | ||||
|  */ | ||||
| test('Label Printing', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Label Printing', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'stock/location/index/' }); | ||||
|  | ||||
|   await navigate(page, 'stock/location/index/'); | ||||
|   await page.waitForURL('**/web/stock/location/**'); | ||||
|  | ||||
|   await loadTab(page, 'Stock Items'); | ||||
| @@ -50,10 +49,9 @@ test('Label Printing', async ({ page }) => { | ||||
|  * Navigate to a PurchaseOrder detail page, | ||||
|  * and print a report against it. | ||||
|  */ | ||||
| test('Report Printing', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| test('Report Printing', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { url: 'stock/location/index/' }); | ||||
|  | ||||
|   await navigate(page, 'stock/location/index/'); | ||||
|   await page.waitForURL('**/web/stock/location/**'); | ||||
|  | ||||
|   // Navigate to a specific PurchaseOrder | ||||
| @@ -81,9 +79,11 @@ test('Report Printing', async ({ page }) => { | ||||
|   await page.context().close(); | ||||
| }); | ||||
|  | ||||
| test('Report Editing', async ({ page, request }) => { | ||||
|   const [username, password] = ['admin', 'inventree']; | ||||
|   await doQuickLogin(page, username, password); | ||||
| test('Report Editing', async ({ browser, request }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|  | ||||
|   // activate the sample plugin for this test | ||||
|   await setPluginState({ | ||||
|   | ||||
| @@ -1,49 +1,45 @@ | ||||
| import { expect, test } from './baseFixtures.js'; | ||||
| import { apiUrl } from './defaults.js'; | ||||
| import { getRowFromCell, loadTab, navigate } from './helpers.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
| import { doCachedLogin } from './login.js'; | ||||
| import { setSettingState } from './settings.js'; | ||||
|  | ||||
| /** | ||||
|  * Adjust language and color settings | ||||
|  * | ||||
|  * TODO: Reimplement this - without logging out a cached user | ||||
|  */ | ||||
| test('Settings - Language / Color', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| // test('Settings - Language / Color', async ({ browser }) => { | ||||
| //   const page = await doCachedLogin(browser); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Ally Access' }).click(); | ||||
|   await page.getByRole('menuitem', { name: 'Logout' }).click(); | ||||
|   await page.getByRole('button', { name: 'Send me an email' }).click(); | ||||
|   await page.getByLabel('Language toggle').click(); | ||||
|   await page.getByLabel('Select language').first().click(); | ||||
|   await page.getByRole('option', { name: 'German' }).click(); | ||||
|   await page.waitForTimeout(200); | ||||
| //   await page.getByRole('button', { name: 'Ally Access' }).click(); | ||||
| //   await page.getByRole('menuitem', { name: 'Logout' }).click(); | ||||
| //   await page.getByRole('button', { name: 'Send me an email' }).click(); | ||||
| //   await page.getByLabel('Language toggle').click(); | ||||
| //   await page.getByLabel('Select language').first().click(); | ||||
| //   await page.getByRole('option', { name: 'German' }).click(); | ||||
| //   await page.waitForTimeout(200); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Benutzername und Passwort' }).click(); | ||||
|   await page.getByPlaceholder('Ihr Benutzername').click(); | ||||
|   await page.getByPlaceholder('Ihr Benutzername').fill('admin'); | ||||
|   await page.getByPlaceholder('Ihr Benutzername').press('Tab'); | ||||
|   await page.getByPlaceholder('Dein Passwort').fill('inventree'); | ||||
|   await page.getByRole('button', { name: 'Anmelden' }).click(); | ||||
|   await page.waitForTimeout(200); | ||||
| //   await page.getByRole('button', { name: 'Benutzername und Passwort' }).click(); | ||||
| //   await page.getByPlaceholder('Ihr Benutzername').click(); | ||||
| //   await page.getByPlaceholder('Ihr Benutzername').fill('admin'); | ||||
| //   await page.getByPlaceholder('Ihr Benutzername').press('Tab'); | ||||
| //   await page.getByPlaceholder('Dein Passwort').fill('inventree'); | ||||
| //   await page.getByRole('button', { name: 'Anmelden' }).click(); | ||||
| //   await page.waitForTimeout(200); | ||||
|  | ||||
|   // Note: changes to the dashboard have invalidated these tests (for now) | ||||
|   // await page | ||||
|   //   .locator('span') | ||||
|   //   .filter({ hasText: 'AnzeigeneinstellungenFarbmodusSprache' }) | ||||
|   //   .getByRole('button') | ||||
|   //   .click(); | ||||
|   // await page | ||||
|   //   .locator('span') | ||||
|   //   .filter({ hasText: 'AnzeigeneinstellungenFarbmodusSprache' }) | ||||
|   //   .getByRole('button') | ||||
|   //   .click(); | ||||
| //   await page.getByRole('tab', { name: 'Dashboard' }).click(); | ||||
| //   await page.waitForURL('**/web/home'); | ||||
| // }); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Dashboard' }).click(); | ||||
|   await page.waitForURL('**/web/home'); | ||||
| }); | ||||
| test('Settings - User theme', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'allaccess', | ||||
|     password: 'nolimits' | ||||
|   }); | ||||
|  | ||||
|   await page.waitForLoadState('networkidle'); | ||||
|  | ||||
| test('Settings - User theme', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|   await page.getByRole('button', { name: 'Ally Access' }).click(); | ||||
|   await page.getByRole('menuitem', { name: 'Account settings' }).click(); | ||||
|  | ||||
| @@ -82,14 +78,14 @@ test('Settings - User theme', async ({ page }) => { | ||||
|   // primary | ||||
|   await page.getByLabel('#fab005').click(); | ||||
|   await page.getByLabel('#228be6').click(); | ||||
|  | ||||
|   // language | ||||
|   await page.getByRole('button', { name: 'Use pseudo language' }).click(); | ||||
| }); | ||||
|  | ||||
| test('Settings - Admin', async ({ page }) => { | ||||
| test('Settings - Admin', async ({ browser }) => { | ||||
|   // Note here we login with admin access | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|  | ||||
|   // User settings | ||||
|   await page.getByRole('button', { name: 'admin' }).click(); | ||||
| @@ -184,9 +180,12 @@ test('Settings - Admin', async ({ page }) => { | ||||
|   await page.getByRole('button', { name: 'Submit' }).click(); | ||||
| }); | ||||
|  | ||||
| test('Settings - Admin - Barcode History', async ({ page, request }) => { | ||||
| test('Settings - Admin - Barcode History', async ({ browser, request }) => { | ||||
|   // Login with admin credentials | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|  | ||||
|   // Ensure that the "save scans" setting is enabled | ||||
|   await setSettingState({ | ||||
| @@ -221,11 +220,14 @@ test('Settings - Admin - Barcode History', async ({ page, request }) => { | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| test('Settings - Admin - Unauthorized', async ({ page }) => { | ||||
| test('Settings - Admin - Unauthorized', async ({ browser }) => { | ||||
|   // Try to access "admin" page with a non-staff user | ||||
|   await doQuickLogin(page, 'allaccess', 'nolimits'); | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'allaccess', | ||||
|     password: 'nolimits', | ||||
|     url: 'settings/admin/' | ||||
|   }); | ||||
|  | ||||
|   await navigate(page, 'settings/admin/'); | ||||
|   await page.waitForURL('**/settings/admin/**'); | ||||
|  | ||||
|   // Should get a permission denied message | ||||
| @@ -252,9 +254,12 @@ test('Settings - Admin - Unauthorized', async ({ page }) => { | ||||
| }); | ||||
|  | ||||
| // Test for user auth configuration | ||||
| test('Settings - Auth - Email', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'allaccess', 'nolimits'); | ||||
|   await navigate(page, 'settings/user/'); | ||||
| test('Settings - Auth - Email', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'allaccess', | ||||
|     password: 'nolimits', | ||||
|     url: 'settings/user/' | ||||
|   }); | ||||
|  | ||||
|   await loadTab(page, 'Security'); | ||||
|  | ||||
| @@ -269,9 +274,8 @@ test('Settings - Auth - Email', async ({ page }) => { | ||||
|   await page.getByRole('button', { name: 'Remove' }).click(); | ||||
|  | ||||
|   await page.getByText('Currently no email addresses are registered').waitFor(); | ||||
|  | ||||
|   await page.waitForTimeout(2500); | ||||
| }); | ||||
|  | ||||
| async function testColorPicker(page, ref: string) { | ||||
|   const element = page.getByLabel(ref); | ||||
|   await element.click(); | ||||
|   | ||||
| @@ -4,13 +4,11 @@ import { | ||||
|   navigate, | ||||
|   setTableChoiceFilter | ||||
| } from './helpers.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
|  | ||||
| test('Tables - Filters', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
| import { doCachedLogin } from './login.js'; | ||||
|  | ||||
| test('Tables - Filters', async ({ browser }) => { | ||||
|   // Head to the "build order list" page | ||||
|   await navigate(page, 'manufacturing/index/'); | ||||
|   const page = await doCachedLogin(browser, { url: 'manufacturing/index/' }); | ||||
|  | ||||
|   await clearTableFilters(page); | ||||
|  | ||||
| @@ -41,11 +39,11 @@ test('Tables - Filters', async ({ page }) => { | ||||
|   await clearTableFilters(page); | ||||
| }); | ||||
|  | ||||
| test('Tables - Columns', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
| test('Tables - Columns', async ({ browser }) => { | ||||
|   // Go to the "stock list" page | ||||
|   await navigate(page, 'stock/location/index/stock-items'); | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     url: 'stock/location/index/stock-items' | ||||
|   }); | ||||
|  | ||||
|   // Open column selector | ||||
|   await page.getByLabel('table-select-columns').click(); | ||||
| @@ -64,6 +62,4 @@ test('Tables - Columns', async ({ page }) => { | ||||
|   await page.getByRole('menuitem', { name: 'Target Date' }).click(); | ||||
|   await page.getByRole('menuitem', { name: 'Reference', exact: true }).click(); | ||||
|   await page.getByRole('menuitem', { name: 'Project Code' }).click(); | ||||
|  | ||||
|   await page.waitForTimeout(1000); | ||||
| }); | ||||
|   | ||||
| @@ -1,9 +1,12 @@ | ||||
| import { test } from '../baseFixtures'; | ||||
| import { navigate } from '../helpers'; | ||||
| import { doQuickLogin } from '../login'; | ||||
| import { doCachedLogin } from '../login'; | ||||
|  | ||||
| test('PUI - Admin - Parameter', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
| test('PUI - Admin - Parameter', async ({ browser }) => { | ||||
|   const page = await doCachedLogin(browser, { | ||||
|     username: 'admin', | ||||
|     password: 'inventree' | ||||
|   }); | ||||
|   await page.getByRole('button', { name: 'admin' }).click(); | ||||
|   await page.getByRole('menuitem', { name: 'Admin Center' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Part Parameters' }).click(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user