Skip to content

Commit 479e8c2

Browse files
authored
Merge branch 'dev' into feature/#765-Add-calculator-icon-to-set-of-icons
2 parents a2b64aa + cadb555 commit 479e8c2

10 files changed

Lines changed: 557 additions & 12 deletions

e2e/helpers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './konva-testing.helpers';
22
export * from './position.helpers';
3+
export * from './properties.helpers';

e2e/helpers/position.helpers.ts

Lines changed: 114 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export interface Position {
55
y: number;
66
}
77

8+
export interface ComponentWithCategory {
9+
name: string;
10+
category?: string;
11+
}
12+
813
export const getLocatorPosition = async (
914
locator: Locator
1015
): Promise<Position> => {
@@ -44,6 +49,18 @@ export const dragAndDrop = async (
4449
await page.mouse.up();
4550
};
4651

52+
const getTargetPosition = (
53+
canvasPosition: { x: number; y: number },
54+
displacementQty: number,
55+
multiplyFactor: number
56+
): Position => {
57+
const positionDisplacement = displacementQty * (multiplyFactor + 1);
58+
return {
59+
x: canvasPosition.x + displacementQty + positionDisplacement,
60+
y: canvasPosition.y + positionDisplacement,
61+
};
62+
};
63+
4764
export const addComponentsToCanvas = async (
4865
page: Page,
4966
components: string[],
@@ -58,25 +75,110 @@ export const addComponentsToCanvas = async (
5875
await component.scrollIntoViewIfNeeded();
5976
const position = await getLocatorPosition(component);
6077

61-
const targetPosition = (
62-
displacementQty: number,
63-
multiplyFactor: number
64-
) => {
65-
const positionDisplacement = displacementQty * (multiplyFactor + 1);
66-
return {
67-
x: canvasPosition.x + displacementQty + positionDisplacement,
68-
y: canvasPosition.y + positionDisplacement,
69-
};
70-
};
71-
72-
await dragAndDrop(page, position, targetPosition(displacementQty, index));
78+
const targetPosition = getTargetPosition(
79+
canvasPosition,
80+
displacementQty,
81+
index
82+
);
83+
await dragAndDrop(page, position, targetPosition);
84+
}
85+
};
86+
87+
export const addComponentsWithDifferentCategoriesToCanvas = async (
88+
page: Page,
89+
components: ComponentWithCategory[],
90+
displacementQty: number = 120
91+
) => {
92+
// Handle empty array
93+
if (components.length === 0) {
94+
return;
95+
}
96+
97+
const stageCanvas = await page.locator('#konva-stage canvas').nth(1);
98+
const canvasPosition = await stageCanvas.boundingBox();
99+
if (!canvasPosition) throw new Error('No canvas found');
100+
101+
let currentCategory: string | undefined = undefined;
102+
103+
for await (const [index, componentConfig] of components.entries()) {
104+
try {
105+
// Change category only if it's different from current one
106+
if (
107+
componentConfig.category &&
108+
componentConfig.category !== currentCategory
109+
) {
110+
const categoryButton = page.getByText(componentConfig.category, {
111+
exact: true,
112+
});
113+
114+
// Check if category exists before clicking
115+
await categoryButton.waitFor({ state: 'visible', timeout: 3000 });
116+
await categoryButton.click();
117+
118+
// Wait a bit for the category change to take effect
119+
await page.waitForTimeout(500);
120+
currentCategory = componentConfig.category;
121+
}
122+
123+
// Find component with better handling for duplicates
124+
let component = page.getByAltText(componentConfig.name, { exact: true });
125+
126+
// Check if there are multiple elements with the same alt text
127+
const componentCount = await component.count();
128+
129+
if (componentCount > 1) {
130+
// Handle duplicates by selecting the first visible one in the current category context
131+
console.warn(
132+
`Multiple components found with name "${componentConfig.name}". Using first visible one.`
133+
);
134+
component = component.first();
135+
}
136+
137+
// Wait for component to be available
138+
await component.waitFor({ state: 'visible', timeout: 5000 });
139+
await component.scrollIntoViewIfNeeded();
140+
const position = await getLocatorPosition(component);
141+
142+
const targetPosition = getTargetPosition(
143+
canvasPosition,
144+
displacementQty,
145+
index
146+
);
147+
await dragAndDrop(page, position, targetPosition);
148+
} catch (error) {
149+
const errorMessage =
150+
error instanceof Error ? error.message : String(error);
151+
throw new Error(
152+
`Failed to add component "${componentConfig.name}" from category "${componentConfig.category || 'default'}": ${errorMessage}`
153+
);
154+
}
73155
}
74156
};
75157

76158
export const getShapePosition = async (shape: Group): Promise<Position> => {
77159
return { x: shape?.attrs.x, y: shape?.attrs.y };
78160
};
79161

162+
export const selectAllComponentsInCanvas = async (
163+
page: Page,
164+
selectionArea?: { start: Position; end: Position }
165+
) => {
166+
// Clear any existing selection first
167+
await page.mouse.click(800, 130);
168+
169+
// Small delay to ensure the click is processed
170+
await page.waitForTimeout(100);
171+
172+
const selectionStart = selectionArea?.start || { x: 260, y: 130 };
173+
const selectionEnd = selectionArea?.end || { x: 1000, y: 650 };
174+
175+
// Perform drag selection using the proven coordinates
176+
await dragAndDrop(page, selectionStart, selectionEnd);
177+
178+
// Small delay to ensure selection is processed
179+
await page.waitForTimeout(200);
180+
};
181+
80182
export const moveSelected = (
81183
page: Page,
82184
direction: string,

e2e/helpers/properties.helpers.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Page, expect } from '@playwright/test';
2+
import { getByShapeType } from './konva-testing.helpers';
3+
import { Group } from 'konva/lib/Group';
4+
5+
export const getShapeBackgroundColor = async (
6+
page: Page,
7+
shapeType: string
8+
): Promise<string> => {
9+
const shape = (await getByShapeType(page, shapeType)) as Group;
10+
return shape?.children?.[0]?.attrs?.fill;
11+
};
12+
13+
export const checkPropertiesExist = async (
14+
page: Page,
15+
properties: string[]
16+
) => {
17+
for (const property of properties) {
18+
const propLocator = page.getByText(property, { exact: true });
19+
await expect(propLocator).toBeVisible();
20+
}
21+
};
22+
23+
export const checkPropertiesDoNotExist = async (
24+
page: Page,
25+
properties: string[]
26+
) => {
27+
for (const property of properties) {
28+
const propLocator = page.getByText(property, { exact: true });
29+
await expect(propLocator).not.toBeVisible();
30+
}
31+
};
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { test, expect } from '@playwright/test';
2+
import {
3+
getTransformer,
4+
ComponentWithCategory,
5+
getShapeBackgroundColor,
6+
addComponentsWithDifferentCategoriesToCanvas,
7+
selectAllComponentsInCanvas,
8+
checkPropertiesExist,
9+
} from '../helpers';
10+
11+
test('when selecting a button and a rectangle, select both, change background color to red, both should update their bg to red', async ({
12+
page,
13+
}) => {
14+
await page.goto('');
15+
16+
// Add components to canvas
17+
const components: ComponentWithCategory[] = [
18+
{ name: 'Button' }, // Button is in default 'Components' category
19+
{ name: 'Rectangle', category: 'Basic Shapes' },
20+
];
21+
await addComponentsWithDifferentCategoriesToCanvas(page, components);
22+
23+
// Select all components in canvas
24+
await selectAllComponentsInCanvas(page);
25+
26+
// Confirm both items are selected
27+
const selectedItems = await getTransformer(page);
28+
expect(selectedItems._nodes.length).toEqual(2);
29+
30+
// Change background color to red
31+
const bgSelector = page
32+
.getByText('Background')
33+
.locator('..')
34+
.locator('button');
35+
await bgSelector.click();
36+
37+
const redColorBox = page.locator(
38+
'div[style*="background-color: rgb(221, 0, 0)"]'
39+
);
40+
await redColorBox.click();
41+
42+
// Verify that both items have red background
43+
const buttonBgColor = await getShapeBackgroundColor(page, 'button');
44+
const rectangleBgColor = await getShapeBackgroundColor(page, 'rectangle');
45+
46+
expect(buttonBgColor).toBe('#DD0000');
47+
expect(rectangleBgColor).toBe('#DD0000');
48+
});
49+
50+
test('verify that in the props we can find the common props of both items', async ({
51+
page,
52+
}) => {
53+
await page.goto('');
54+
55+
// Add components to canvas
56+
const components: ComponentWithCategory[] = [
57+
{ name: 'Button' },
58+
{ name: 'Rectangle', category: 'Basic Shapes' },
59+
];
60+
await addComponentsWithDifferentCategoriesToCanvas(page, components);
61+
62+
// Select all components in canvas
63+
await selectAllComponentsInCanvas(page);
64+
65+
// Confirm both items are selected
66+
const selectedItems = await getTransformer(page);
67+
expect(selectedItems._nodes.length).toEqual(2);
68+
69+
const commonProps: string[] = [
70+
'Layering',
71+
'Stroke',
72+
'Stroke style',
73+
'Background',
74+
'Border-radius',
75+
];
76+
77+
// Verify common properties are visible in the properties panel
78+
await checkPropertiesExist(page, commonProps);
79+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { test, expect } from '@playwright/test';
2+
import {
3+
addComponentsWithDifferentCategoriesToCanvas,
4+
checkPropertiesDoNotExist,
5+
checkPropertiesExist,
6+
ComponentWithCategory,
7+
getTransformer,
8+
selectAllComponentsInCanvas,
9+
} from '../helpers';
10+
11+
test('when selecting button and bar chart, check that there are not common props (just default layering prop)', async ({
12+
page,
13+
}) => {
14+
page.goto('');
15+
16+
// Add components to canvas
17+
const components: ComponentWithCategory[] = [
18+
{ name: 'Button' },
19+
{ name: 'Bar Chart', category: 'Rich Components' },
20+
];
21+
await addComponentsWithDifferentCategoriesToCanvas(page, components);
22+
23+
// Select all components in canvas
24+
await selectAllComponentsInCanvas(page);
25+
26+
// Confirm both items are selected
27+
const selectedItems = await getTransformer(page);
28+
expect(selectedItems._nodes.length).toEqual(2);
29+
30+
const buttonProps: string[] = [
31+
'Stroke',
32+
'Stroke style',
33+
'Background',
34+
'TextColor',
35+
'Disabled',
36+
'Border-radius',
37+
];
38+
39+
// Verify button props are not visible in the properties panel
40+
await checkPropertiesDoNotExist(page, buttonProps);
41+
42+
// Verify layering prop to be visible
43+
44+
await checkPropertiesExist(page, ['Layering']);
45+
});
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { test, expect } from '@playwright/test';
2+
import { dragAndDrop, getByShapeType, getLocatorPosition } from '../helpers';
3+
4+
test('when selecting a new thumb and adding a new shape it will be dropped in the new created page', async ({
5+
page,
6+
}) => {
7+
await page.goto('');
8+
9+
await page.getByText('Devices').click();
10+
11+
// Drag & drop mobile device component to default page canvas
12+
const componentFirstPage = page
13+
.getByText('Mobile Phone', { exact: true })
14+
.locator('..');
15+
16+
const position = await getLocatorPosition(componentFirstPage);
17+
const targetPosition = { x: position.x + 500, y: position.y - 200 };
18+
await dragAndDrop(page, position, targetPosition);
19+
20+
// Add new page
21+
await page.getByText('Pages').click();
22+
const addButton = page.getByRole('button', { name: 'add new page' });
23+
await addButton.click();
24+
25+
// Verify Page 2 is automatically selected/active
26+
const pageTwo = page.getByText('Page 2', { exact: true }).locator('..');
27+
await expect(pageTwo).toHaveClass(/active/);
28+
29+
// Drag & drop browser component to second page canvas
30+
await page.getByText('Devices').click();
31+
const componentSecondPage = page
32+
.getByText('Browser', { exact: true })
33+
.locator('..');
34+
35+
const position2 = await getLocatorPosition(componentSecondPage);
36+
const targetPosition2 = { x: position2.x + 400, y: position2.y };
37+
await dragAndDrop(page, position2, targetPosition2);
38+
39+
await page.getByText('Pages').click();
40+
41+
// Verify if browser is in page 2 (current selected page)
42+
const browser = await getByShapeType(page, 'browser');
43+
expect(browser).toBeDefined();
44+
45+
// Switch to page 1
46+
const pageOne = page.getByText('Page 1', { exact: true }).locator('..');
47+
await pageOne.click();
48+
49+
// Verify if in page 1: mobile visible, browser not visible
50+
const mobile = await getByShapeType(page, 'mobilePhone');
51+
const browserInPage1 = await getByShapeType(page, 'browser');
52+
53+
expect(mobile).toBeDefined();
54+
expect(browserInPage1).toBeUndefined();
55+
56+
// Add button to page 1 to verify shapes are added to correct active page
57+
await page.getByText('Components', { exact: true }).click();
58+
const button = page.getByAltText('Button', { exact: true });
59+
60+
const position3 = await getLocatorPosition(button);
61+
const targetPosition3 = { x: position.x + 500, y: position.y - 100 };
62+
await dragAndDrop(page, position3, targetPosition3);
63+
64+
// Verify button was added to canvas in page 1
65+
const buttonInCanvas = await getByShapeType(page, 'button');
66+
expect(mobile).toBeDefined();
67+
expect(buttonInCanvas).toBeDefined();
68+
});

0 commit comments

Comments
 (0)