Skip to content

Commit

Permalink
Fix drag and drop error in Playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasEng committed Jul 23, 2024
1 parent ff68b2e commit 349e8f9
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 51 deletions.
11 changes: 10 additions & 1 deletion frontend/testing/playwright/helpers/BasePage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as nbTexts from '@altinn-studio/language/src/nb.json';
import * as enTexts from '@altinn-studio/language/src/en.json';
import type { Page } from '@playwright/test';
import type { Locator, Page } from '@playwright/test';
import { RouterRoute } from './RouterRoute';
import type { Environment } from './StudioEnvironment';

Expand Down Expand Up @@ -42,4 +42,13 @@ export class BasePage extends RouterRoute {
}, milliseconds),
);
}

// Use this in favor of Playwright's dragTo method when the exact element that is supposed to listen to the drop event is unknown (i.e. if it may be a child element of the target)
public async dragAndDropManually(source: Locator, target: Locator): Promise<void> {
await source.hover();
await this.page.mouse.down();
const numberOfTimesToHover: number = 5; // Target must be hovered multiple times - see https://playwright.dev/docs/input#dragging-manually
for (let i = 0; i < numberOfTimesToHover; i++) await target.hover();
await this.page.mouse.up();
}
}
3 changes: 2 additions & 1 deletion frontend/testing/playwright/pages/GiteaPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export class GiteaPage extends BasePage {
}

public async verifyThatDataModelBindingsAreVisible(dataModelBinding: string): Promise<void> {
await this.page.getByText(giteaPageTexts['dataModelBindings']).isVisible();
// Todo: Check the JSON structure directly instead: https://github.com/Altinn/altinn-studio/issues/13216
await this.page.getByText(giteaPageTexts['dataModelBindings']).first().isVisible();
await this.page.getByText(dataModelBinding, { exact: true }).isVisible();
}

Expand Down
60 changes: 16 additions & 44 deletions frontend/testing/playwright/pages/UiEditorPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,32 +51,19 @@ export class UiEditorPage extends BasePage {
await this.page.getByText(this.textMock('ux_editor.container_empty')).isVisible();
}

// This is for when the list is empty
public async dragComponentInToDroppableList(component: ComponentType): Promise<void> {
const dropDestination = this.getDroppableList();

await this.getToolbarItems()
.getByText(this.textMock(`ux_editor.component_title.${component}`))
.dragTo(dropDestination);
}

