Skip to content

Commit

Permalink
Add e2e scenario for removing an inter-service relation (Issue #6047,…
Browse files Browse the repository at this point in the history
… PR #6069)

# Description

Added e2e for inter-service relations, fixed issue with removing inter-service relations for instance that could have an array of those, added constraint to deploy button, fixed issue with relation removal didn't trigger the update of the cell

closes #6007

# Self Check:

Strike through any lines that are not applicable (`~~line~~`) then check the box

- [ ] Attached issue to pull request
- [ ] Changelog entry
- [ ] Code is clear and sufficiently documented
- [ ] Sufficient test cases (reproduces the bug/tests the requested feature)
- [ ] Correct, in line with design
- [ ] End user documentation is included or an issue is created for end-user documentation (add ref to issue here: )
  • Loading branch information
matborowczyk authored and inmantaci committed Nov 26, 2024
1 parent f5ef81e commit 22d0e0a
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 26 deletions.
4 changes: 4 additions & 0 deletions changelogs/unreleased/6007-e2e-removal-scenario.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
description: Add e2e scenario for removing an inter-service relation
issue-nr: 6047
change-type: patch
destination-branches: [master]
143 changes: 137 additions & 6 deletions cypress/e2e/scenario-8-instance-composer.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ if (Cypress.env("edition") === "iso") {
cy.get('[aria-label="Environment card"]')
.contains("lsm-frontend")
.click();
cy.get(".pf-v5-c-nav__item").contains("Service Catalog").click();
cy.get("a").contains("Service Catalog").click();

// click on Show Inventory on embedded-entity-service-extra, expect no instances
cy.get("#container-service", { timeout: 60000 })
Expand Down Expand Up @@ -149,7 +149,7 @@ if (Cypress.env("edition") === "iso") {
cy.get('[aria-label="Environment card"]')
.contains("lsm-frontend")
.click();
cy.get(".pf-v5-c-nav__item").contains("Service Catalog").click();
cy.get("a").contains("Service Catalog").click();

//Add parent instance
// click on Show Inventory of parent-service, expect no instances
Expand Down Expand Up @@ -233,7 +233,7 @@ if (Cypress.env("edition") === "iso") {
.should("have.text", "up", { timeout: 90000 });

//Add many-defaults instance
cy.get(".pf-v5-c-nav__item").contains("Service Catalog").click();
cy.get("a").contains("Service Catalog").click();
// click on Show Inventory of many-defaults service, expect no instances
cy.get("#many-defaults", { timeout: 60000 })
.contains("Show inventory")
Expand Down Expand Up @@ -563,7 +563,7 @@ if (Cypress.env("edition") === "iso") {
cy.get('[aria-label="Environment card"]')
.contains("lsm-frontend")
.click();
cy.get(".pf-v5-c-nav__item").contains("Service Catalog").click();
cy.get("a").contains("Service Catalog").click();
// click on Show Inventory of many-defaults service, expect no instances
cy.get("#many-defaults", { timeout: 60000 })
.contains("Show inventory")
Expand Down Expand Up @@ -724,13 +724,13 @@ if (Cypress.env("edition") === "iso") {
);
});

it("8.4 composer edit view is able to add/remove instances relations", () => {
it("8.4 composer edit view is able to edit instances relations", () => {
// Select 'test' environment
cy.visit("/console/");
cy.get('[aria-label="Environment card"]')
.contains("lsm-frontend")
.click();
cy.get(".pf-v5-c-nav__item").contains("Service Catalog").click();
cy.get("a").contains("Service Catalog").click();
// click on Show Inventory of many-defaults service, expect no instances
cy.get("#child-service", { timeout: 60000 })
.contains("Show inventory")
Expand Down Expand Up @@ -870,5 +870,136 @@ if (Cypress.env("edition") === "iso") {
cy.get('[data-label="active"]').should("have.text", "test_name2");
});
});

it("8.5 composer edit view is able to remove inter-service relation from instance", () => {
// Select 'test' environment
cy.visit("/console/");
cy.get('[aria-label="Environment card"]')
.contains("lsm-frontend")
.click();
cy.get("a").contains("Service Catalog").click();
// click on Show Inventory of many-defaults service, expect no instances
cy.get("#child-with-many-parents-service", { timeout: 60000 })
.contains("Show inventory")
.click();
cy.get('[aria-label="ServiceInventory-Empty"]').should("to.be.visible");
// click on add instance with composer
cy.get('[aria-label="AddInstanceToggle"]').click();
cy.get("#add-instance-composer-button").click();

//fill child attributes
cy.get('[data-type="app.ServiceEntityBlock"')
.contains("child-with-many")
.click();
cy.get('[aria-label="TextInput-name"]').type("child_test");
cy.get('[aria-label="TextInput-service_id"]').type("child_test_id");

//add parent instances to the canvas and connect them to the core instance
cy.get("#inventory-tab").click();

//add first inter-service relation
cy.get(".bodyTwo_test_name")
.trigger("mouseover")
.trigger("mousedown")
.trigger("mousemove", {
clientX: 800,
clientY: 500,
})
.trigger("mouseup");

cy.get('[data-type="app.ServiceEntityBlock"')
.contains("child-with-many")
.click();
cy.get('[data-action="link"]')
.trigger("mouseover")
.trigger("mousedown")
.trigger("mousemove", {
clientX: 800,
clientY: 600,
})
.trigger("mouseup");

//add second inter-service relation
cy.get(".bodyTwo_test_name2")
.trigger("mouseover")
.trigger("mousedown")
.trigger("mousemove", {
clientX: 800,
clientY: 700,
})
.trigger("mouseup");

cy.get('[data-type="app.ServiceEntityBlock"')
.contains("child-with-many")
.click();
cy.get('[data-action="link"]')
.trigger("mouseover")
.trigger("mousedown")
.trigger("mousemove", {
clientX: 800,
clientY: 800,
})
.trigger("mouseup");

cy.get('[data-type="Link"]').should("have.length", 2);

cy.get("button").contains("Deploy").click();

cy.get('[data-label="State"]', { timeout: 90000 })
.eq(0, { timeout: 90000 })
.should("have.text", "up", { timeout: 90000 });

// click on edit instance with composer
cy.get('[aria-label="row actions toggle"]').click();
cy.get("button").contains("Edit in Composer").click();

cy.get('[data-type="app.ServiceEntityBlock"')
.contains("test_name2")
.click();

cy.get("button").contains("Remove").click();
cy.get("button").contains("Deploy").click();

cy.get('[data-label="State"]', { timeout: 90000 })
.eq(0, { timeout: 90000 })
.should("have.text", "up", { timeout: 90000 });

//go to details view
cy.get('[aria-label="row actions toggle"]').click();
cy.get("button").contains("Instance Details").click();

//assert that in Active attribute we have only 1 relation
cy.get('[aria-label="Expand row 2"]').click();

const uuidRegex =
/^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;

cy.get('[data-testid="0"]')
.invoke("text")
.then((text) => {
expect(text).to.match(uuidRegex);
});

cy.get('[data-testid="1"]').should("not.exist");

//assert that in Rollback attribute we have 2 relations
cy.get('[aria-label="Select-AttributeSet"]').select(
"rollback_attributes",
);

cy.get('[aria-label="Expand row 2"]').click();

cy.get('[data-testid="0"]')
.invoke("text")
.then((text) => {
expect(text).to.match(uuidRegex);
});

cy.get('[data-testid="1"]')
.invoke("text")
.then((text) => {
expect(text).to.match(uuidRegex);
});
});
});
}
19 changes: 16 additions & 3 deletions src/UI/Components/Diagram/components/ComposerActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ export const ComposerActions: React.FC<Props> = ({ serviceName, editable }) => {
const { serviceModels, mainService, instance } = useContext(
InstanceComposerContext,
);
const { serviceOrderItems, isDirty, looseElement, diagramHandlers } =
useContext(CanvasContext);
const {
serviceOrderItems,
isDirty,
looseElement,
diagramHandlers,
interServiceRelationsOnCanvas,
} = useContext(CanvasContext);
const { routeManager, environmentHandler } = useContext(DependencyContext);

const [alertMessage, setAlertMessage] = useState("");
Expand Down Expand Up @@ -100,6 +105,13 @@ export const ComposerActions: React.FC<Props> = ({ serviceName, editable }) => {

orderMutation.mutate(orderItems);
};
const missingInterServiceRelations = Array.from(
interServiceRelationsOnCanvas,
).filter(
([_key, value]) =>
value.relations.filter((relation) => relation.current < relation.min)
.length > 0,
);

useEffect(() => {
if (orderMutation.isSuccess) {
Expand Down Expand Up @@ -153,7 +165,8 @@ export const ComposerActions: React.FC<Props> = ({ serviceName, editable }) => {
serviceOrderItems.size < 1 ||
!isDirty ||
looseElement.size > 0 ||
!editable
!editable ||
missingInterServiceRelations.length > 0
}
>
{words("deploy")}
Expand Down
36 changes: 20 additions & 16 deletions src/UI/Components/Diagram/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,27 +375,31 @@ export const shapesDataTransform = (

//convert relatedTo property into valid attribute
if (parentInstance.relatedTo) {
Array.from(parentInstance.relatedTo).forEach(([id, attributeName]) => {
if (parentInstance.attributes) {
const model = serviceModel.inter_service_relations.find(
(relation) => relation.name === attributeName,
const tempHolderForRelation: InstanceAttributeModel = {}; //this is solution for the case when we are updating the instance with Array of the relations

serviceModel.inter_service_relations.forEach((relation) => {
if (parentInstance.relatedTo) {
const relations = Array.from(parentInstance.relatedTo).filter(
([_id, attributeName]) => attributeName === relation.name,
);

if (model) {
if (model.upper_limit !== 1) {
if (Array.isArray(parentInstance.attributes[attributeName])) {
(parentInstance.attributes[attributeName] as dia.Cell.ID[]).push(
id,
);
} else {
parentInstance.attributes[attributeName] = [id];
}
} else {
parentInstance.attributes[attributeName] = id;
}
if (relation.upper_limit !== 1) {
tempHolderForRelation[relation.name] = relations.map(([id]) => id);
} else {
tempHolderForRelation[relation.name] = relations[0]
? relations[0][0]
: undefined;
}
}
});

Array.from(Object.entries(tempHolderForRelation)).forEach(
([key, value]) => {
if (parentInstance.attributes) {
parentInstance.attributes[key] = value;
}
},
);
}

//if any of its embedded instances were edited, and its action is indicating no changes to main attributes, change it to "update"
Expand Down
3 changes: 2 additions & 1 deletion src/UI/Components/Diagram/paper/paper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,10 @@ export class ComposerPaper {
},
}),
);

document.dispatchEvent(
new CustomEvent("updateServiceOrderItems", {
detail: { cell: sourceCell, action: ActionEnum.UPDATE },
detail: { cell: targetCell, action: ActionEnum.UPDATE },
}),
);
toggleLooseElement(
Expand Down

0 comments on commit 22d0e0a

Please sign in to comment.