Skip to content

Commit

Permalink
Order payment and fulfillment with transaction flow tests (#4561)
Browse files Browse the repository at this point in the history
* Create order with activated transaction flow in channel test

* new assertions

* Mark order as fully paid and fullfill all variants

* Trigger Build

* capture manual transactions test

* remove not needed expect
  • Loading branch information
wojteknowacki authored Dec 20, 2023
1 parent 2948281 commit 7d59680
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 4 deletions.
6 changes: 6 additions & 0 deletions .changeset/rich-hairs-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"saleor-dashboard": minor
---

Mark order as fully paid and fulfill all variants test
Manual capture transactions and fulfill order test
13 changes: 13 additions & 0 deletions playwright/data/e2eTestData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,19 @@ export const PRODUCTS = {
},
};

export const ORDERS = {
ordersWithinTransactionFlow: {
markAsPaidOrder: {
orderId: "T3JkZXI6MDE4ZWM0NGUtNTgwMC00NGM0LTliMzAtZDE3YTIxYjljOTgz",
info: "Order used to mark as paid and fulfill",
},
captureManualTransactionOrder: {
orderId: "T3JkZXI6MmE1NTNkMzktOWU0OS00ZWE5LWIyNzEtNzk2ZWI5OGJhNzcz",
info: "Order used to capture manual transactions and fulfill",
},
},
};

