Skip to content

Commit

Permalink
Merge branch 'dev' into feature/#227-add-icons
Browse files Browse the repository at this point in the history
  • Loading branch information
IonutGabi committed Oct 28, 2024
2 parents 9b7c2a2 + 2d7871e commit e3d6722
Show file tree
Hide file tree
Showing 25 changed files with 659 additions and 211 deletions.
17 changes: 16 additions & 1 deletion e2e/helpers/konva-testing.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Layer } from 'konva/lib/Layer';
import { Shape } from 'konva/lib/Shape';
import { Group } from 'konva/lib/Group';
import { E2E_CanvasItemKeyAttrs } from './types/e2e-types';
import { getCanvasBoundingBox } from './position.helpers';

const getLayer = async (page: Page): Promise<Layer> =>
await page.evaluate(() => {
Expand Down Expand Up @@ -77,7 +78,8 @@ export const clickOnCanvasItem = async (
item: E2E_CanvasItemKeyAttrs
) => {
const { x, y } = item;
const canvasWindowPos = await page.locator('canvas').boundingBox();
const stageCanvas = await page.locator('#konva-stage canvas').first();
const canvasWindowPos = await stageCanvas.boundingBox();
if (!canvasWindowPos) throw new Error('Canvas is not loaded on ui');
await page.mouse.move(
canvasWindowPos?.x + x + 20,
Expand All @@ -90,6 +92,19 @@ export const clickOnCanvasItem = async (
return item;
};

export const dbClickOnCanvasItem = async (
page: Page,
item: E2E_CanvasItemKeyAttrs
) => {
const { x, y } = item;
const canvasWindowPos = await getCanvasBoundingBox(page);
await page.mouse.dblclick(
canvasWindowPos?.x + x + 20,
canvasWindowPos?.y + y + 20
);
return item;
};

export const ctrlClickOverCanvasItems = async (
page: Page,
itemList: E2E_CanvasItemKeyAttrs[]
Expand Down
14 changes: 13 additions & 1 deletion e2e/helpers/position.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ export const getLocatorPosition = async (
return { x: box.x + box.width / 2, y: box.y + box.height / 2 };
};

export const getCanvasBoundingBox = async (page: Page) => {
const canvasWindowPos = await page
.locator('#konva-stage canvas')
.boundingBox();
if (canvasWindowPos) {
return canvasWindowPos;
} else {
throw new Error('Canvas is not loaded on ui');
}
};

export const dragAndDrop = async (
page: Page,
aPosition: Position,
Expand All @@ -34,7 +45,8 @@ export const addComponentsToCanvas = async (
page: Page,
components: string[]
) => {
const canvasPosition = await page.locator('canvas').boundingBox();
const stageCanvas = await page.locator('#konva-stage canvas').first();
const canvasPosition = await stageCanvas.boundingBox();
if (!canvasPosition) throw new Error('No canvas found');

for await (const [index, c] of components.entries()) {
Expand Down
3 changes: 2 additions & 1 deletion e2e/selection/shape-selection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ test('drop shape in canvas, click on canvas, drop diselected', async ({
const inputShape = (await getByShapeType(page, 'input')) as Group;
expect(inputShape).toBeDefined();

await page.click('canvas');
//Click Away
await page.mouse.click(800, 130);

const transformer = await getTransformer(page);
expect(transformer).toBeDefined();
Expand Down
3 changes: 2 additions & 1 deletion e2e/ui-functionality/copy-paste.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ test.describe('Copy/Paste functionality tests', () => {
);
});

/*
test('Should copy and paste a multiple shapes using the ToolBar UI buttons', async ({
page,
}) => {
Expand Down Expand Up @@ -112,7 +113,7 @@ test.describe('Copy/Paste functionality tests', () => {
expect(originalComp_2['data-id']).not.toEqual(copiedComp_2['data-id']);
expect(originalComp_3['data-id']).not.toEqual(copiedComp_3['data-id']);
});

*/
test('Should copy and paste a multiple shapes using keyboard commands', async ({
page,
}) => {
Expand Down
166 changes: 166 additions & 0 deletions e2e/ui-functionality/toolbar_undo-redo.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { test, expect } from '@playwright/test';
import {
addComponentsToCanvas,
getWithinCanvasItemList,
getByShapeType,
dbClickOnCanvasItem,
getCanvasBoundingBox,
getShapePosition,
} from '../helpers';
import { E2E_CanvasItemKeyAttrs } from '../helpers/types/e2e-types';
import { Group } from 'konva/lib/Group';
import {
clickRedoUiButton,
clickUndoUiButton,
} from '../helpers/ui-buttons.helpers';

test.describe('ToolBar buttons Undo/Redo functionality tests', () => {
test.beforeEach(async ({ page }) => {
await page.goto('');
});

test('Should remove and restore a just dragged into canvas-item, respectively', async ({
page,
}) => {
//Arrange
const addInputIntoCanvas = ['Input'];
await addComponentsToCanvas(page, addInputIntoCanvas);

//Undo and check within canvas items
await clickUndoUiButton(page);
const insideCanvasItemList = await getWithinCanvasItemList(page);

expect(insideCanvasItemList.length).toEqual(0);

//Redo and check existing item within canvas
await clickRedoUiButton(page);
const updatedInsideCanvasItemList = await getWithinCanvasItemList(page);

expect(updatedInsideCanvasItemList.length).toEqual(1);
});

test('Should remove and restore the last item you just dragged into the canvas', async ({
page,
}) => {
//Arrange
const addComponentsIntoCanvas = ['Input', 'Combobox'];
await addComponentsToCanvas(page, addComponentsIntoCanvas);

//Undo and assert there is only one Item within canvas
await clickUndoUiButton(page);
const insideCanvasItemList = await getWithinCanvasItemList(page);

expect(insideCanvasItemList.length).toEqual(1);

const firsCanvastItem = await getByShapeType(page, 'input');
expect(firsCanvastItem).toBeDefined();

//Redo and assert both items are contained within the canvas
await clickRedoUiButton(page);
const updatedInsideCanvasItemList = await getWithinCanvasItemList(page);
const secondCanvasItem = await getByShapeType(page, 'combobox');

expect(updatedInsideCanvasItemList.length).toEqual(2);
expect(firsCanvastItem).toBeDefined();
expect(secondCanvasItem).toBeDefined();
});

test('Should reverse and restore an edited text of an Input Component', async ({
page,
}) => {
//Arrange data and drag an input
const addComponentsIntoCanvas = ['Input'];
const defaultInputPlaceholder = 'Placeholder';
const updatedText = 'Hello';

await addComponentsToCanvas(page, addComponentsIntoCanvas);
const [inputOnCanvas] = (await getWithinCanvasItemList(
page
)) as E2E_CanvasItemKeyAttrs[];

//Start Input component inline editing
await dbClickOnCanvasItem(page, inputOnCanvas);
const editableInput = page.locator('input[data-is-inline-edition-on=true]');
const defaultInputValue = await editableInput.inputValue();

await editableInput.fill(updatedText);
const updatedInputValue = await editableInput.inputValue();

//Undo edit and assert text is reversed
await clickUndoUiButton(page);
expect(defaultInputValue).toEqual(defaultInputPlaceholder);

//Redo edit and assert that input contains the restored updated text
await clickRedoUiButton(page);
expect(updatedInputValue).toEqual(updatedText);
});

test('Should restore the item position to its previous placement', async ({
page,
}) => {
//Arrange data and drag an input into canvas
const componentToAddintoCanvas = ['Input'];
await addComponentsToCanvas(page, componentToAddintoCanvas);

const { x: canvasXStart, y: canvasYStart } =
await getCanvasBoundingBox(page);

const inputElement = (await getByShapeType(page, 'input')) as Group;

const inputInitialPosition = await getShapePosition(inputElement);
const inputModifiedPosition = {
x: inputInitialPosition.x + canvasXStart + 200,
y: inputInitialPosition.y + canvasYStart,
};

//Displace item within the canvas
await page.mouse.down();
await page.mouse.move(inputModifiedPosition.x, inputModifiedPosition.y);
await page.mouse.up();

//Undo and assert that the item is placed in its initial position
await clickUndoUiButton(page);
const finalInputPosition = await getShapePosition(inputElement);

expect(finalInputPosition).toEqual(inputInitialPosition);
});

test('Should undo and redo, backward and forward severals steps consistently', async ({
page,
}) => {
//Arrange data and drag an items into canvas
const componentsToAddIntoCanvas = ['Input', 'Combobox'];
await addComponentsToCanvas(page, componentsToAddIntoCanvas);

await page.getByText('Rich Components').click();
const richComponentsToAddintoCanvas = ['Accordion'];
await addComponentsToCanvas(page, richComponentsToAddintoCanvas);

//Assert there are 3 items within the canvas
const itemsQtyWithinCanvas_step1 = (await getWithinCanvasItemList(page))
.length;

expect(itemsQtyWithinCanvas_step1).toEqual(3);

//x3 undo
await clickUndoUiButton(page);
await clickUndoUiButton(page);
await clickUndoUiButton(page);

//Assert there are no items within the canvas
const itemsQtyWithinCanvas_step2 = (await getWithinCanvasItemList(page))
.length;

expect(itemsQtyWithinCanvas_step2).toEqual(0);

//x3 redo
await clickRedoUiButton(page);
await clickRedoUiButton(page);
await clickRedoUiButton(page);

//Assert there are again 3 items within the canvas
const itemsQtyWithinCanvas_step3 = (await getWithinCanvasItemList(page))
.length;
expect(itemsQtyWithinCanvas_step3).toEqual(3);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,33 @@ export const InputShape = forwardRef<any, ShapeProps>((props, ref) => {
</Group>
);
});

/*
<Group {...commonGroupProps} {...shapeProps}>
<Rect
x={0}
y={0}
width={restrictedWidth}
height={restrictedHeight}
cornerRadius={borderRadius}
stroke={stroke}
dash={strokeStyle}
strokeWidth={INPUT_SHAPE.DEFAULT_STROKE_WIDTH}
fill={fill}
/>
<Text
x={INPUT_SHAPE.DEFAULT_PADDING}
y={INPUT_SHAPE.DEFAULT_PADDING + 1}
width={width - INPUT_SHAPE.DEFAULT_PADDING * 2}
text={text}
fontFamily={INPUT_SHAPE.DEFAULT_FONT_FAMILY}
fontSize={INPUT_SHAPE.DEFAULT_FONT_SIZE}
lineHeight={INPUT_SHAPE.DEFAULT_LINE_HEIGHT}
fill={textColor}
align="left"
ellipsis={true}
wrap="none"
/>
</Group>
*/
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const getBrowserWindowShapeSizeRestrictions =
const shapeType: ShapeType = 'browser';

export const BrowserWindowShape = forwardRef<any, ShapeProps>((props, ref) => {
const { x, y, width, height, id, onSelected, ...shapeProps } = props;
const { x, y, width, height, id, onSelected, text, ...shapeProps } = props;
const restrictedSize = fitSizeToShapeSizeRestrictions(
browserWindowShapeSizeRestrictions,
width,
Expand Down Expand Up @@ -114,9 +114,9 @@ export const BrowserWindowShape = forwardRef<any, ShapeProps>((props, ref) => {
<Text
x={margin * 4}
y={margin * 3.5 + titleBarHeight}
width={restrictedWidth - 50}
height={restrictedHeight - 50}
text="https://example.com"
width={restrictedWidth - margin * 7}
height={urlBarHeight}
text={text}
fontFamily={BASIC_SHAPE.DEFAULT_FONT_FAMILY}
fontSize={12}
fill="black"
Expand Down
27 changes: 6 additions & 21 deletions src/core/local-disk/shapes-to-document.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
import { ShapeModel } from '../model';
import { DocumentModel } from '../providers/canvas/canvas.model';
import { QuickMockFileContract, Page } from './local-disk.model';
import { QuickMockFileContract } from './local-disk.model';

export const mapFromShapesArrayToQuickMockFileDocument = (
shapes: ShapeModel[]
fullDocument: DocumentModel
): QuickMockFileContract => {
const pages: Page[] = shapes.reduce((acc, shape) => {
/*
* TODO: Add the correct id, name and version values.
*/
const newPage: Page = {
id: '1',
name: 'default',
shapes: [{ ...shape }],
};

return [...acc, newPage];
}, [] as Page[]);

// TODO: Serialize the activePageIndex?
return {
version: '0.1',
pages,
pages: fullDocument.pages,
};
};

export const mapFromQuickMockFileDocumentToApplicationDocument = (
fileDocument: QuickMockFileContract
): DocumentModel => {
const shapes: ShapeModel[] = fileDocument.pages.reduce((acc, page) => {
return [...acc, ...page.shapes];
}, [] as ShapeModel[]);
return {
shapes,
activePageIndex: 0,
pages: fileDocument.pages,
};
};
Loading

0 comments on commit e3d6722

Please sign in to comment.