// This is for when the list is is not empty
public async dragComponentInToDroppableListItem(
public async dragComponentIntoDroppableListItem(
components: DragAndDropComponents,
): Promise<void> {
const { componentToDrag, componentToDropOn } = components;
const dragLocator = await this.getDraggableComponent(componentToDrag);
const dropLocator = await this.getComponentInListByType(componentToDropOn);
await this.dragAndDropManually(dragLocator, dropLocator);
}

await this.hoverOverComponentToDrag(componentToDrag);
await this.startDragComponent();

// Dragging manually requires the hover over the droppable list treeitem to be called at least 2 times: https://playwright.dev/docs/input#dragging-manually
const numberOfTimesToHoverOverDroppableListTreeItem: number = 5;

for (let i = 0; i < numberOfTimesToHoverOverDroppableListTreeItem; i++) {
await this.hoverOverDroppableListTreeItem(componentToDropOn);
}

await this.dropComponent();
public async dragComponentIntoDroppableList(component: ComponentType): Promise<void> {
const dropDestination = this.getDroppableList();
const componentToDrag = await this.getDraggableComponent(component);
await this.dragAndDropManually(componentToDrag, dropDestination);
}

public async waitForComponentTreeItemToBeVisibleInDroppableList(
Expand Down Expand Up @@ -273,34 +260,19 @@ export class UiEditorPage extends BasePage {
await this.page.getByRole('textbox', { name: this.textMock(`language.${lang}`) }).isVisible();
}

private getToolbarItems(): Locator {
return this.page.getByTestId(DataTestId.DraggableToolbarItem);
}

private getDroppableList(): Locator {
return this.page.getByTestId(DataTestId.DroppableList);
}

private async hoverOverComponentToDrag(componentToDrag: ComponentType): Promise<void> {
await this.page
private async getDraggableComponent(componentToDrag: ComponentType): Promise<Locator> {
return this.page
.getByTestId(DataTestId.DraggableToolbarItem)
.getByText(this.textMock(`ux_editor.component_title.${componentToDrag}`))
.hover();
}

private async startDragComponent(): Promise<void> {
await this.page.mouse.down();
}

private async hoverOverDroppableListTreeItem(componentToDropOn: ComponentType): Promise<void> {
await this.page
.getByRole('treeitem', {
name: this.textMock(`ux_editor.component_title.${componentToDropOn}`),
})
.hover();
.getByText(this.textMock(`ux_editor.component_title.${componentToDrag}`));
}

private async dropComponent(): Promise<void> {
await this.page.mouse.up();
private async getComponentInListByType(componentType: ComponentType): Promise<Locator> {
return this.page.getByRole('treeitem', {
name: this.textMock(`ux_editor.component_title.${componentType}`),
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ test('That it is possible to create a text at the ux-editor page, and that the t
const uiEditorPage = new UiEditorPage(page, { app: testAppName });

await navigateToUiEditorAndVerifyPage(header, uiEditorPage);
await uiEditorPage.dragComponentInToDroppableList(ComponentType.Input);
await uiEditorPage.dragComponentIntoDroppableList(ComponentType.Input);

await uiEditorPage.deleteOldComponentId();
await uiEditorPage.writeNewComponentId(COMPONENT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ test('That it is possible to add a data model binding, and that the files are up
await uiEditorPage.verifyThatPageIsEmpty();

const newInputLabel: string = 'Input Label 1';
await uiEditorPage.dragComponentInToDroppableList(ComponentType.Input);
await uiEditorPage.dragComponentIntoDroppableList(ComponentType.Input);
await uiEditorPage.waitForComponentTreeItemToBeVisibleInDroppableList(ComponentType.Input);
await addNewLabelToTreeItemComponent(uiEditorPage, newInputLabel);

Expand Down Expand Up @@ -143,7 +143,7 @@ test('That is possible to select a different data model binding, and that the fi
await uiEditorPage.verifyUiEditorPage();
await openPageAccordionAndVerifyUpdatedUrl(uiEditorPage, pageName);

await uiEditorPage.dragComponentInToDroppableList(ComponentType.Input);
await uiEditorPage.dragComponentIntoDroppableList(ComponentType.Input);
await uiEditorPage.waitForComponentTreeItemToBeVisibleInDroppableList(ComponentType.Input);

await uiEditorPage.clickOnComponentDataModelBindingConfigAccordion();
Expand Down
4 changes: 2 additions & 2 deletions frontend/testing/playwright/tests/ui-editor/ui-editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test('That it is possible to add and delete form components', async ({

await uiEditorPage.verifyThatPageIsEmpty();

await uiEditorPage.dragComponentInToDroppableList(ComponentType.Input);
await uiEditorPage.dragComponentIntoDroppableList(ComponentType.Input);
await uiEditorPage.waitForComponentTreeItemToBeVisibleInDroppableList(ComponentType.Input);
await uiEditorPage.verifyThatPageEmptyMessageIsHidden();
});
Expand Down Expand Up @@ -88,7 +88,7 @@ test('That it is possible to add a Header component to the page when there is al
await uiEditorPage.openTextComponentSection();
await uiEditorPage.waitForDraggableToolbarItemToBeVisible(ComponentType.Header);

await uiEditorPage.dragComponentInToDroppableListItem({
await uiEditorPage.dragComponentIntoDroppableListItem({
componentToDrag: ComponentType.Header,
componentToDropOn: ComponentType.Input,
});
Expand Down

0 comments on commit 349e8f9

Please sign in to comment.