diff --git a/cypress/e2e/backoffice/purchasing-control/budget.cy.ts b/cypress/e2e/backoffice/purchasing-control/budget.cy.ts new file mode 100644 index 000000000..ad7e3c8dc --- /dev/null +++ b/cypress/e2e/backoffice/purchasing-control/budget.cy.ts @@ -0,0 +1,84 @@ +import { container } from '@utils'; +import { BackofficeBudgetCrudStaticFixtures, BackofficeBudgetCrudDynamicFixtures } from '@interfaces/backoffice'; +import { BackofficeBudgetListPage, BackofficeBudgetCreatePage, BackofficeBudgetEditPage } from '@pages/backoffice'; +import { UserLoginScenario } from '@scenarios/backoffice'; + +function formatDate(date: Date): string { + return date.toISOString().split('T')[0]; +} + +function getBudgetStartDate(): string { + const date = new Date(); + date.setMonth(date.getMonth() + 1); + date.setDate(1); + + return formatDate(date); +} + +function getBudgetEndDate(): string { + const date = new Date(); + date.setMonth(date.getMonth() + 4); + date.setDate(0); + + return formatDate(date); +} + +describe( + 'purchasing control budget crud', + { + tags: ['@backoffice', '@purchasing-control', 'purchasing-control', 'spryker-core-back-office', 'spryker-core'], + }, + (): void => { + if (['b2c', 'b2c-mp'].includes(Cypress.env('repositoryId'))) { + it.skip('skipped because tests run only for suite, b2b, and b2b-mp', () => {}); + return; + } + + const budgetListPage = container.get(BackofficeBudgetListPage); + const budgetCreatePage = container.get(BackofficeBudgetCreatePage); + const budgetEditPage = container.get(BackofficeBudgetEditPage); + const userLoginScenario = container.get(UserLoginScenario); + + let staticFixtures: BackofficeBudgetCrudStaticFixtures; + let dynamicFixtures: BackofficeBudgetCrudDynamicFixtures; + + before((): void => { + ({ staticFixtures, dynamicFixtures } = Cypress.env()); + }); + + beforeEach((): void => { + userLoginScenario.execute({ + username: dynamicFixtures.rootUser.username, + password: staticFixtures.defaultPassword, + }); + }); + + it('backoffice user should be able to create a budget for a cost center', (): void => { + budgetCreatePage.visitByCostCenter(dynamicFixtures.costCenter.id_cost_center); + + budgetCreatePage.fillName(staticFixtures.newBudgetName); + budgetCreatePage.fillAmount(staticFixtures.budgetAmount); + budgetCreatePage.selectCurrency(staticFixtures.budgetCurrency); + budgetCreatePage.selectEnforcementRule(staticFixtures.budgetEnforcementRule); + budgetCreatePage.fillStartDate(getBudgetStartDate()); + budgetCreatePage.fillEndDate(getBudgetEndDate()); + budgetCreatePage.submit(); + + budgetCreatePage.assertSuccess(); + }); + + it('backoffice user should see budget in the budget list after creation', (): void => { + budgetListPage.visitByCostCenter(dynamicFixtures.costCenter.id_cost_center); + budgetListPage.assertBudgetInTable(dynamicFixtures.preExistingBudget.name); + }); + + it('backoffice user should be able to edit a budget', (): void => { + budgetEditPage.visitById(dynamicFixtures.preExistingBudget.id_budget, dynamicFixtures.costCenter.id_cost_center); + budgetEditPage.fillName(staticFixtures.updatedBudgetName); + budgetEditPage.submit(); + + budgetEditPage.assertSuccess(); + budgetListPage.assertBudgetInTable(staticFixtures.updatedBudgetName); + }); + } +); diff --git a/cypress/e2e/backoffice/purchasing-control/cost-center.cy.ts b/cypress/e2e/backoffice/purchasing-control/cost-center.cy.ts new file mode 100644 index 000000000..c055328e4 --- /dev/null +++ b/cypress/e2e/backoffice/purchasing-control/cost-center.cy.ts @@ -0,0 +1,61 @@ +import { container } from '@utils'; +import { + BackofficeCostCenterCrudStaticFixtures, + BackofficeCostCenterCrudDynamicFixtures, +} from '@interfaces/backoffice'; +import { CostCenterListPage, CostCenterCreatePage, CostCenterEditPage } from '@pages/backoffice'; +import { UserLoginScenario } from '@scenarios/backoffice'; + +describe( + 'purchasing control cost center crud', + { + tags: ['@backoffice', '@purchasing-control', 'purchasing-control', 'spryker-core-back-office', 'spryker-core'], + }, + (): void => { + if (['b2c', 'b2c-mp'].includes(Cypress.env('repositoryId'))) { + it.skip('skipped because tests run only for suite, b2b, and b2b-mp', () => {}); + return; + } + + const costCenterListPage = container.get(CostCenterListPage); + const costCenterCreatePage = container.get(CostCenterCreatePage); + const costCenterEditPage = container.get(CostCenterEditPage); + const userLoginScenario = container.get(UserLoginScenario); + + let staticFixtures: BackofficeCostCenterCrudStaticFixtures; + let dynamicFixtures: BackofficeCostCenterCrudDynamicFixtures; + + before((): void => { + ({ staticFixtures, dynamicFixtures } = Cypress.env()); + }); + + beforeEach((): void => { + userLoginScenario.execute({ + username: dynamicFixtures.rootUser.username, + password: staticFixtures.defaultPassword, + }); + }); + + it('backoffice user should be able to create a cost center', (): void => { + costCenterListPage.waitForTable(); + costCenterListPage.clickCreateButton(); + + costCenterCreatePage.fillName(staticFixtures.newCostCenterName); + costCenterCreatePage.fillDescription(staticFixtures.newCostCenterDescription); + costCenterCreatePage.selectCompany(dynamicFixtures.company.name); + costCenterCreatePage.selectBusinessUnit(dynamicFixtures.businessUnit.name); + costCenterCreatePage.submit(); + + costCenterCreatePage.assertSuccess(); + }); + + it('backoffice user should be able to edit a cost center', (): void => { + costCenterEditPage.visitById(dynamicFixtures.preExistingCostCenter.id_cost_center); + costCenterEditPage.fillName(staticFixtures.updatedCostCenterName); + costCenterEditPage.submit(); + + costCenterEditPage.assertSuccess(); + costCenterListPage.assertCostCenterInTable(staticFixtures.updatedCostCenterName); + }); + } +); diff --git a/cypress/e2e/yves/purchasing-control/budget-enforcement.cy.ts b/cypress/e2e/yves/purchasing-control/budget-enforcement.cy.ts new file mode 100644 index 000000000..65b8a6039 --- /dev/null +++ b/cypress/e2e/yves/purchasing-control/budget-enforcement.cy.ts @@ -0,0 +1,79 @@ +import { container } from '@utils'; +import { BudgetEnforcementStaticFixtures, BudgetEnforcementDynamicFixtures } from '@interfaces/yves'; +import { + CartPage, + CheckoutAddressPage, + CheckoutPaymentPage, + CheckoutShipmentPage, + CheckoutSummaryPage, + CheckoutSummaryBudgetPage, +} from '@pages/yves'; +import { CustomerLoginScenario } from '@scenarios/yves'; + +describe( + 'purchasing control budget enforcement at checkout', + { tags: ['@yves', '@purchasing-control', 'purchasing-control', 'spryker-core'] }, + (): void => { + if (['b2c', 'b2c-mp'].includes(Cypress.env('repositoryId'))) { + it.skip('skipped because tests run only for suite, b2b, and b2b-mp', () => {}); + return; + } + + const customerLoginScenario = container.get(CustomerLoginScenario); + const cartPage = container.get(CartPage); + const checkoutAddressPage = container.get(CheckoutAddressPage); + const checkoutShipmentPage = container.get(CheckoutShipmentPage); + const checkoutPaymentPage = container.get(CheckoutPaymentPage); + const checkoutSummaryPage = container.get(CheckoutSummaryPage); + const checkoutSummaryBudgetPage = container.get(CheckoutSummaryBudgetPage); + + let staticFixtures: BudgetEnforcementStaticFixtures; + let dynamicFixtures: BudgetEnforcementDynamicFixtures; + + before((): void => { + ({ staticFixtures, dynamicFixtures } = Cypress.env()); + }); + + const loginAsCompanyBuyer = (email: string): void => { + customerLoginScenario.execute({ email, password: staticFixtures.defaultPassword, withoutSession: true }); + }; + + const proceedThroughCheckoutToSummary = (email: string): void => { + loginAsCompanyBuyer(email); + cartPage.visit(); + cartPage.startCheckout(); + checkoutAddressPage.fillShippingAddress(); + checkoutShipmentPage.setStandardShippingMethod(); + checkoutPaymentPage.setDummyPaymentMethod(); + }; + + it('buyer should be able to place order when grand total is within budget', (): void => { + proceedThroughCheckoutToSummary(dynamicFixtures.buyerForWithin.email); + checkoutSummaryPage.placeOrder(); + + cy.url().should('include', '/checkout/success'); + }); + + it('buyer should be blocked from placing order when block budget is exceeded', (): void => { + proceedThroughCheckoutToSummary(dynamicFixtures.buyerForBlock.email); + + checkoutSummaryBudgetPage.assertEnforcementError(); + cy.url().should('include', '/checkout/summary'); + }); + + it('buyer should see warning but still place order when warn budget is exceeded', (): void => { + proceedThroughCheckoutToSummary(dynamicFixtures.buyerForWarn.email); + checkoutSummaryPage.placeOrder(); + + cy.url().should('include', '/checkout/success'); + checkoutSummaryBudgetPage.assertWarnFlashMessage(); + }); + + it('buyer should be blocked from placing order when require_approval budget is exceeded without approval', (): void => { + proceedThroughCheckoutToSummary(dynamicFixtures.buyerForRequireApproval.email); + + checkoutSummaryBudgetPage.assertEnforcementError(); + cy.url().should('include', '/checkout/summary'); + }); + } +); diff --git a/cypress/e2e/yves/purchasing-control/budget.cy.ts b/cypress/e2e/yves/purchasing-control/budget.cy.ts new file mode 100644 index 000000000..0bcfefea5 --- /dev/null +++ b/cypress/e2e/yves/purchasing-control/budget.cy.ts @@ -0,0 +1,86 @@ +import { container } from '@utils'; +import { YvesBudgetCrudStaticFixtures, YvesBudgetCrudDynamicFixtures } from '@interfaces/yves'; +import { YvesBudgetListPage, YvesBudgetCreatePage, YvesBudgetUpdatePage } from '@pages/yves'; +import { CustomerLoginScenario } from '@scenarios/yves'; + +function formatDate(date: Date): string { + return date.toISOString().split('T')[0]; +} + +function getBudgetStartDate(): string { + const date = new Date(); + date.setMonth(date.getMonth() + 1); + date.setDate(1); + + return formatDate(date); +} + +function getBudgetEndDate(): string { + const date = new Date(); + date.setMonth(date.getMonth() + 4); + date.setDate(0); + + return formatDate(date); +} + +describe( + 'purchasing control budget crud', + { + tags: ['@yves', '@purchasing-control', 'purchasing-control', 'spryker-core'], + }, + (): void => { + if (['b2c', 'b2c-mp'].includes(Cypress.env('repositoryId'))) { + it.skip('skipped because tests run only for suite, b2b, and b2b-mp', () => {}); + return; + } + + const customerLoginScenario = container.get(CustomerLoginScenario); + const budgetListPage = container.get(YvesBudgetListPage); + const budgetCreatePage = container.get(YvesBudgetCreatePage); + const budgetUpdatePage = container.get(YvesBudgetUpdatePage); + + let staticFixtures: YvesBudgetCrudStaticFixtures; + let dynamicFixtures: YvesBudgetCrudDynamicFixtures; + + before((): void => { + ({ staticFixtures, dynamicFixtures } = Cypress.env()); + }); + + beforeEach((): void => { + customerLoginScenario.execute({ + email: dynamicFixtures.authorizedCustomer.email, + password: staticFixtures.defaultPassword, + }); + }); + + it('authorized company user should see budget list for a cost center', (): void => { + budgetListPage.visitByCostCenterUuid(dynamicFixtures.costCenter.uuid); + + budgetListPage.assertBudgetInTable(dynamicFixtures.preExistingBudget.name); + }); + + it('authorized company user should be able to create a budget', (): void => { + budgetCreatePage.visitByCostCenterUuid(dynamicFixtures.costCenter.uuid); + + budgetCreatePage.fillName(staticFixtures.newBudgetName); + budgetCreatePage.fillAmount(staticFixtures.budgetAmount); + budgetCreatePage.selectCurrency(staticFixtures.budgetCurrency); + budgetCreatePage.selectEnforcementRule(staticFixtures.budgetEnforcementRule); + budgetCreatePage.fillStartDate(getBudgetStartDate()); + budgetCreatePage.fillEndDate(getBudgetEndDate()); + budgetCreatePage.submit(); + + budgetCreatePage.assertSuccess(); + }); + + it('authorized company user should be able to update a budget', (): void => { + budgetUpdatePage.visitByUuid(dynamicFixtures.preExistingBudget.uuid, dynamicFixtures.costCenter.uuid); + budgetUpdatePage.fillName(staticFixtures.updatedBudgetName); + budgetUpdatePage.submit(); + + budgetUpdatePage.assertSuccess(); + budgetListPage.visitByCostCenterUuid(dynamicFixtures.costCenter.uuid); + budgetListPage.assertBudgetInTable(staticFixtures.updatedBudgetName); + }); + } +); diff --git a/cypress/e2e/yves/purchasing-control/cost-center.cy.ts b/cypress/e2e/yves/purchasing-control/cost-center.cy.ts new file mode 100644 index 000000000..221e502bf --- /dev/null +++ b/cypress/e2e/yves/purchasing-control/cost-center.cy.ts @@ -0,0 +1,95 @@ +import { container } from '@utils'; +import { YvesCostCenterCrudStaticFixtures, YvesCostCenterCrudDynamicFixtures } from '@interfaces/yves'; +import { YvesCostCenterListPage, YvesCostCenterCreatePage, YvesCostCenterUpdatePage } from '@pages/yves'; +import { CustomerLoginScenario } from '@scenarios/yves'; + +describe( + 'purchasing control cost center crud', + { + tags: ['@yves', '@purchasing-control', 'purchasing-control', 'spryker-core'], + }, + (): void => { + if (['b2c', 'b2c-mp'].includes(Cypress.env('repositoryId'))) { + it.skip('skipped because tests run only for suite, b2b, and b2b-mp', () => {}); + return; + } + + const customerLoginScenario = container.get(CustomerLoginScenario); + const costCenterListPage = container.get(YvesCostCenterListPage); + const costCenterCreatePage = container.get(YvesCostCenterCreatePage); + const costCenterUpdatePage = container.get(YvesCostCenterUpdatePage); + + let staticFixtures: YvesCostCenterCrudStaticFixtures; + let dynamicFixtures: YvesCostCenterCrudDynamicFixtures; + + before((): void => { + ({ staticFixtures, dynamicFixtures } = Cypress.env()); + }); + + beforeEach((): void => { + customerLoginScenario.execute({ + email: dynamicFixtures.authorizedCustomer.email, + password: staticFixtures.defaultPassword, + }); + }); + + it('authorized company user should see cost center list', (): void => { + costCenterListPage.visit(); + + costCenterListPage.assertCostCenterInTable(dynamicFixtures.preExistingCostCenter.name); + }); + + it('authorized company user should be able to create a cost center', (): void => { + costCenterCreatePage.visit(); + + costCenterCreatePage.fillName(staticFixtures.newCostCenterName); + costCenterCreatePage.fillDescription(staticFixtures.newCostCenterDescription); + costCenterCreatePage.selectBusinessUnit(dynamicFixtures.businessUnit.id_company_business_unit); + costCenterCreatePage.submit(); + + costCenterCreatePage.assertSuccess(); + }); + + it('authorized company user should be able to edit a cost center', (): void => { + costCenterUpdatePage.visitByUuid(dynamicFixtures.preExistingCostCenter.uuid); + costCenterUpdatePage.fillName(staticFixtures.updatedCostCenterName); + costCenterUpdatePage.submit(); + + costCenterUpdatePage.assertSuccess(); + costCenterListPage.assertCostCenterInTable(staticFixtures.updatedCostCenterName); + }); + + it('authorized company user should be able to deactivate a cost center', (): void => { + costCenterUpdatePage.visitByUuid(dynamicFixtures.preExistingCostCenter.uuid); + costCenterUpdatePage.deactivate(); + costCenterUpdatePage.submit(); + + costCenterUpdatePage.assertSuccess(); + + costCenterUpdatePage.visitByUuid(dynamicFixtures.preExistingCostCenter.uuid); + costCenterUpdatePage.assertIsInactive(); + }); + + it('authorized company user should be able to reactivate a cost center', (): void => { + costCenterUpdatePage.visitByUuid(dynamicFixtures.inactiveCostCenter.uuid); + costCenterUpdatePage.activate(); + costCenterUpdatePage.submit(); + + costCenterUpdatePage.assertSuccess(); + + costCenterUpdatePage.visitByUuid(dynamicFixtures.inactiveCostCenter.uuid); + costCenterUpdatePage.assertIsActive(); + }); + + it('unauthorized company user should receive 403 when accessing cost center list', (): void => { + customerLoginScenario.execute({ + email: dynamicFixtures.unauthorizedCustomer.email, + password: staticFixtures.defaultPassword, + }); + + cy.visit('/company/cost-center', { failOnStatusCode: false }); + + cy.url().should('include', '403'); + }); + } +); diff --git a/cypress/fixtures/suite/backoffice/purchasing-control/dynamic-budget.json b/cypress/fixtures/suite/backoffice/purchasing-control/dynamic-budget.json new file mode 100644 index 000000000..734a2f690 --- /dev/null +++ b/cypress/fixtures/suite/backoffice/purchasing-control/dynamic-budget.json @@ -0,0 +1,33 @@ +{ + "data": { + "type": "dynamic-fixtures", + "attributes": { + "synchronize": false, + "operations": [ + { + "type": "helper", + "name": "haveUser", + "key": "rootUser", + "arguments": [{ "password": "change123" }] + }, + { + "type": "helper", + "name": "addUserToGroup", + "arguments": ["#rootUser.id_user", 1] + }, + { + "type": "helper", + "name": "haveCostCenter", + "key": "costCenter", + "arguments": [] + }, + { + "type": "helper", + "name": "haveBudget", + "key": "preExistingBudget", + "arguments": ["#costCenter.id_cost_center", { "currency_iso_code": "EUR" }] + } + ] + } + } +} diff --git a/cypress/fixtures/suite/backoffice/purchasing-control/dynamic-cost-center.json b/cypress/fixtures/suite/backoffice/purchasing-control/dynamic-cost-center.json new file mode 100644 index 000000000..164569d99 --- /dev/null +++ b/cypress/fixtures/suite/backoffice/purchasing-control/dynamic-cost-center.json @@ -0,0 +1,39 @@ +{ + "data": { + "type": "dynamic-fixtures", + "attributes": { + "synchronize": false, + "operations": [ + { + "type": "helper", + "name": "haveUser", + "key": "rootUser", + "arguments": [{ "password": "change123" }] + }, + { + "type": "helper", + "name": "addUserToGroup", + "arguments": ["#rootUser.id_user", 1] + }, + { + "type": "helper", + "name": "haveCompany", + "key": "company", + "arguments": [{ "status": "approved", "is_active": true }] + }, + { + "type": "helper", + "name": "haveCompanyBusinessUnit", + "key": "businessUnit", + "arguments": [{ "fk_company": "#company.id_company" }] + }, + { + "type": "helper", + "name": "haveCostCenter", + "key": "preExistingCostCenter", + "arguments": [{ "companyBusinessUnit": "#businessUnit" }] + } + ] + } + } +} diff --git a/cypress/fixtures/suite/backoffice/purchasing-control/static-budget.json b/cypress/fixtures/suite/backoffice/purchasing-control/static-budget.json new file mode 100644 index 000000000..3e2109282 --- /dev/null +++ b/cypress/fixtures/suite/backoffice/purchasing-control/static-budget.json @@ -0,0 +1,8 @@ +{ + "defaultPassword": "change123", + "newBudgetName": "Q1 Budget", + "budgetAmount": "100000", + "budgetCurrency": "EUR", + "budgetEnforcementRule": "block", + "updatedBudgetName": "Updated Budget Name" +} diff --git a/cypress/fixtures/suite/backoffice/purchasing-control/static-cost-center.json b/cypress/fixtures/suite/backoffice/purchasing-control/static-cost-center.json new file mode 100644 index 000000000..0f30cd24d --- /dev/null +++ b/cypress/fixtures/suite/backoffice/purchasing-control/static-cost-center.json @@ -0,0 +1,6 @@ +{ + "defaultPassword": "change123", + "newCostCenterName": "Test Cost Center", + "newCostCenterDescription": "Test description", + "updatedCostCenterName": "Updated Cost Center Name" +} diff --git a/cypress/fixtures/suite/yves/purchasing-control/dynamic-budget-enforcement.json b/cypress/fixtures/suite/yves/purchasing-control/dynamic-budget-enforcement.json new file mode 100644 index 000000000..75006b3be --- /dev/null +++ b/cypress/fixtures/suite/yves/purchasing-control/dynamic-budget-enforcement.json @@ -0,0 +1,389 @@ +{ + "data": { + "type": "dynamic-fixtures", + "attributes": { + "synchronize": true, + "operations": [ + { + "type": "helper", + "name": "haveCompany", + "key": "company", + "arguments": [{ "status": "approved", "is_active": true }] + }, + { + "type": "helper", + "name": "haveCompanyBusinessUnit", + "key": "businessUnit", + "arguments": [{ "fk_company": "#company.id_company" }] + }, + { + "type": "helper", + "name": "havePermissionByKey", + "key": "manageCostCentersPermission", + "arguments": ["ManageCostCentersPermissionPlugin"] + }, + { + "type": "helper", + "name": "havePermissionByKey", + "key": "placeOrderPermission", + "arguments": ["PlaceOrderPermissionPlugin"] + }, + { + "type": "helper", + "name": "havePermissionByKey", + "key": "requestQuoteApprovalPermission", + "arguments": ["RequestQuoteApprovalPermissionPlugin"] + }, + { + "type": "helper", + "name": "haveCompanyRoleWithPermissions", + "key": "buyerRole", + "arguments": [ + { "fk_company": "#company.id_company" }, + ["#manageCostCentersPermission", "#placeOrderPermission", "#requestQuoteApprovalPermission"] + ] + }, + { + "type": "helper", + "name": "havePermissionByKey", + "key": "approveQuotePermission", + "arguments": ["ApproveQuotePermissionPlugin"] + }, + { + "type": "helper", + "name": "haveCompanyRoleWithPermissions", + "key": "approverRole", + "arguments": [{ "fk_company": "#company.id_company" }, ["#approveQuotePermission"]] + }, + { + "type": "helper", + "name": "haveCostCenter", + "key": "costCenter", + "arguments": [{ "companyBusinessUnit": "#businessUnit", "is_active": true }] + }, + { + "type": "helper", + "name": "haveBudget", + "key": "blockBudget", + "arguments": [ + "#costCenter.id_cost_center", + { "enforcement_rule": "block", "amount": 100, "currency_iso_code": "EUR", "is_active": true } + ] + }, + { + "type": "helper", + "name": "haveBudget", + "key": "warnBudget", + "arguments": [ + "#costCenter.id_cost_center", + { "enforcement_rule": "warn", "amount": 100, "currency_iso_code": "EUR", "is_active": true } + ] + }, + { + "type": "helper", + "name": "haveBudget", + "key": "requireApprovalBudget", + "arguments": [ + "#costCenter.id_cost_center", + { "enforcement_rule": "require_approval", "amount": 100, "currency_iso_code": "EUR", "is_active": true } + ] + }, + { + "type": "helper", + "name": "haveBudget", + "key": "withinBudget", + "arguments": [ + "#costCenter.id_cost_center", + { "enforcement_rule": "block", "amount": 9999900, "currency_iso_code": "EUR", "is_active": true } + ] + }, + { + "type": "transfer", + "name": "StoreTransfer", + "key": "store", + "arguments": { "id_store": 1 } + }, + { + "type": "helper", + "name": "haveFullProduct", + "key": "product", + "arguments": [{}, { "idTaxSet": 1 }] + }, + { + "type": "helper", + "name": "havePriceProduct", + "arguments": [ + { + "skuProductAbstract": "#product.abstract_sku", + "skuProduct": "#product.sku", + "moneyValue": { "netAmount": 30000, "grossAmount": 30000 } + } + ] + }, + { + "type": "helper", + "name": "haveProductInStockForStore", + "arguments": ["#store", { "sku": "#product.sku", "isNeverOutOfStock": "1" }] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "buyerForWithin", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "buyerForWithinRoleCollection", + "arguments": { "roles": ["#buyerRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "buyerForWithinCompanyUser", + "arguments": [ + { + "customer": "#buyerForWithin", + "fk_company": "#company.id_company", + "company_role_collection": ["#buyerForWithinRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#buyerForWithinCompanyUser", ["#buyerRole"]] + }, + { + "type": "helper", + "name": "havePersistentQuote", + "key": "withinBudgetQuote", + "arguments": [ + { + "customer": "#buyerForWithin", + "idCostCenter": "#costCenter.id_cost_center", + "idBudget": "#withinBudget.id_budget", + "items": [ + { "sku": "#product.sku", "abstractSku": "#product.abstract_sku", "quantity": 1, "unitPrice": 30000 } + ] + } + ] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "buyerForBlock", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "buyerForBlockRoleCollection", + "arguments": { "roles": ["#buyerRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "buyerForBlockCompanyUser", + "arguments": [ + { + "customer": "#buyerForBlock", + "fk_company": "#company.id_company", + "company_role_collection": ["#buyerForBlockRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#buyerForBlockCompanyUser", ["#buyerRole"]] + }, + { + "type": "helper", + "name": "havePersistentQuote", + "key": "blockExceededQuote", + "arguments": [ + { + "customer": "#buyerForBlock", + "idCostCenter": "#costCenter.id_cost_center", + "idBudget": "#blockBudget.id_budget", + "items": [ + { "sku": "#product.sku", "abstractSku": "#product.abstract_sku", "quantity": 1, "unitPrice": 30000 } + ] + } + ] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "buyerForWarn", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "buyerForWarnRoleCollection", + "arguments": { "roles": ["#buyerRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "buyerForWarnCompanyUser", + "arguments": [ + { + "customer": "#buyerForWarn", + "fk_company": "#company.id_company", + "company_role_collection": ["#buyerForWarnRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#buyerForWarnCompanyUser", ["#buyerRole"]] + }, + { + "type": "helper", + "name": "havePersistentQuote", + "key": "warnExceededQuote", + "arguments": [ + { + "customer": "#buyerForWarn", + "idCostCenter": "#costCenter.id_cost_center", + "idBudget": "#warnBudget.id_budget", + "items": [ + { "sku": "#product.sku", "abstractSku": "#product.abstract_sku", "quantity": 1, "unitPrice": 30000 } + ] + } + ] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "buyerForRequireApproval", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "buyerForRequireApprovalRoleCollection", + "arguments": { "roles": ["#buyerRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "buyerForRequireApprovalCompanyUser", + "arguments": [ + { + "customer": "#buyerForRequireApproval", + "fk_company": "#company.id_company", + "company_role_collection": ["#buyerForRequireApprovalRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#buyerForRequireApprovalCompanyUser", ["#buyerRole"]] + }, + { + "type": "helper", + "name": "havePersistentQuote", + "key": "requireApprovalQuote", + "arguments": [ + { + "customer": "#buyerForRequireApproval", + "idCostCenter": "#costCenter.id_cost_center", + "idBudget": "#requireApprovalBudget.id_budget", + "items": [ + { "sku": "#product.sku", "abstractSku": "#product.abstract_sku", "quantity": 1, "unitPrice": 30000 } + ] + } + ] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "buyerForApproved", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "buyerForApprovedRoleCollection", + "arguments": { "roles": ["#buyerRole"] } + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "approverCustomer", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "approverRoleCollection", + "arguments": { "roles": ["#approverRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "approverCompanyUser", + "arguments": [ + { + "customer": "#approverCustomer", + "fk_company": "#company.id_company", + "company_role_collection": ["#approverRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#approverCompanyUser", ["#approverRole"]] + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "buyerForApprovedCompanyUser", + "arguments": [ + { + "customer": "#buyerForApproved", + "fk_company": "#company.id_company", + "company_role_collection": ["#buyerForApprovedRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#buyerForApprovedCompanyUser", ["#buyerRole"]] + }, + { + "type": "helper", + "name": "havePersistentQuote", + "key": "approvedQuote", + "arguments": [ + { + "customer": "#buyerForApproved", + "idCostCenter": "#costCenter.id_cost_center", + "idBudget": "#requireApprovalBudget.id_budget", + "quoteApprovals": [ + { "status": "approved", "approverCompanyUserId": "#approverCompanyUser.id_company_user" } + ], + "items": [ + { "sku": "#product.sku", "abstractSku": "#product.abstract_sku", "quantity": 1, "unitPrice": 30000 } + ] + } + ] + } + ] + } + } +} diff --git a/cypress/fixtures/suite/yves/purchasing-control/dynamic-budget.json b/cypress/fixtures/suite/yves/purchasing-control/dynamic-budget.json new file mode 100644 index 000000000..a6017d063 --- /dev/null +++ b/cypress/fixtures/suite/yves/purchasing-control/dynamic-budget.json @@ -0,0 +1,76 @@ +{ + "data": { + "type": "dynamic-fixtures", + "attributes": { + "synchronize": false, + "operations": [ + { + "type": "helper", + "name": "haveCompany", + "key": "company", + "arguments": [{ "status": "approved", "is_active": true }] + }, + { + "type": "helper", + "name": "haveCompanyBusinessUnit", + "key": "businessUnit", + "arguments": [{ "fk_company": "#company.id_company" }] + }, + { + "type": "helper", + "name": "havePermissionByKey", + "key": "manageCostCentersPermission", + "arguments": ["ManageCostCentersPermissionPlugin"] + }, + { + "type": "helper", + "name": "haveCompanyRoleWithPermissions", + "key": "authorizedRole", + "arguments": [{ "fk_company": "#company.id_company" }, ["#manageCostCentersPermission"]] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "authorizedCustomer", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "authorizedRoleCollection", + "arguments": { "roles": ["#authorizedRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "authorizedCompanyUser", + "arguments": [ + { + "customer": "#authorizedCustomer", + "fk_company": "#company.id_company", + "company_role_collection": ["#authorizedRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#authorizedCompanyUser", ["#authorizedRole"]] + }, + { + "type": "helper", + "name": "haveCostCenter", + "key": "costCenter", + "arguments": [{ "companyBusinessUnit": "#businessUnit", "is_active": true }] + }, + { + "type": "helper", + "name": "haveBudget", + "key": "preExistingBudget", + "arguments": ["#costCenter.id_cost_center", { "currency_iso_code": "EUR" }] + } + ] + } + } +} diff --git a/cypress/fixtures/suite/yves/purchasing-control/dynamic-cost-center.json b/cypress/fixtures/suite/yves/purchasing-control/dynamic-cost-center.json new file mode 100644 index 000000000..45f96e3cc --- /dev/null +++ b/cypress/fixtures/suite/yves/purchasing-control/dynamic-cost-center.json @@ -0,0 +1,112 @@ +{ + "data": { + "type": "dynamic-fixtures", + "attributes": { + "synchronize": false, + "operations": [ + { + "type": "helper", + "name": "haveCompany", + "key": "company", + "arguments": [{ "status": "approved", "is_active": true }] + }, + { + "type": "helper", + "name": "haveCompanyBusinessUnit", + "key": "businessUnit", + "arguments": [{ "fk_company": "#company.id_company" }] + }, + { + "type": "helper", + "name": "havePermissionByKey", + "key": "manageCostCentersPermission", + "arguments": ["ManageCostCentersPermissionPlugin"] + }, + { + "type": "helper", + "name": "haveCompanyRoleWithPermissions", + "key": "authorizedRole", + "arguments": [{ "fk_company": "#company.id_company" }, ["#manageCostCentersPermission"]] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "authorizedCustomer", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "authorizedRoleCollection", + "arguments": { "roles": ["#authorizedRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "authorizedCompanyUser", + "arguments": [ + { + "customer": "#authorizedCustomer", + "fk_company": "#company.id_company", + "company_role_collection": ["#authorizedRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#authorizedCompanyUser", ["#authorizedRole"]] + }, + { + "type": "helper", + "name": "haveCompanyRoleWithPermissions", + "key": "unauthorizedRole", + "arguments": [{ "fk_company": "#company.id_company" }, []] + }, + { + "type": "helper", + "name": "haveConfirmedCustomer", + "key": "unauthorizedCustomer", + "arguments": [{ "registered": "2025-01-01", "password": "change123", "locale_name": "en_US" }] + }, + { + "type": "builder", + "name": "CompanyRoleCollectionBuilder", + "key": "unauthorizedRoleCollection", + "arguments": { "roles": ["#unauthorizedRole"] } + }, + { + "type": "helper", + "name": "haveCompanyUser", + "key": "unauthorizedCompanyUser", + "arguments": [ + { + "customer": "#unauthorizedCustomer", + "fk_company": "#company.id_company", + "company_role_collection": ["#unauthorizedRoleCollection"], + "fk_company_business_unit": "#businessUnit.id_company_business_unit" + } + ] + }, + { + "type": "helper", + "name": "assignCompanyRoles", + "arguments": ["#unauthorizedCompanyUser", ["#unauthorizedRole"]] + }, + { + "type": "helper", + "name": "haveCostCenter", + "key": "preExistingCostCenter", + "arguments": [{ "companyBusinessUnit": "#businessUnit", "is_active": true }] + }, + { + "type": "helper", + "name": "haveCostCenter", + "key": "inactiveCostCenter", + "arguments": [{ "companyBusinessUnit": "#businessUnit", "is_active": false }] + } + ] + } + } +} diff --git a/cypress/fixtures/suite/yves/purchasing-control/static-budget-enforcement.json b/cypress/fixtures/suite/yves/purchasing-control/static-budget-enforcement.json new file mode 100644 index 000000000..ba4339e8a --- /dev/null +++ b/cypress/fixtures/suite/yves/purchasing-control/static-budget-enforcement.json @@ -0,0 +1,3 @@ +{ + "defaultPassword": "change123" +} diff --git a/cypress/fixtures/suite/yves/purchasing-control/static-budget.json b/cypress/fixtures/suite/yves/purchasing-control/static-budget.json new file mode 100644 index 000000000..43bb9ec05 --- /dev/null +++ b/cypress/fixtures/suite/yves/purchasing-control/static-budget.json @@ -0,0 +1,8 @@ +{ + "defaultPassword": "change123", + "newBudgetName": "Q2 Budget", + "budgetAmount": "50000", + "budgetCurrency": "EUR", + "budgetEnforcementRule": "block", + "updatedBudgetName": "Updated Budget Name" +} diff --git a/cypress/fixtures/suite/yves/purchasing-control/static-cost-center.json b/cypress/fixtures/suite/yves/purchasing-control/static-cost-center.json new file mode 100644 index 000000000..2c936f967 --- /dev/null +++ b/cypress/fixtures/suite/yves/purchasing-control/static-cost-center.json @@ -0,0 +1,6 @@ +{ + "defaultPassword": "change123", + "newCostCenterName": "New Cost Center", + "newCostCenterDescription": "New cost center description", + "updatedCostCenterName": "Updated Cost Center Name" +} diff --git a/cypress/support/pages/backoffice/index.ts b/cypress/support/pages/backoffice/index.ts index d41d1645c..4cbae6dc2 100644 --- a/cypress/support/pages/backoffice/index.ts +++ b/cypress/support/pages/backoffice/index.ts @@ -71,3 +71,9 @@ export * from './product-attribute-visibility/list/product-attribute-visibility- export * from './product-attribute-visibility/create/product-attribute-visibility-create-page'; export * from './product-attribute-visibility/edit/product-attribute-visibility-edit-page'; export * from './configuration/configuration-page'; +export * from './purchasing-control/cost-center/list/cost-center-list-page'; +export * from './purchasing-control/cost-center/create/cost-center-create-page'; +export * from './purchasing-control/cost-center/edit/cost-center-edit-page'; +export * from './purchasing-control/budget/list/budget-list-page'; +export * from './purchasing-control/budget/create/budget-create-page'; +export * from './purchasing-control/budget/edit/budget-edit-page'; diff --git a/cypress/support/pages/backoffice/purchasing-control/budget/create/budget-create-page.ts b/cypress/support/pages/backoffice/purchasing-control/budget/create/budget-create-page.ts new file mode 100644 index 000000000..d1594ce18 --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/budget/create/budget-create-page.ts @@ -0,0 +1,48 @@ +import { autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { BackofficePage } from '@pages/backoffice'; +import { BackofficeBudgetCreateRepository } from './budget-create-repository'; + +@injectable() +@autoWired +export class BackofficeBudgetCreatePage extends BackofficePage { + @inject(BackofficeBudgetCreateRepository) private repository: BackofficeBudgetCreateRepository; + + protected PAGE_URL = '/purchasing-control/budget/create'; + + visitByCostCenter = (idCostCenter: number): void => { + cy.visitBackoffice(`/purchasing-control/budget/create?id-cost-center=${idCostCenter}`); + }; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillAmount = (amount: string): void => { + this.repository.getAmountInput().clear().type(amount); + }; + + selectCurrency = (currency: string): void => { + this.repository.getCurrencySelect().select(currency, { force: true }); + }; + + selectEnforcementRule = (rule: string): void => { + this.repository.getEnforcementRuleSelect().select(rule, { force: true }); + }; + + fillStartDate = (date: string): void => { + this.repository.getStartsAtInput().type(date); + }; + + fillEndDate = (date: string): void => { + this.repository.getEndsAtInput().type(date); + }; + + submit = (): void => { + this.repository.getSaveButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessMessage().should('be.visible'); + }; +} diff --git a/cypress/support/pages/backoffice/purchasing-control/budget/create/budget-create-repository.ts b/cypress/support/pages/backoffice/purchasing-control/budget/create/budget-create-repository.ts new file mode 100644 index 000000000..5c0b9a395 --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/budget/create/budget-create-repository.ts @@ -0,0 +1,16 @@ +import { autoWired } from '@utils'; +import { injectable } from 'inversify'; + +@injectable() +@autoWired +export class BackofficeBudgetCreateRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="budget-name"]'); + getAmountInput = (): Cypress.Chainable => cy.get('[data-qa="budget-amount"]'); + getCurrencySelect = (): Cypress.Chainable => cy.get('[data-qa="budget-currency"]'); + getEnforcementRuleSelect = (): Cypress.Chainable => cy.get('[data-qa="budget-enforcement-rule"]'); + getStartsAtInput = (): Cypress.Chainable => cy.get('[data-qa="budget-starts-at"]'); + getEndsAtInput = (): Cypress.Chainable => cy.get('[data-qa="budget-ends-at"]'); + getIsActiveCheckbox = (): Cypress.Chainable => cy.get('[data-qa="budget-is-active"]'); + getSaveButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + getSuccessMessage = (): Cypress.Chainable => cy.get('.alert-success'); +} diff --git a/cypress/support/pages/backoffice/purchasing-control/budget/edit/budget-edit-page.ts b/cypress/support/pages/backoffice/purchasing-control/budget/edit/budget-edit-page.ts new file mode 100644 index 000000000..1503f8757 --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/budget/edit/budget-edit-page.ts @@ -0,0 +1,36 @@ +import { autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { BackofficePage } from '@pages/backoffice'; +import { BackofficeBudgetEditRepository } from './budget-edit-repository'; + +@injectable() +@autoWired +export class BackofficeBudgetEditPage extends BackofficePage { + @inject(BackofficeBudgetEditRepository) private repository: BackofficeBudgetEditRepository; + + protected PAGE_URL = '/purchasing-control/budget/edit'; + + visitById = (idBudget: number, idCostCenter: number): void => { + cy.visitBackoffice(`/purchasing-control/budget/edit?id-cost-center=${idCostCenter}&id-budget=${idBudget}`); + }; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillAmount = (amount: string): void => { + this.repository.getAmountInput().clear().type(amount); + }; + + submit = (): void => { + this.repository.getSaveButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessMessage().should('be.visible'); + }; + + getNameValue = (): Cypress.Chainable => { + return this.repository.getNameInput().invoke('val') as Cypress.Chainable; + }; +} diff --git a/cypress/support/pages/backoffice/purchasing-control/budget/edit/budget-edit-repository.ts b/cypress/support/pages/backoffice/purchasing-control/budget/edit/budget-edit-repository.ts new file mode 100644 index 000000000..d9893cfec --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/budget/edit/budget-edit-repository.ts @@ -0,0 +1,16 @@ +import { autoWired } from '@utils'; +import { injectable } from 'inversify'; + +@injectable() +@autoWired +export class BackofficeBudgetEditRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="budget-name"]'); + getAmountInput = (): Cypress.Chainable => cy.get('[data-qa="budget-amount"]'); + getCurrencySelect = (): Cypress.Chainable => cy.get('[data-qa="budget-currency"]'); + getEnforcementRuleSelect = (): Cypress.Chainable => cy.get('[data-qa="budget-enforcement-rule"]'); + getStartsAtInput = (): Cypress.Chainable => cy.get('[data-qa="budget-starts-at"]'); + getEndsAtInput = (): Cypress.Chainable => cy.get('[data-qa="budget-ends-at"]'); + getIsActiveCheckbox = (): Cypress.Chainable => cy.get('[data-qa="budget-is-active"]'); + getSaveButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + getSuccessMessage = (): Cypress.Chainable => cy.get('.alert-success'); +} diff --git a/cypress/support/pages/backoffice/purchasing-control/budget/list/budget-list-page.ts b/cypress/support/pages/backoffice/purchasing-control/budget/list/budget-list-page.ts new file mode 100644 index 000000000..132076e7b --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/budget/list/budget-list-page.ts @@ -0,0 +1,30 @@ +import { autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { BackofficePage } from '@pages/backoffice'; +import { BackofficeBudgetListRepository } from './budget-list-repository'; + +@injectable() +@autoWired +export class BackofficeBudgetListPage extends BackofficePage { + @inject(BackofficeBudgetListRepository) private repository: BackofficeBudgetListRepository; + + protected PAGE_URL = '/purchasing-control/budget'; + + visitByCostCenter = (idCostCenter: number): void => { + cy.intercept('GET', '**/purchasing-control/budget/table**').as('budgetTable'); + cy.visitBackoffice(`/purchasing-control/budget?id-cost-center=${idCostCenter}`); + cy.wait('@budgetTable'); + }; + + clickCreateButton = (): void => { + cy.get(this.repository.getCreateButtonSelector()).click(); + }; + + clickEditButton = (idBudget: number, idCostCenter: number): void => { + cy.visitBackoffice(`/purchasing-control/budget/edit?id-cost-center=${idCostCenter}&id-budget=${idBudget}`); + }; + + assertBudgetInTable = (name: string): void => { + cy.get(this.repository.getTableBodySelector()).should('contain', name); + }; +} diff --git a/cypress/support/pages/backoffice/purchasing-control/budget/list/budget-list-repository.ts b/cypress/support/pages/backoffice/purchasing-control/budget/list/budget-list-repository.ts new file mode 100644 index 000000000..622c724ab --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/budget/list/budget-list-repository.ts @@ -0,0 +1,10 @@ +import { autoWired } from '@utils'; +import { injectable } from 'inversify'; + +@injectable() +@autoWired +export class BackofficeBudgetListRepository { + getCreateButtonSelector = (): string => 'a[href*="/purchasing-control/budget/create"]'; + getTableBodySelector = (): string => 'table.gui-table-data tbody'; + getEditLinkSelector = (idBudget: number): string => `a[href*="id-budget=${idBudget}"][href*="/edit"]`; +} diff --git a/cypress/support/pages/backoffice/purchasing-control/cost-center/create/cost-center-create-page.ts b/cypress/support/pages/backoffice/purchasing-control/cost-center/create/cost-center-create-page.ts new file mode 100644 index 000000000..c134e5bab --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/cost-center/create/cost-center-create-page.ts @@ -0,0 +1,44 @@ +import { autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { BackofficePage } from '@pages/backoffice'; +import { CostCenterCreateRepository } from './cost-center-create-repository'; + +@injectable() +@autoWired +export class CostCenterCreatePage extends BackofficePage { + @inject(CostCenterCreateRepository) private repository: CostCenterCreateRepository; + + protected PAGE_URL = '/purchasing-control/cost-center/create'; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillDescription = (description: string): void => { + this.repository.getDescriptionTextarea().clear().type(description); + }; + + selectCompany = (companyName: string): void => { + cy.intercept('GET', '**/company-gui/suggest*').as('companySuggest'); + this.repository.getCompanySelect().siblings('.select2-container').find('.select2-selection').click(); + cy.get('.select2-dropdown .select2-search__field').type(companyName); + cy.wait('@companySuggest'); + cy.contains('.select2-dropdown .select2-results__option', companyName).click(); + }; + + selectBusinessUnit = (businessUnitName: string): void => { + cy.intercept('GET', '**/company-business-unit-gui/suggest*').as('buSearch'); + this.repository.getBusinessUnitSelect().siblings('.select2-container').find('.select2-selection').click(); + cy.get('.select2-search__field:visible').type(businessUnitName); + cy.wait('@buSearch'); + cy.contains('.select2-results__option', businessUnitName).click(); + }; + + submit = (): void => { + this.repository.getSaveButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessMessage().should('be.visible'); + }; +} diff --git a/cypress/support/pages/backoffice/purchasing-control/cost-center/create/cost-center-create-repository.ts b/cypress/support/pages/backoffice/purchasing-control/cost-center/create/cost-center-create-repository.ts new file mode 100644 index 000000000..8e7a29a5e --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/cost-center/create/cost-center-create-repository.ts @@ -0,0 +1,14 @@ +import { autoWired } from '@utils'; +import { injectable } from 'inversify'; + +@injectable() +@autoWired +export class CostCenterCreateRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="cost-center-name"]'); + getDescriptionTextarea = (): Cypress.Chainable => cy.get('[data-qa="cost-center-description"]'); + getCompanySelect = (): Cypress.Chainable => cy.get('[data-qa="cost-center-company"]'); + getBusinessUnitSelect = (): Cypress.Chainable => cy.get('[data-qa="cost-center-business-unit-ids"]'); + getIsActiveCheckbox = (): Cypress.Chainable => cy.get('[data-qa="cost-center-is-active"]'); + getSaveButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + getSuccessMessage = (): Cypress.Chainable => cy.get('.alert-success'); +} diff --git a/cypress/support/pages/backoffice/purchasing-control/cost-center/edit/cost-center-edit-page.ts b/cypress/support/pages/backoffice/purchasing-control/cost-center/edit/cost-center-edit-page.ts new file mode 100644 index 000000000..16712b36a --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/cost-center/edit/cost-center-edit-page.ts @@ -0,0 +1,36 @@ +import { autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { BackofficePage } from '@pages/backoffice'; +import { CostCenterEditRepository } from './cost-center-edit-repository'; + +@injectable() +@autoWired +export class CostCenterEditPage extends BackofficePage { + @inject(CostCenterEditRepository) private repository: CostCenterEditRepository; + + protected PAGE_URL = '/purchasing-control/cost-center/edit'; + + visitById = (idCostCenter: number): void => { + cy.visitBackoffice(`/purchasing-control/cost-center/edit?id-cost-center=${idCostCenter}`); + }; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillDescription = (description: string): void => { + this.repository.getDescriptionTextarea().clear().type(description); + }; + + submit = (): void => { + this.repository.getSaveButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessMessage().should('be.visible'); + }; + + getNameValue = (): Cypress.Chainable => { + return this.repository.getNameInput().invoke('val') as Cypress.Chainable; + }; +} diff --git a/cypress/support/pages/backoffice/purchasing-control/cost-center/edit/cost-center-edit-repository.ts b/cypress/support/pages/backoffice/purchasing-control/cost-center/edit/cost-center-edit-repository.ts new file mode 100644 index 000000000..d02a0c2ff --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/cost-center/edit/cost-center-edit-repository.ts @@ -0,0 +1,14 @@ +import { autoWired } from '@utils'; +import { injectable } from 'inversify'; + +@injectable() +@autoWired +export class CostCenterEditRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="cost-center-name"]'); + getDescriptionTextarea = (): Cypress.Chainable => cy.get('[data-qa="cost-center-description"]'); + getCompanySelect = (): Cypress.Chainable => cy.get('[data-qa="cost-center-company"]'); + getBusinessUnitSelect = (): Cypress.Chainable => cy.get('[data-qa="cost-center-business-unit-ids"]'); + getIsActiveCheckbox = (): Cypress.Chainable => cy.get('[data-qa="cost-center-is-active"]'); + getSaveButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + getSuccessMessage = (): Cypress.Chainable => cy.get('.alert-success'); +} diff --git a/cypress/support/pages/backoffice/purchasing-control/cost-center/list/cost-center-list-page.ts b/cypress/support/pages/backoffice/purchasing-control/cost-center/list/cost-center-list-page.ts new file mode 100644 index 000000000..d567390e6 --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/cost-center/list/cost-center-list-page.ts @@ -0,0 +1,37 @@ +import { autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { BackofficePage } from '@pages/backoffice'; +import { CostCenterListRepository } from './cost-center-list-repository'; + +@injectable() +@autoWired +export class CostCenterListPage extends BackofficePage { + @inject(CostCenterListRepository) private repository: CostCenterListRepository; + + protected PAGE_URL = '/purchasing-control/cost-center'; + + waitForTable = (): void => { + cy.intercept('GET', '**/purchasing-control/cost-center/table**').as('costCenterTable'); + this.visit(); + cy.wait('@costCenterTable'); + }; + + clickCreateButton = (): void => { + cy.get(this.repository.getCreateButtonSelector()).click(); + }; + + clickEditButton = (idCostCenter: number): void => { + cy.visitBackoffice(`/purchasing-control/cost-center/edit?id-cost-center=${idCostCenter}`); + }; + + clickBudgetsButton = (idCostCenter: number): void => { + cy.visitBackoffice(`/purchasing-control/budget?id-cost-center=${idCostCenter}`); + }; + + assertCostCenterInTable = (name: string): void => { + cy.intercept('GET', '**/purchasing-control/cost-center/table**').as('costCenterTableAssert'); + this.visit(); + cy.wait('@costCenterTableAssert'); + cy.get(this.repository.getTableBodySelector()).should('contain', name); + }; +} diff --git a/cypress/support/pages/backoffice/purchasing-control/cost-center/list/cost-center-list-repository.ts b/cypress/support/pages/backoffice/purchasing-control/cost-center/list/cost-center-list-repository.ts new file mode 100644 index 000000000..c50d87d29 --- /dev/null +++ b/cypress/support/pages/backoffice/purchasing-control/cost-center/list/cost-center-list-repository.ts @@ -0,0 +1,12 @@ +import { autoWired } from '@utils'; +import { injectable } from 'inversify'; + +@injectable() +@autoWired +export class CostCenterListRepository { + getCreateButtonSelector = (): string => 'a[href*="/purchasing-control/cost-center/create"]'; + getTableBodySelector = (): string => 'table.gui-table-data tbody'; + getEditLinkSelector = (idCostCenter: number): string => `a[href*="id-cost-center=${idCostCenter}"][href*="/edit"]`; + getBudgetsLinkSelector = (idCostCenter: number): string => + `a[href*="id-cost-center=${idCostCenter}"][href*="/budget"]`; +} diff --git a/cypress/support/pages/yves/index.ts b/cypress/support/pages/yves/index.ts index 60d2b88c3..2e23b883c 100644 --- a/cypress/support/pages/yves/index.ts +++ b/cypress/support/pages/yves/index.ts @@ -42,3 +42,10 @@ export * from './multi-factor-auth/agent/agent-multi-factor-auth-page'; export * from './ssp-dashboard-management/ssp-dashboard-page'; export * from './merchant-registration/merchant-registration-page'; export * from './product-attribute-visibility/product-attribute-visibility-page'; +export * from './purchasing-control/cost-center/list/cost-center-list-page'; +export * from './purchasing-control/cost-center/create/cost-center-create-page'; +export * from './purchasing-control/cost-center/update/cost-center-update-page'; +export * from './purchasing-control/budget/list/budget-list-page'; +export * from './purchasing-control/budget/create/budget-create-page'; +export * from './purchasing-control/budget/update/budget-update-page'; +export * from './purchasing-control/checkout-summary/checkout-summary-budget-page'; diff --git a/cypress/support/pages/yves/purchasing-control/budget/create/budget-create-page.ts b/cypress/support/pages/yves/purchasing-control/budget/create/budget-create-page.ts new file mode 100644 index 000000000..44b4e581b --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/create/budget-create-page.ts @@ -0,0 +1,49 @@ +import { REPOSITORIES, autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { YvesPage } from '@pages/yves'; +import { BudgetCreateRepository } from './budget-create-repository'; + +@injectable() +@autoWired +export class YvesBudgetCreatePage extends YvesPage { + @inject(REPOSITORIES.YvesBudgetCreateRepository) + private repository: BudgetCreateRepository; + + protected PAGE_URL = '/company/cost-center/budget/create'; + + visitByCostCenterUuid = (costCenterUuid: string): void => { + cy.visit(`/company/cost-center/budget/create?costCenterUuid=${costCenterUuid}`); + }; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillAmount = (amount: string): void => { + this.repository.getAmountInput().clear().type(amount); + }; + + selectCurrency = (currency: string): void => { + this.repository.getCurrencySelect().select(currency); + }; + + selectEnforcementRule = (rule: string): void => { + this.repository.getEnforcementRuleSelect().select(rule); + }; + + fillStartDate = (date: string): void => { + this.repository.getStartsAtInput().type(date); + }; + + fillEndDate = (date: string): void => { + this.repository.getEndsAtInput().type(date); + }; + + submit = (): void => { + this.repository.getSubmitButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessFlashMessage().should('be.visible'); + }; +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/create/budget-create-repository.ts b/cypress/support/pages/yves/purchasing-control/budget/create/budget-create-repository.ts new file mode 100644 index 000000000..39805f607 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/create/budget-create-repository.ts @@ -0,0 +1,10 @@ +export interface BudgetCreateRepository { + getNameInput(): Cypress.Chainable; + getAmountInput(): Cypress.Chainable; + getCurrencySelect(): Cypress.Chainable; + getEnforcementRuleSelect(): Cypress.Chainable; + getStartsAtInput(): Cypress.Chainable; + getEndsAtInput(): Cypress.Chainable; + getSubmitButton(): Cypress.Chainable; + getSuccessFlashMessage(): Cypress.Chainable; +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/create/repositories/suite-budget-create-repository.ts b/cypress/support/pages/yves/purchasing-control/budget/create/repositories/suite-budget-create-repository.ts new file mode 100644 index 000000000..53e9549b9 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/create/repositories/suite-budget-create-repository.ts @@ -0,0 +1,21 @@ +import { injectable } from 'inversify'; +import { BudgetCreateRepository } from '../budget-create-repository'; + +@injectable() +export class SuiteBudgetCreateRepository implements BudgetCreateRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="budget-name-input"]'); + + getAmountInput = (): Cypress.Chainable => cy.get('[data-qa="budget-amount-input"]'); + + getCurrencySelect = (): Cypress.Chainable => cy.get('[data-qa="budget-currency-select"]'); + + getEnforcementRuleSelect = (): Cypress.Chainable => cy.get('[data-qa="budget-enforcement-rule-select"]'); + + getStartsAtInput = (): Cypress.Chainable => cy.get('[data-qa="budget-starts-at-input"]'); + + getEndsAtInput = (): Cypress.Chainable => cy.get('[data-qa="budget-ends-at-input"]'); + + getSubmitButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + + getSuccessFlashMessage = (): Cypress.Chainable => cy.get('[data-qa="component notification-area"] flash-message'); +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/list/budget-list-page.ts b/cypress/support/pages/yves/purchasing-control/budget/list/budget-list-page.ts new file mode 100644 index 000000000..b9bc5f812 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/list/budget-list-page.ts @@ -0,0 +1,29 @@ +import { REPOSITORIES, autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { YvesPage } from '@pages/yves'; +import { BudgetListRepository } from './budget-list-repository'; + +@injectable() +@autoWired +export class YvesBudgetListPage extends YvesPage { + @inject(REPOSITORIES.YvesBudgetListRepository) + private repository: BudgetListRepository; + + protected PAGE_URL = '/company/cost-center/budget'; + + visitByCostCenterUuid = (costCenterUuid: string): void => { + cy.visit(`/company/cost-center/budget?costCenterUuid=${costCenterUuid}`); + }; + + clickCreateButton = (): void => { + this.repository.getCreateButton().click(); + }; + + clickEditButton = (budgetUuid: string): void => { + this.repository.getEditButtonByUuid(budgetUuid).click(); + }; + + assertBudgetInTable = (name: string): void => { + this.repository.getTableRows().should('contain', name); + }; +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/list/budget-list-repository.ts b/cypress/support/pages/yves/purchasing-control/budget/list/budget-list-repository.ts new file mode 100644 index 000000000..e48177284 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/list/budget-list-repository.ts @@ -0,0 +1,5 @@ +export interface BudgetListRepository { + getCreateButton(): Cypress.Chainable; + getTableRows(): Cypress.Chainable; + getEditButtonByUuid(uuid: string): Cypress.Chainable; +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/list/repositories/suite-budget-list-repository.ts b/cypress/support/pages/yves/purchasing-control/budget/list/repositories/suite-budget-list-repository.ts new file mode 100644 index 000000000..cca6ce3b2 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/list/repositories/suite-budget-list-repository.ts @@ -0,0 +1,12 @@ +import { injectable } from 'inversify'; +import { BudgetListRepository } from '../budget-list-repository'; + +@injectable() +export class SuiteBudgetListRepository implements BudgetListRepository { + getCreateButton = (): Cypress.Chainable => cy.get('a[href*="budget/create"]'); + + getTableRows = (): Cypress.Chainable => cy.get('[data-qa="component data-table"] tbody tr'); + + getEditButtonByUuid = (uuid: string): Cypress.Chainable => + cy.get(`[data-qa="cell-actions"] a[href*="${uuid}"]`).first(); +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/update/budget-update-page.ts b/cypress/support/pages/yves/purchasing-control/budget/update/budget-update-page.ts new file mode 100644 index 000000000..83378a6a9 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/update/budget-update-page.ts @@ -0,0 +1,37 @@ +import { REPOSITORIES, autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { YvesPage } from '@pages/yves'; +import { BudgetUpdateRepository } from './budget-update-repository'; + +@injectable() +@autoWired +export class YvesBudgetUpdatePage extends YvesPage { + @inject(REPOSITORIES.YvesBudgetUpdateRepository) + private repository: BudgetUpdateRepository; + + protected PAGE_URL = '/company/cost-center/budget/update'; + + visitByUuid = (budgetUuid: string, costCenterUuid: string): void => { + cy.visit(`/company/cost-center/budget/update?budgetUuid=${budgetUuid}&costCenterUuid=${costCenterUuid}`); + }; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillAmount = (amount: string): void => { + this.repository.getAmountInput().clear().type(amount); + }; + + submit = (): void => { + this.repository.getSubmitButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessFlashMessage().should('be.visible'); + }; + + getNameValue = (): Cypress.Chainable => { + return this.repository.getNameInput().invoke('val') as Cypress.Chainable; + }; +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/update/budget-update-repository.ts b/cypress/support/pages/yves/purchasing-control/budget/update/budget-update-repository.ts new file mode 100644 index 000000000..aae6670fd --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/update/budget-update-repository.ts @@ -0,0 +1,6 @@ +export interface BudgetUpdateRepository { + getNameInput(): Cypress.Chainable; + getAmountInput(): Cypress.Chainable; + getSubmitButton(): Cypress.Chainable; + getSuccessFlashMessage(): Cypress.Chainable; +} diff --git a/cypress/support/pages/yves/purchasing-control/budget/update/repositories/suite-budget-update-repository.ts b/cypress/support/pages/yves/purchasing-control/budget/update/repositories/suite-budget-update-repository.ts new file mode 100644 index 000000000..d854fd9d8 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/budget/update/repositories/suite-budget-update-repository.ts @@ -0,0 +1,13 @@ +import { injectable } from 'inversify'; +import { BudgetUpdateRepository } from '../budget-update-repository'; + +@injectable() +export class SuiteBudgetUpdateRepository implements BudgetUpdateRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="budget-name-input"]'); + + getAmountInput = (): Cypress.Chainable => cy.get('[data-qa="budget-amount-input"]'); + + getSubmitButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + + getSuccessFlashMessage = (): Cypress.Chainable => cy.get('[data-qa="component notification-area"] flash-message'); +} diff --git a/cypress/support/pages/yves/purchasing-control/checkout-summary/checkout-summary-budget-page.ts b/cypress/support/pages/yves/purchasing-control/checkout-summary/checkout-summary-budget-page.ts new file mode 100644 index 000000000..fd0ac4a96 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/checkout-summary/checkout-summary-budget-page.ts @@ -0,0 +1,45 @@ +import { REPOSITORIES, autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { YvesPage } from '@pages/yves'; +import { CheckoutSummaryBudgetRepository } from './checkout-summary-budget-repository'; + +@injectable() +@autoWired +export class CheckoutSummaryBudgetPage extends YvesPage { + @inject(REPOSITORIES.YvesCheckoutSummaryBudgetRepository) + private repository: CheckoutSummaryBudgetRepository; + + protected PAGE_URL = '/checkout/summary'; + + assertEnforcementError = (): void => { + this.repository.getCheckoutErrorMessage().should('be.visible'); + }; + + assertWarnFlashMessage = (): void => { + this.repository.getWarnFlashMessage().should('be.visible'); + }; + + assertLockedCostCenterValue = (): void => { + this.repository.getCostCenterSelectorValue().should('be.visible'); + }; + + assertBudgetRemainingVisible = (): void => { + this.repository.getBudgetRemainingAmount().should('be.visible'); + }; + + assertApproveButtonVisible = (): void => { + this.repository.getApproveButton().should('be.visible'); + }; + + assertDeclineButtonVisible = (): void => { + this.repository.getDeclineButton().should('be.visible'); + }; + + approveQuote = (): void => { + this.repository.getApproveButton().click(); + }; + + declineQuote = (): void => { + this.repository.getDeclineButton().click(); + }; +} diff --git a/cypress/support/pages/yves/purchasing-control/checkout-summary/checkout-summary-budget-repository.ts b/cypress/support/pages/yves/purchasing-control/checkout-summary/checkout-summary-budget-repository.ts new file mode 100644 index 000000000..310a5a4f6 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/checkout-summary/checkout-summary-budget-repository.ts @@ -0,0 +1,8 @@ +export interface CheckoutSummaryBudgetRepository { + getCheckoutErrorMessage(): Cypress.Chainable; + getWarnFlashMessage(): Cypress.Chainable; + getCostCenterSelectorValue(): Cypress.Chainable; + getBudgetRemainingAmount(): Cypress.Chainable; + getApproveButton(): Cypress.Chainable; + getDeclineButton(): Cypress.Chainable; +} diff --git a/cypress/support/pages/yves/purchasing-control/checkout-summary/repositories/suite-checkout-summary-budget-repository.ts b/cypress/support/pages/yves/purchasing-control/checkout-summary/repositories/suite-checkout-summary-budget-repository.ts new file mode 100644 index 000000000..d7cd1042a --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/checkout-summary/repositories/suite-checkout-summary-budget-repository.ts @@ -0,0 +1,17 @@ +import { injectable } from 'inversify'; +import { CheckoutSummaryBudgetRepository } from '../checkout-summary-budget-repository'; + +@injectable() +export class SuiteCheckoutSummaryBudgetRepository implements CheckoutSummaryBudgetRepository { + getCheckoutErrorMessage = (): Cypress.Chainable => cy.get('ul.list--alert'); + + getWarnFlashMessage = (): Cypress.Chainable => cy.get('flash-message.flash-message--alert'); + + getCostCenterSelectorValue = (): Cypress.Chainable => cy.get('.cost-center-selector__value'); + + getBudgetRemainingAmount = (): Cypress.Chainable => cy.get('.cost-center-selector__remaining'); + + getApproveButton = (): Cypress.Chainable => cy.get('button.button--success'); + + getDeclineButton = (): Cypress.Chainable => cy.get('button.button--alert'); +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/create/cost-center-create-page.ts b/cypress/support/pages/yves/purchasing-control/cost-center/create/cost-center-create-page.ts new file mode 100644 index 000000000..7a267a091 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/create/cost-center-create-page.ts @@ -0,0 +1,33 @@ +import { REPOSITORIES, autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { YvesPage } from '@pages/yves'; +import { CostCenterCreateRepository } from './cost-center-create-repository'; + +@injectable() +@autoWired +export class YvesCostCenterCreatePage extends YvesPage { + @inject(REPOSITORIES.YvesCostCenterCreateRepository) + private repository: CostCenterCreateRepository; + + protected PAGE_URL = '/company/cost-center/create'; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillDescription = (description: string): void => { + this.repository.getDescriptionTextarea().clear().type(description); + }; + + selectBusinessUnit = (idBusinessUnit: number): void => { + this.repository.getBusinessUnitCheckbox(idBusinessUnit).check({ force: true }); + }; + + submit = (): void => { + this.repository.getSubmitButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessFlashMessage().should('be.visible'); + }; +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/create/cost-center-create-repository.ts b/cypress/support/pages/yves/purchasing-control/cost-center/create/cost-center-create-repository.ts new file mode 100644 index 000000000..2108d33fb --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/create/cost-center-create-repository.ts @@ -0,0 +1,7 @@ +export interface CostCenterCreateRepository { + getNameInput(): Cypress.Chainable; + getDescriptionTextarea(): Cypress.Chainable; + getBusinessUnitCheckbox(idBusinessUnit: number): Cypress.Chainable; + getSubmitButton(): Cypress.Chainable; + getSuccessFlashMessage(): Cypress.Chainable; +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/create/repositories/suite-cost-center-create-repository.ts b/cypress/support/pages/yves/purchasing-control/cost-center/create/repositories/suite-cost-center-create-repository.ts new file mode 100644 index 000000000..8668c9f62 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/create/repositories/suite-cost-center-create-repository.ts @@ -0,0 +1,16 @@ +import { injectable } from 'inversify'; +import { CostCenterCreateRepository } from '../cost-center-create-repository'; + +@injectable() +export class SuiteCostCenterCreateRepository implements CostCenterCreateRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="cost-center-name-input"]'); + + getDescriptionTextarea = (): Cypress.Chainable => cy.get('[data-qa="cost-center-description-input"]'); + + getBusinessUnitCheckbox = (idBusinessUnit: number): Cypress.Chainable => + cy.get(`[name="costCenterForm[companyBusinessUnitIds][]"][value="${idBusinessUnit}"]`); + + getSubmitButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + + getSuccessFlashMessage = (): Cypress.Chainable => cy.get('[data-qa="component notification-area"] flash-message'); +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/list/cost-center-list-page.ts b/cypress/support/pages/yves/purchasing-control/cost-center/list/cost-center-list-page.ts new file mode 100644 index 000000000..19e2006e0 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/list/cost-center-list-page.ts @@ -0,0 +1,30 @@ +import { REPOSITORIES, autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { YvesPage } from '@pages/yves'; +import { CostCenterListRepository } from './cost-center-list-repository'; + +@injectable() +@autoWired +export class YvesCostCenterListPage extends YvesPage { + @inject(REPOSITORIES.YvesCostCenterListRepository) + private repository: CostCenterListRepository; + + protected PAGE_URL = '/company/cost-center'; + + clickCreateButton = (): void => { + this.repository.getCreateButton().click(); + }; + + clickEditButton = (uuid: string): void => { + this.repository.getEditButtonByUuid(uuid).click(); + }; + + assertCostCenterInTable = (name: string): void => { + cy.visit(`/company/cost-center?costCenterSearchForm[name]=${encodeURIComponent(name)}`); + this.repository.getTableRows().should('contain', name); + }; + + assertStatusBadge = (uuid: string, expectedStatus: string): void => { + this.repository.getStatusBadgeByUuid(uuid).should('contain', expectedStatus); + }; +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/list/cost-center-list-repository.ts b/cypress/support/pages/yves/purchasing-control/cost-center/list/cost-center-list-repository.ts new file mode 100644 index 000000000..00ceb9871 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/list/cost-center-list-repository.ts @@ -0,0 +1,6 @@ +export interface CostCenterListRepository { + getCreateButton(): Cypress.Chainable; + getTableRows(): Cypress.Chainable; + getEditButtonByUuid(uuid: string): Cypress.Chainable; + getStatusBadgeByUuid(uuid: string): Cypress.Chainable; +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/list/repositories/suite-cost-center-list-repository.ts b/cypress/support/pages/yves/purchasing-control/cost-center/list/repositories/suite-cost-center-list-repository.ts new file mode 100644 index 000000000..ea3485545 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/list/repositories/suite-cost-center-list-repository.ts @@ -0,0 +1,18 @@ +import { injectable } from 'inversify'; +import { CostCenterListRepository } from '../cost-center-list-repository'; + +@injectable() +export class SuiteCostCenterListRepository implements CostCenterListRepository { + getCreateButton = (): Cypress.Chainable => cy.get('a[href*="cost-center/create"]'); + + getTableRows = (): Cypress.Chainable => cy.get('[data-qa="component data-table"] tbody tr'); + + getEditButtonByUuid = (uuid: string): Cypress.Chainable => + cy.get(`[data-qa="cell-actions"] a[href*="${uuid}"]`).first(); + + getStatusBadgeByUuid = (uuid: string): Cypress.Chainable => + cy + .get(`[data-qa="cell-actions"] a[href*="${uuid}"]`) + .closest('tr') + .find('[data-qa="cell-spy_cost_center.is_active"]'); +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/update/cost-center-update-page.ts b/cypress/support/pages/yves/purchasing-control/cost-center/update/cost-center-update-page.ts new file mode 100644 index 000000000..27ea17e1e --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/update/cost-center-update-page.ts @@ -0,0 +1,53 @@ +import { REPOSITORIES, autoWired } from '@utils'; +import { inject, injectable } from 'inversify'; +import { YvesPage } from '@pages/yves'; +import { CostCenterUpdateRepository } from './cost-center-update-repository'; + +@injectable() +@autoWired +export class YvesCostCenterUpdatePage extends YvesPage { + @inject(REPOSITORIES.YvesCostCenterUpdateRepository) + private repository: CostCenterUpdateRepository; + + protected PAGE_URL = '/company/cost-center/update'; + + visitByUuid = (uuid: string): void => { + cy.visit(`/company/cost-center/update?costCenterUuid=${uuid}`); + }; + + fillName = (name: string): void => { + this.repository.getNameInput().clear().type(name); + }; + + fillDescription = (description: string): void => { + this.repository.getDescriptionTextarea().clear().type(description); + }; + + deactivate = (): void => { + this.repository.getIsActiveCheckbox().uncheck({ force: true }); + }; + + activate = (): void => { + this.repository.getIsActiveCheckbox().check({ force: true }); + }; + + submit = (): void => { + this.repository.getSubmitButton().click(); + }; + + assertSuccess = (): void => { + this.repository.getSuccessFlashMessage().should('be.visible'); + }; + + assertIsActive = (): void => { + this.repository.getIsActiveCheckbox().should('be.checked'); + }; + + assertIsInactive = (): void => { + this.repository.getIsActiveCheckbox().should('not.be.checked'); + }; + + getNameValue = (): Cypress.Chainable => { + return this.repository.getNameInput().invoke('val') as Cypress.Chainable; + }; +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/update/cost-center-update-repository.ts b/cypress/support/pages/yves/purchasing-control/cost-center/update/cost-center-update-repository.ts new file mode 100644 index 000000000..f66125aec --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/update/cost-center-update-repository.ts @@ -0,0 +1,7 @@ +export interface CostCenterUpdateRepository { + getNameInput(): Cypress.Chainable; + getDescriptionTextarea(): Cypress.Chainable; + getIsActiveCheckbox(): Cypress.Chainable; + getSubmitButton(): Cypress.Chainable; + getSuccessFlashMessage(): Cypress.Chainable; +} diff --git a/cypress/support/pages/yves/purchasing-control/cost-center/update/repositories/suite-cost-center-update-repository.ts b/cypress/support/pages/yves/purchasing-control/cost-center/update/repositories/suite-cost-center-update-repository.ts new file mode 100644 index 000000000..3d41d5093 --- /dev/null +++ b/cypress/support/pages/yves/purchasing-control/cost-center/update/repositories/suite-cost-center-update-repository.ts @@ -0,0 +1,15 @@ +import { injectable } from 'inversify'; +import { CostCenterUpdateRepository } from '../cost-center-update-repository'; + +@injectable() +export class SuiteCostCenterUpdateRepository implements CostCenterUpdateRepository { + getNameInput = (): Cypress.Chainable => cy.get('[data-qa="cost-center-name-input"]'); + + getDescriptionTextarea = (): Cypress.Chainable => cy.get('[data-qa="cost-center-description-input"]'); + + getIsActiveCheckbox = (): Cypress.Chainable => cy.get('#costCenterForm_isActive'); + + getSubmitButton = (): Cypress.Chainable => cy.get('[data-qa="submit-button"]'); + + getSuccessFlashMessage = (): Cypress.Chainable => cy.get('[data-qa="component notification-area"] flash-message'); +} diff --git a/cypress/support/types/backoffice/index.ts b/cypress/support/types/backoffice/index.ts index 41ac228e0..f04c64840 100644 --- a/cypress/support/types/backoffice/index.ts +++ b/cypress/support/types/backoffice/index.ts @@ -18,3 +18,4 @@ export * from './restore-session-after-login-timeout'; export * from './product-merchant-relation-management'; export * from './configuration'; export * from './acl-navigation-access'; +export * from './purchasing-control'; diff --git a/cypress/support/types/backoffice/purchasing-control.ts b/cypress/support/types/backoffice/purchasing-control.ts new file mode 100644 index 000000000..0d3235539 --- /dev/null +++ b/cypress/support/types/backoffice/purchasing-control.ts @@ -0,0 +1,30 @@ +import { User } from './shared'; + +export interface BackofficeCostCenterCrudStaticFixtures { + defaultPassword: string; + newCostCenterName: string; + newCostCenterDescription: string; + updatedCostCenterName: string; +} + +export interface BackofficeCostCenterCrudDynamicFixtures { + rootUser: User; + company: { id_company: number; name: string }; + businessUnit: { id_company_business_unit: number; name: string }; + preExistingCostCenter: { id_cost_center: number; uuid: string; name: string }; +} + +export interface BackofficeBudgetCrudStaticFixtures { + defaultPassword: string; + newBudgetName: string; + budgetAmount: string; + budgetCurrency: string; + budgetEnforcementRule: string; + updatedBudgetName: string; +} + +export interface BackofficeBudgetCrudDynamicFixtures { + rootUser: User; + costCenter: { id_cost_center: number; uuid: string; name: string }; + preExistingBudget: { id_budget: number; uuid: string; name: string }; +} diff --git a/cypress/support/types/yves/index.ts b/cypress/support/types/yves/index.ts index 09415a3e3..845a190cf 100644 --- a/cypress/support/types/yves/index.ts +++ b/cypress/support/types/yves/index.ts @@ -19,3 +19,4 @@ export * from './ssp-file-management'; export * from './ssp-asset'; export * from './ssp-asset-specific-catalog'; export * from './ssp-dashboard-management'; +export * from './purchasing-control'; diff --git a/cypress/support/types/yves/purchasing-control.ts b/cypress/support/types/yves/purchasing-control.ts new file mode 100644 index 000000000..6c871ef28 --- /dev/null +++ b/cypress/support/types/yves/purchasing-control.ts @@ -0,0 +1,43 @@ +export interface YvesCostCenterCrudStaticFixtures { + defaultPassword: string; + newCostCenterName: string; + newCostCenterDescription: string; + updatedCostCenterName: string; +} + +export interface YvesCostCenterCrudDynamicFixtures { + authorizedCustomer: { email: string }; + unauthorizedCustomer: { email: string }; + businessUnit: { id_company_business_unit: number; name: string }; + preExistingCostCenter: { id_cost_center: number; uuid: string; name: string }; + inactiveCostCenter: { id_cost_center: number; uuid: string; name: string }; +} + +export interface YvesBudgetCrudStaticFixtures { + defaultPassword: string; + newBudgetName: string; + budgetAmount: string; + budgetCurrency: string; + budgetEnforcementRule: string; + updatedBudgetName: string; +} + +export interface YvesBudgetCrudDynamicFixtures { + authorizedCustomer: { email: string }; + costCenter: { id_cost_center: number; uuid: string; name: string }; + preExistingBudget: { id_budget: number; uuid: string; name: string }; +} + +export interface BudgetEnforcementStaticFixtures { + defaultPassword: string; +} + +export interface BudgetEnforcementDynamicFixtures { + buyerForWithin: { email: string }; + buyerForBlock: { email: string }; + buyerForWarn: { email: string }; + buyerForRequireApproval: { email: string }; + buyerForApproved: { email: string }; + approverCustomer: { email: string }; + approverCompanyUser: { id_company_user: number }; +} diff --git a/cypress/support/utils/inversify/inversify.config.ts b/cypress/support/utils/inversify/inversify.config.ts index 7058681b5..2ccc2ab5f 100644 --- a/cypress/support/utils/inversify/inversify.config.ts +++ b/cypress/support/utils/inversify/inversify.config.ts @@ -177,6 +177,13 @@ import { B2bMpSspDashboardManagementRepository } from '../../pages/yves/ssp-dash import { B2bSspDashboardManagementRepository } from '../../pages/yves/ssp-dashboard-management/repositories/b2b-ssp-dashboard-management-repository'; import { SuiteMerchantRegistrationRepository } from '../../pages/yves/merchant-registration/repositories/suite-merchant-registration-repository'; import { B2bMpMerchantRegistrationRepository } from '../../pages/yves/merchant-registration/repositories/b2b-mp-merchant-registration-repository'; +import { SuiteCostCenterListRepository } from '../../pages/yves/purchasing-control/cost-center/list/repositories/suite-cost-center-list-repository'; +import { SuiteCostCenterCreateRepository } from '../../pages/yves/purchasing-control/cost-center/create/repositories/suite-cost-center-create-repository'; +import { SuiteCostCenterUpdateRepository } from '../../pages/yves/purchasing-control/cost-center/update/repositories/suite-cost-center-update-repository'; +import { SuiteBudgetListRepository } from '../../pages/yves/purchasing-control/budget/list/repositories/suite-budget-list-repository'; +import { SuiteBudgetCreateRepository } from '../../pages/yves/purchasing-control/budget/create/repositories/suite-budget-create-repository'; +import { SuiteBudgetUpdateRepository } from '../../pages/yves/purchasing-control/budget/update/repositories/suite-budget-update-repository'; +import { SuiteCheckoutSummaryBudgetRepository } from '../../pages/yves/purchasing-control/checkout-summary/repositories/suite-checkout-summary-budget-repository'; type BindingsMap = { [K in REPOSITORIES]?: interfaces.Newable }; @@ -218,6 +225,13 @@ const suiteMappings: BindingsMap = { [REPOSITORIES.UserMultiFactorAuthRepository]: SuiteUserMultiFactorAuthRepository, [REPOSITORIES.SspDashboardManagementRepository]: SuiteSspDashboardManagementRepository, [REPOSITORIES.MerchantRegistrationRepository]: SuiteMerchantRegistrationRepository, + [REPOSITORIES.YvesCostCenterListRepository]: SuiteCostCenterListRepository, + [REPOSITORIES.YvesCostCenterCreateRepository]: SuiteCostCenterCreateRepository, + [REPOSITORIES.YvesCostCenterUpdateRepository]: SuiteCostCenterUpdateRepository, + [REPOSITORIES.YvesBudgetListRepository]: SuiteBudgetListRepository, + [REPOSITORIES.YvesBudgetCreateRepository]: SuiteBudgetCreateRepository, + [REPOSITORIES.YvesBudgetUpdateRepository]: SuiteBudgetUpdateRepository, + [REPOSITORIES.YvesCheckoutSummaryBudgetRepository]: SuiteCheckoutSummaryBudgetRepository, }; const b2cMappings: BindingsMap = { diff --git a/cypress/support/utils/inversify/types.ts b/cypress/support/utils/inversify/types.ts index 5f346a90d..91ef1f231 100644 --- a/cypress/support/utils/inversify/types.ts +++ b/cypress/support/utils/inversify/types.ts @@ -36,4 +36,11 @@ export const enum REPOSITORIES { UserMultiFactorAuthRepository = 'UserMultiFactorAuthRepository', SspDashboardManagementRepository = 'SspDashboardManagementRepository', MerchantRegistrationRepository = 'MerchantRegistrationRepository', + YvesCostCenterListRepository = 'YvesCostCenterListRepository', + YvesCostCenterCreateRepository = 'YvesCostCenterCreateRepository', + YvesCostCenterUpdateRepository = 'YvesCostCenterUpdateRepository', + YvesBudgetListRepository = 'YvesBudgetListRepository', + YvesBudgetCreateRepository = 'YvesBudgetCreateRepository', + YvesBudgetUpdateRepository = 'YvesBudgetUpdateRepository', + YvesCheckoutSummaryBudgetRepository = 'YvesCheckoutSummaryBudgetRepository', } diff --git a/package-lock.json b/package-lock.json index 614e2ee48..cae9488cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@faker-js/faker": "^8.4.1", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", - "cypress": "^14.5.3", + "cypress": "^14.5.4", "cypress-file-upload": "^5.0.8", "dotenv": "^16.4.5", "eslint": "^8.57.0", @@ -1689,9 +1689,9 @@ } }, "node_modules/cypress": { - "version": "14.5.3", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-14.5.3.tgz", - "integrity": "sha512-syLwKjDeMg77FRRx68bytLdlqHXDT4yBVh0/PPkcgesChYDjUZbwxLqMXuryYKzAyJsPsQHUDW1YU74/IYEUIA==", + "version": "14.5.4", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-14.5.4.tgz", + "integrity": "sha512-0Dhm4qc9VatOcI1GiFGVt8osgpPdqJLHzRwcAB5MSD/CAAts3oybvPUPawHyvJZUd8osADqZe/xzMsZ8sDTjXw==", "dev": true, "hasInstallScript": true, "license": "MIT", diff --git a/package.json b/package.json index f4caee97b..f6fd0f1b7 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@faker-js/faker": "^8.4.1", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", - "cypress": "^14.5.3", + "cypress": "^14.5.4", "cypress-file-upload": "^5.0.8", "dotenv": "^16.4.5", "eslint": "^8.57.0",