export const SHIPPING_METHODS = {
shippingMethodWithoutRates: {
id: "U2hpcHBpbmdab25lOjIzNzg%3D",
Expand Down
1 change: 1 addition & 0 deletions playwright/pages/basePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class BasePage {
constructor(
page: Page,
readonly pageHeader = page.getByTestId("page-header"),
readonly pageHeaderStatusInfo = page.getByTestId("status-info"),
readonly bulkDeleteGridRowsButton = page.getByTestId("bulk-delete-button"),
readonly gridCanvas = page.locator('[data-testid="data-grid-canvas"]'),
readonly gridInput = page
Expand Down
45 changes: 45 additions & 0 deletions playwright/pages/dialogs/manualTransactionDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { Page } from "@playwright/test";

export class ManualTransactionDialog {
constructor(
page: Page,
readonly transactionDescriptionInput = page.getByTestId(
"transactionDescription",
),
readonly createManualTransactionButton = page.getByTestId(
"manualTransactionSubmit",
),
readonly transactionPspReferenceInput = page.getByTestId(
"transactionPspReference",
),
readonly transactAmountInput = page.getByTestId("transactAmountInput"),
) {}

async clickCreateManualTransactionButton() {
await this.createManualTransactionButton.click();
await this.createManualTransactionButton.waitFor({ state: "hidden" });
}

async typeTransactionDescription(description = "partial payment") {
await this.transactionDescriptionInput.fill(description);
}

async typeTransactionPspReference(reference = "999999999") {
await this.transactionPspReferenceInput.fill(reference);
}

async typeTransactionAmount(amount = "100") {
await this.transactAmountInput.fill(amount);
}

async completeManualTransactionDialogAndSave(
description: string,
reference: string,
transactionAmount: string,
) {
await this.typeTransactionDescription(description);
await this.typeTransactionDescription(reference);
await this.typeTransactionAmount(transactionAmount);
await this.clickCreateManualTransactionButton();
}
}
17 changes: 17 additions & 0 deletions playwright/pages/dialogs/markOrderAsPaidDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Page } from "@playwright/test";

export class MarkOrderAsPaidDialog {
constructor(
page: Page,
readonly transactionReferenceInput = page
.getByTestId("transaction-reference-input")
.locator("input"),
readonly confirmButton = page.getByTestId("submit"),
) {}

async typeAndSaveOrderReference(value = "09728937896253") {
await this.transactionReferenceInput.fill(value);
await this.confirmButton.click();
await this.transactionReferenceInput.waitFor({ state: "hidden" });
}
}
15 changes: 15 additions & 0 deletions playwright/pages/fulfillmentPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Page } from "@playwright/test";

export class FulfillmentPage {
readonly page: Page;
constructor(
page: Page,
readonly fulfillButton = page.getByTestId("button-bar-confirm"),
) {
this.page = page;
}

async clickFulfillButton() {
await this.fulfillButton.click();
}
}
30 changes: 28 additions & 2 deletions playwright/pages/ordersPage.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
import { URL_LIST } from "@data/url";
import { ManualTransactionDialog } from "@dialogs/manualTransactionDialog";
import { MarkOrderAsPaidDialog } from "@dialogs/markOrderAsPaidDialog";
import { BasePage } from "@pages/basePage";
import { AddProductsDialog } from "@pages/dialogs/addProductsDialog";
import { AddressDialog } from "@pages/dialogs/addressDialog";
import { OrderCreateDialog } from "@pages/dialogs/orderCreateDialog";
import { ShippingAddressDialog } from "@pages/dialogs/shippingMethodDialog";
import { Page } from "@playwright/test";

import { BasePage } from "./basePage";

export class OrdersPage extends BasePage {
orderCreateDialog: OrderCreateDialog;
markOrderAsPaidDialog: MarkOrderAsPaidDialog;
addProductsDialog: AddProductsDialog;
addressDialog: AddressDialog;
shippingAddressDialog: ShippingAddressDialog;
basePage: BasePage;
manualTransactionDialog: ManualTransactionDialog;

constructor(
page: Page,
readonly createOrderButton = page.getByTestId("create-order-button"),
readonly markAsPaidButton = page.getByTestId("markAsPaidButton"),
readonly manualTransactionButton = page.getByTestId(
"captureManualTransactionButton",
),
readonly orderSummarySection = page.getByTestId("OrderSummaryCard"),
readonly paymentSummarySection = page.getByTestId("payment-section"),
readonly paymentStatusInfo = page.getByTestId("payment-status"),
readonly fulfillButton = page.getByTestId("fulfill-button"),
readonly addProducts = page.getByTestId("add-products-button"),
readonly orderTransactionsList = page
.getByTestId("orderTransactionsList")
.locator("table"),
readonly salesChannel = page.getByTestId("salesChannel"),
readonly editCustomerButton = page.getByTestId("edit-customer"),
readonly searchCustomerInput = page.getByTestId("select-customer"),
Expand All @@ -35,11 +45,13 @@ export class OrdersPage extends BasePage {
),
) {
super(page);
this.markOrderAsPaidDialog = new MarkOrderAsPaidDialog(page);
this.orderCreateDialog = new OrderCreateDialog(page);
this.basePage = new BasePage(page);
this.addProductsDialog = new AddProductsDialog(page);
this.addressDialog = new AddressDialog(page);
this.shippingAddressDialog = new ShippingAddressDialog(page);
this.manualTransactionDialog = new ManualTransactionDialog(page);
}

async selectCustomer(customer = "allison.freeman@example.com") {
Expand All @@ -48,6 +60,15 @@ export class OrdersPage extends BasePage {
async clickCreateOrderButton() {
await this.createOrderButton.click();
}
async clickManualTransactionButton() {
await this.manualTransactionButton.click();
}
async clickMarkAsPaidButton() {
await this.markAsPaidButton.click();
}
async clickFulfillButton() {
await this.fulfillButton.click();
}
async clickAddShippingCarrierButton() {
await this.addShippingCarrierLink.click();
}
Expand All @@ -70,4 +91,9 @@ export class OrdersPage extends BasePage {
async goToOrdersListView() {
await this.page.goto(URL_LIST.orders);
}
async goToExistingOrderPage(orderId: string) {
const orderLink = URL_LIST.orders + orderId;
await console.log("Navigating to order details view: " + orderLink);
await this.page.goto(orderLink);
}
}
92 changes: 91 additions & 1 deletion playwright/tests/orders.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { PRODUCTS } from "@data/e2eTestData";
import { ORDERS, PRODUCTS } from "@data/e2eTestData";
import { FulfillmentPage } from "@pages/fulfillmentPage";
import { OrdersPage } from "@pages/ordersPage";
import { expect, test } from "@playwright/test";

test.use({ storageState: "playwright/.auth/admin.json" });
let ordersPage: OrdersPage;
let fulfillmentPage: FulfillmentPage;

test.beforeEach(({ page }) => {
ordersPage = new OrdersPage(page);
fulfillmentPage = new FulfillmentPage(page);
});

test("TC: SALEOR_28 Create basic order @e2e @order", async () => {
Expand Down Expand Up @@ -55,3 +58,90 @@ test("TC: SALEOR_76 Create order with transaction flow activated @e2e @order", a
await expect(ordersPage.orderSummarySection).toBeVisible();
await expect(ordersPage.fulfillButton).toBeDisabled();
});

test("TC: SALEOR_77 Mark order as paid and fulfill it with transaction flow activated @e2e @order", async () => {
await ordersPage.goToExistingOrderPage(
ORDERS.ordersWithinTransactionFlow.markAsPaidOrder.orderId,
);
await ordersPage.waitForGrid();
await ordersPage.clickMarkAsPaidButton();
await ordersPage.markOrderAsPaidDialog.typeAndSaveOrderReference();
await ordersPage.expectSuccessBannerMessage("paid");
const transactionsMadeRows = await ordersPage.orderTransactionsList.locator(
"tr",
);
expect(await transactionsMadeRows.count()).toEqual(1);
await expect(transactionsMadeRows).toContainText("Success");
await ordersPage.clickFulfillButton();
await fulfillmentPage.clickFulfillButton();
await ordersPage.expectSuccessBannerMessage("fulfilled");
expect(await ordersPage.pageHeaderStatusInfo).toContainText("Fulfilled");
});

test("TC: SALEOR_78 Capture partial amounts by manual transactions and fulfill order with transaction flow activated @e2e @order", async () => {
const firstManualTransactionAmount = "100";
const secondManualTransactionAmount = "20";

await ordersPage.goToExistingOrderPage(
ORDERS.ordersWithinTransactionFlow.captureManualTransactionOrder.orderId,
);
await ordersPage.waitForGrid();
await ordersPage.clickManualTransactionButton();
await ordersPage.manualTransactionDialog.completeManualTransactionDialogAndSave(
"partial payment 1",
"111111",
firstManualTransactionAmount,
);
const completedTransactionsRows =
await ordersPage.orderTransactionsList.locator("tr");

await expect(
completedTransactionsRows.filter({
hasText: `EUR${firstManualTransactionAmount}`,
}),
"Row with first manual transaction details is visible with Success status",
).toContainText("Success");
expect(
await ordersPage.pageHeaderStatusInfo,
"Order should not be yet fulfilled",
).toContainText("Unfulfilled");
expect(
await ordersPage.paymentStatusInfo,
"Order should be partially paid",
).toContainText("Partially paid");

await ordersPage.clickManualTransactionButton();
await ordersPage.manualTransactionDialog.completeManualTransactionDialogAndSave(
"partial payment 2",
"222222",
secondManualTransactionAmount,
);

await expect(
completedTransactionsRows.filter({
hasText: `EUR${secondManualTransactionAmount}`,
}),
"Row with first manual transaction details is visible with Success status",
).toContainText("Success");
expect(
await completedTransactionsRows.filter({ hasText: "Success" }).count(),
"Two rows are visible within Manual capture sections with Success status",
).toEqual(2);
expect(
await ordersPage.pageHeaderStatusInfo,
"Order should not be yet fulfilled",
).toContainText("Unfulfilled");
expect(
await ordersPage.paymentStatusInfo,
"Order should fully paid",
).toContainText("Fully paid");

await ordersPage.clickFulfillButton();
await fulfillmentPage.clickFulfillButton();
await ordersPage.expectSuccessBannerMessage("fulfilled");

expect(
await ordersPage.pageHeaderStatusInfo,
"Order should be yet fulfilled",
).toContainText("Fulfilled");
});
2 changes: 1 addition & 1 deletion src/orders/components/OrderDetailsPage/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const Title: React.FC<TitleProps> = props => {
{ orderNumber: order?.number },
)}
<div className={classes.statusContainer}>
<Pill label={localized} color={status} />
<Pill data-test-id="status-info" label={localized} color={status} />
</div>
</Box>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const OrderPaymentSummaryCard: React.FC<OrderPaymementProps> = ({
label={payment.localized}
color={payment.status}
className={classes.paymentStatus}
data-test-id="payment-status"
/>
}
title={<FormattedMessage {...orderPaymentMessages.paymentTitle} />}
Expand Down

0 comments on commit 7d59680

Please sign in to comment.