mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Add playground / pricing tests (#7057)
* Only render categories in overview if there is data Red #7025 * add option to disable accordions * remove unneeded log * make optional * add disabled state to panels * add missing panels to overview * use enum for refs * add quickjump anchors * use navigation function instaed * make links more distinguishable * fix type * format ticks using currency * add tooltip formatter * fix type * add pricing tests * move test * add more playground tests * use plattform for logins * add id for chart for easier testing * test hover state and bom pricing details * test linked rows works * disable flaky test * cleanup tests * adjust test assumptions to dataset * fix test * remove second test stage * remove unnecessary step * open up tab instaed of checking for it * add test for Dashboard * add Supplier Pricing test * add internal pricing test * added variant pricing test * add test for Purchase History * make sure button is enabled * remove submit * remove timeout going back to default 30s * make less ambigious * reintroduce higher timeout * change url back * Revert "change url back" This reverts commit 9d20d2a86e8fd93df5e5f006617b32a95f578fc4. * fix test * just use cancel * revert url change * remove timeput * use PUI URL - baseUrl is pointing to CUI * fix url for testin * reintroduce options * use default url * disable non working test for now * run in debug mode * use PUI for testing to actually get coverage
This commit is contained in:
parent
2e0b197457
commit
86597ce717
@ -36,6 +36,9 @@ export default defineConfig({
|
||||
},
|
||||
{
|
||||
command: 'invoke server -a 127.0.0.1:8000',
|
||||
env: {
|
||||
INVENTREE_DEBUG: 'True'
|
||||
},
|
||||
url: 'http://127.0.0.1:8000/api/',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
stdout: 'pipe',
|
||||
|
@ -37,7 +37,13 @@ import { InvenTreeTable } from '../../../tables/InvenTreeTable';
|
||||
import { NoPricingData } from './PricingPanel';
|
||||
|
||||
// Display BOM data as a pie chart
|
||||
function BomPieChart({ data, currency }: { data: any[]; currency: string }) {
|
||||
function BomPieChart({
|
||||
data,
|
||||
currency
|
||||
}: {
|
||||
readonly data: any[];
|
||||
readonly currency: string;
|
||||
}) {
|
||||
return (
|
||||
<ResponsiveContainer width="100%" height={500}>
|
||||
<PieChart>
|
||||
@ -78,7 +84,13 @@ function BomPieChart({ data, currency }: { data: any[]; currency: string }) {
|
||||
}
|
||||
|
||||
// Display BOM data as a bar chart
|
||||
function BomBarChart({ data, currency }: { data: any[]; currency: string }) {
|
||||
function BomBarChart({
|
||||
data,
|
||||
currency
|
||||
}: {
|
||||
readonly data: any[];
|
||||
readonly currency: string;
|
||||
}) {
|
||||
return (
|
||||
<ResponsiveContainer width="100%" height={500}>
|
||||
<BarChart data={data}>
|
||||
@ -113,8 +125,8 @@ export default function BomPricingPanel({
|
||||
part,
|
||||
pricing
|
||||
}: {
|
||||
part: any;
|
||||
pricing: any;
|
||||
readonly part: any;
|
||||
readonly pricing: any;
|
||||
}): ReactNode {
|
||||
const table = useTable('pricing-bom');
|
||||
|
||||
|
@ -189,7 +189,7 @@ export default function PricingOverviewPanel({
|
||||
<DataTable records={overviewData} columns={columns} />
|
||||
</Stack>
|
||||
<ResponsiveContainer width="100%" height={500}>
|
||||
<BarChart data={overviewData}>
|
||||
<BarChart data={overviewData} id="pricing-overview-chart">
|
||||
<XAxis dataKey="title" />
|
||||
<YAxis
|
||||
tickFormatter={(value, index) =>
|
||||
|
@ -43,9 +43,9 @@ export default function PricingPanel({
|
||||
label: panelOptions;
|
||||
title: string;
|
||||
visible: boolean;
|
||||
disabled?: boolean | undefined;
|
||||
disabled?: boolean;
|
||||
}): ReactNode {
|
||||
const is_disabled = disabled === undefined ? false : disabled;
|
||||
const is_disabled = disabled ?? false;
|
||||
return (
|
||||
visible && (
|
||||
<Accordion.Item value={label} id={label}>
|
||||
|
@ -1,6 +1,6 @@
|
||||
export const classicUrl = 'http://127.0.0.1:8000';
|
||||
|
||||
export const baseUrl = `${classicUrl}/platform`;
|
||||
export const baseUrl = './platform';
|
||||
export const loginUrl = `${baseUrl}/login`;
|
||||
export const logoutUrl = `${baseUrl}/logout`;
|
||||
export const homeUrl = `${baseUrl}/home`;
|
||||
|
@ -25,13 +25,15 @@ export const doLogin = async (page, username?: string, password?: string) => {
|
||||
export const doQuickLogin = async (
|
||||
page,
|
||||
username?: string,
|
||||
password?: string
|
||||
password?: string,
|
||||
url?: string
|
||||
) => {
|
||||
username = username ?? user.username;
|
||||
password = password ?? user.password;
|
||||
url = url ?? baseUrl;
|
||||
|
||||
// await page.goto(logoutUrl);
|
||||
await page.goto(`${baseUrl}/login/?login=${username}&password=${password}`);
|
||||
await page.goto(`${url}/login/?login=${username}&password=${password}`);
|
||||
await page.waitForURL('**/platform/home');
|
||||
await page.waitForTimeout(250);
|
||||
};
|
||||
|
88
src/frontend/tests/pages/pui_index.spec.ts
Normal file
88
src/frontend/tests/pages/pui_index.spec.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { test } from '../baseFixtures.js';
|
||||
import { baseUrl } from '../defaults.js';
|
||||
import { doQuickLogin } from '../login.js';
|
||||
|
||||
const newPartName = 'UITESTIN123';
|
||||
|
||||
test('PUI - Pages - Index - Playground', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
await page.goto('./');
|
||||
// Playground
|
||||
await page.getByRole('tab', { name: 'Playground' }).click();
|
||||
await page.getByRole('button', { name: 'API Forms' }).click();
|
||||
|
||||
// New Part
|
||||
await page.getByRole('button', { name: 'Create New Part' }).click();
|
||||
await page.locator('#react-select-3-input').fill('category 0');
|
||||
await page
|
||||
.getByRole('option', { name: 'Category 0' })
|
||||
.locator('div')
|
||||
.first()
|
||||
.click();
|
||||
await page.getByLabel('Name *').fill(newPartName);
|
||||
await page.getByLabel('Initial Stock Quantity *').fill('1');
|
||||
await page
|
||||
.getByLabel('Create Part')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Edit Part
|
||||
await page.getByRole('button', { name: 'Edit Part' }).click();
|
||||
await page.getByLabel('IPN').click();
|
||||
await page.getByLabel('IPN').fill(newPartName);
|
||||
await page
|
||||
.getByLabel('Edit Part')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Create Stock Item
|
||||
await page.getByRole('button', { name: 'Create Stock Item' }).click();
|
||||
await page.locator('#react-select-25-input').fill('R_1K_0402_1');
|
||||
await page.getByText('R_1K_0402_1%').click();
|
||||
await page
|
||||
.getByLabel('Add Stock Item')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// EditCategory
|
||||
await page.getByRole('button', { name: 'Edit Category' }).click();
|
||||
await page.locator('.css-1xvbfjt-Input2').first().click();
|
||||
await page.getByText('Category 0').click();
|
||||
await page
|
||||
.getByLabel('Edit Category')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Create Attachment
|
||||
await page.getByRole('button', { name: 'Create Attachment' }).click();
|
||||
await page.getByLabel('Attachment *').waitFor();
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
// TODO: actually create an attachment
|
||||
|
||||
// Create Part new Modal
|
||||
await page.getByRole('button', { name: 'Create Part new Modal' }).click();
|
||||
await page.locator('.css-1xvbfjt-Input2').first().click();
|
||||
await page.getByText('Category 0').click();
|
||||
await page
|
||||
.getByLabel('Create part')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
|
||||
// Status Label
|
||||
await page.getByRole('button', { name: 'Status labels' }).click();
|
||||
await page.getByRole('textbox').dblclick();
|
||||
await page.getByRole('textbox').fill('50');
|
||||
await page.getByText('Attention needed').waitFor();
|
||||
});
|
||||
|
||||
test('PUI - Pages - Index - Dashboard', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Dashboard auto update
|
||||
await page.getByRole('tab', { name: 'Dashboard' }).click();
|
||||
await page.getByText('Autoupdate').click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByText('Autoupdate').click();
|
||||
await page.getByText('This page is a replacement').waitFor();
|
||||
});
|
154
src/frontend/tests/pages/pui_part.spec.ts
Normal file
154
src/frontend/tests/pages/pui_part.spec.ts
Normal file
@ -0,0 +1,154 @@
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
import { baseUrl } from '../defaults';
|
||||
import { doQuickLogin } from '../login';
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Nothing, BOM)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part with no history
|
||||
await page.goto(`${baseUrl}/part/82/pricing`);
|
||||
await page.getByText('1551ABK').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isDisabled();
|
||||
|
||||
// Part with history
|
||||
await page.goto(`${baseUrl}/part/108/pricing`);
|
||||
await page.getByText('Part: Blue Chair').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Sale History' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Sale Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'BOM Pricing' }).isEnabled();
|
||||
|
||||
// Overview Graph
|
||||
let graph = page.locator('#pricing-overview-chart');
|
||||
await graph.waitFor();
|
||||
await graph.getByText('$60').waitFor();
|
||||
await graph.getByText('BOM Pricing').waitFor();
|
||||
await graph.getByText('Overall Pricing').waitFor();
|
||||
await graph.locator('path').nth(1).hover();
|
||||
await page.getByText('min_value : $50').waitFor();
|
||||
|
||||
// BOM Pricing
|
||||
await page.getByRole('button', { name: 'BOM Pricing' }).click();
|
||||
await page.getByText('Bar Chart').click();
|
||||
await page.getByText('total_price_min').waitFor();
|
||||
await page.getByText('Pie Chart').click();
|
||||
await page.getByRole('button', { name: 'Quantity Not sorted' }).waitFor();
|
||||
await page.getByRole('button', { name: 'Unit Price Not sorted' }).waitFor();
|
||||
|
||||
// BOM Pricing - linkjumping
|
||||
await page.getByText('Wood Screw').waitFor();
|
||||
await page.getByText('Wood Screw').click();
|
||||
await page.waitForURL('**/part/98/pricing');
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Supplier)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/55/pricing`);
|
||||
await page.getByText('Part: C_100nF_0603').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isEnabled();
|
||||
|
||||
// Supplier Pricing
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByRole('button', { name: 'SKU Not sorted' }).waitFor();
|
||||
|
||||
// Supplier Pricing - linkjumping
|
||||
let target = page.getByText('ARR-26041-LPC').first();
|
||||
await target.waitFor();
|
||||
await target.click();
|
||||
// await page.waitForURL('**/purchasing/supplier-part/697/');
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Variant)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/106/pricing`);
|
||||
await page.getByText('Part: Chair').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'BOM Pricing' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Variant Pricing' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Sale Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Sale History' }).isDisabled();
|
||||
|
||||
// Variant Pricing
|
||||
await page.getByRole('button', { name: 'Variant Pricing' }).click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByRole('button', { name: 'Variant Part Not sorted' }).click();
|
||||
|
||||
// Variant Pricing - linkjumping
|
||||
let target = page.getByText('Green Chair').first();
|
||||
await target.waitFor();
|
||||
await target.click();
|
||||
await page.waitForURL('**/part/109/pricing');
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Internal)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/65/pricing`);
|
||||
await page.getByText('Part: M2x4 SHCS').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isDisabled();
|
||||
|
||||
// Internal Pricing
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).click();
|
||||
await page.getByRole('button', { name: 'Price Break Not sorted' }).waitFor();
|
||||
|
||||
// Internal Pricing - editing
|
||||
await page.getByRole('row', { name: '1 NZ$' }).getByRole('button').click();
|
||||
await page.getByRole('menuitem', { name: 'Edit' }).click();
|
||||
await page.getByText('Part *M2x4 SHCSSocket head').click();
|
||||
await page.getByText('Part *M2x4 SHCSSocket head').click();
|
||||
});
|
||||
|
||||
test('PUI - Pages - Part - Pricing (Purchase)', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
// Part
|
||||
await page.goto(`${baseUrl}/part/69/pricing`);
|
||||
await page.getByText('Part: 530470210').waitFor();
|
||||
await page.getByRole('tab', { name: 'Part Pricing' }).click();
|
||||
await page.getByLabel('Part Pricing').getByText('Part Pricing').waitFor();
|
||||
await page.getByRole('button', { name: 'Pricing Overview' }).waitFor();
|
||||
await page.getByText('Last Updated').waitFor();
|
||||
await page.getByRole('button', { name: 'Purchase History' }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Internal Pricing' }).isDisabled();
|
||||
await page.getByRole('button', { name: 'Supplier Pricing' }).isDisabled();
|
||||
|
||||
// Purchase History
|
||||
await page.getByRole('button', { name: 'Purchase History' }).click();
|
||||
await page
|
||||
.getByRole('button', { name: 'Purchase Order Not sorted' })
|
||||
.waitFor();
|
||||
await page.getByText('2022-04-29').waitFor();
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user