From 28526c6a4f43806168cbc133cb7193b704f6b824 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 30 Sep 2025 10:14:41 -0400 Subject: [PATCH 1/4] feat: refactor condition limit handling for max conditions --- .../ConditionalRedirect/ConditionalRedirect.vue | 14 ++++++++++++-- .../ConditionalRedirect/TaskDestination.vue | 5 +++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue b/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue index 6e87862af..f8980fc0e 100644 --- a/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue +++ b/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue @@ -19,7 +19,7 @@ type="button" class="btn btn-light" @click="addCondition" - :disabled="conditions.length >= MAX_CONDITIONS" + :disabled="maxConditionsReached" data-test="conditional-add-button" > @@ -34,6 +34,7 @@ :value="condition" :taskDestinationOptions="taskDestinationOptions" :conditionId="condition.id" + :maxConditionsReached="maxConditionsReached" @input="onSaveCondition" @duplicate="onDuplicateCondition" @remove="onRemoveCondition" @@ -82,6 +83,11 @@ export default { MAX_CONDITIONS, }; }, + computed: { + maxConditionsReached() { + return this.conditions.length >= MAX_CONDITIONS; + }, + }, watch: { isEnabled: { handler() { @@ -121,7 +127,7 @@ export default { this.$emit('input', data); }, addCondition() { - if (this.conditions.length >= MAX_CONDITIONS) { + if (this.maxConditionsReached) { return; } @@ -146,6 +152,10 @@ export default { this.updateConditionalRedirect(); }, onDuplicateCondition(conditionId) { + if (this.maxConditionsReached) { + return; + } + const condition = this.conditions.find((condition) => condition.id === conditionId); this.conditions.push({ diff --git a/src/components/inspectors/ConditionalRedirect/TaskDestination.vue b/src/components/inspectors/ConditionalRedirect/TaskDestination.vue index f75fbee35..8857ccdbf 100644 --- a/src/components/inspectors/ConditionalRedirect/TaskDestination.vue +++ b/src/components/inspectors/ConditionalRedirect/TaskDestination.vue @@ -61,6 +61,7 @@ type="button" class="btn btn-light btn-sm text-capitalize" @click="onDuplicateCondition" + :disabled="maxConditionsReached" data-test="conditional-duplicate-button" > Duplicate @@ -96,6 +97,10 @@ export default { type: Array, required: true, }, + maxConditionsReached: { + type: Boolean, + required: true, + }, }, data() { return { From cc5b657db5c9a144728e8bc41bc00c3a5d9f48ac Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 30 Sep 2025 15:58:42 -0400 Subject: [PATCH 2/4] feat: update conditional redirect description and task source label --- .../ConditionalRedirect/ConditionalRedirect.vue | 10 +++++++--- .../ConditionalRedirect/conditionalRedirect.js | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue b/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue index f8980fc0e..b725a4a69 100644 --- a/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue +++ b/src/components/inspectors/ConditionalRedirect/ConditionalRedirect.vue @@ -2,9 +2,10 @@
- + Task Destination is used.'); + }, maxConditionsReached() { return this.conditions.length >= MAX_CONDITIONS; }, diff --git a/src/components/inspectors/ConditionalRedirect/conditionalRedirect.js b/src/components/inspectors/ConditionalRedirect/conditionalRedirect.js index ac8198844..5734c09c8 100644 --- a/src/components/inspectors/ConditionalRedirect/conditionalRedirect.js +++ b/src/components/inspectors/ConditionalRedirect/conditionalRedirect.js @@ -6,7 +6,7 @@ export default { label: 'Conditional Redirects', name: 'conditionalRedirect', options: [ - { value: 'taskSource', content: 'Task Source (Default)' }, + { value: 'taskSource', content: 'Task Source' }, { value: 'taskList', content: 'Task List' }, { value: 'processLaunchpad', content: 'Process Launchpad' }, { value: 'homepageDashboard', content: 'Home Page' }, From 0e8540953753f3cef7d165c1940c0c7af33d5744 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Wed, 1 Oct 2025 08:55:45 -0400 Subject: [PATCH 3/4] test: add end-to-end tests for conditional redirect functionality --- .../e2e/specs/conditionalRedirect/Tasks.cy.js | 277 ++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 tests/e2e/specs/conditionalRedirect/Tasks.cy.js diff --git a/tests/e2e/specs/conditionalRedirect/Tasks.cy.js b/tests/e2e/specs/conditionalRedirect/Tasks.cy.js new file mode 100644 index 000000000..2c36b3470 --- /dev/null +++ b/tests/e2e/specs/conditionalRedirect/Tasks.cy.js @@ -0,0 +1,277 @@ +import { + addNodeTypeToPaper, + clickAndDropElement, + getElementAtPosition, modalAnimationTime, + modalCancel, + modalConfirm, + toggleInspector, + typeIntoTextInput, waitForAnimations, + waitToRenderAllShapes, +} from '../../support/utils'; + +import { nodeTypes } from '../../support/constants'; + +describe('Conditional Redirect Tasks', () => { + const taskPosition = { x: 350, y: 250 }; + const testString = 'Conditional Redirect'; + + beforeEach(() => { + toggleInspector(); + }); + + it('Update task name', () => { + clickAndDropElement(nodeTypes.task, taskPosition); + waitToRenderAllShapes(); + + getElementAtPosition(taskPosition).click(); + + typeIntoTextInput('[name=name]', testString); + cy.get('[name=name]').should('have.value', testString); + }); + + it('Update task conditional redirect', () => { + clickAndDropElement(nodeTypes.task, taskPosition); + waitToRenderAllShapes(); + + getElementAtPosition(taskPosition).click(); + + // Enable conditional redirect + cy.get('[data-test=conditional-toggle]').click({ force: true }); + cy.get('[data-test=conditional-add-button]').should('be.visible'); + + // Add condition default empty + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box]').should('be.visible'); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 1); + + // Conditional Redirect - Task Source (Default) + cy.get('[data-test=conditional-box] .task-destination').eq(0).within(() => { + cy.get('[data-test=conditional-task-condition]').type('score > 80'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('Task Source').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'Task Source'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'score > 80'); + }); + + // Conditional Redirect - Task List + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 2); + + cy.get('[data-test=conditional-box] .task-destination').eq(1).within(() => { + cy.get('[data-test=conditional-task-condition]').type('score < 80'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('Task List').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'Task List'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'score < 80'); + }); + + // Conditional Redirect - Process Launchpad + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 3); + + cy.get('[data-test=conditional-box] .task-destination').eq(2).within(() => { + cy.get('[data-test=conditional-task-condition]').type('score == 80'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('Process Launchpad').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'Process Launchpad'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'score == 80'); + }); + + // Conditional Redirect - Home Page + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 4); + + cy.get('[data-test=conditional-box] .task-destination').eq(3).within(() => { + cy.get('[data-test=conditional-task-condition]').type('amount > 1000'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('Home Page').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'Home Page'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'amount > 1000'); + }); + + // Conditional Redirect - Custom Dashboard + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 5); + + cy.get('[data-test=conditional-box] .task-destination').eq(4).within(() => { + cy.get('[data-test=conditional-task-condition]').type('amount == 1000'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('Custom Dashboard').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'Custom Dashboard'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'amount == 1000'); + }); + + // Conditional Redirect - External URL + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 6); + + cy.get('[data-test=conditional-box] .task-destination').eq(5).within(() => { + cy.get('[data-test=conditional-task-condition]').type('amount < 1000'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('External URL').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'External URL'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'amount < 1000'); + + cy.get('[data-test=conditional-task-external-url]').type('https://github.com'); + cy.get('[data-test=conditional-task-external-url]').should('have.value', 'https://github.com'); + }); + + // Conditional Redirect - Display Next Assigned Task + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 7); + + cy.get('[data-test=conditional-box] .task-destination').eq(6).within(() => { + cy.get('[data-test=conditional-task-condition]').type('amount == 1000'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('Display Next Assigned Task').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'Display Next Assigned Task'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'amount == 1000'); + }); + }); + + it('Max conditions reached', () => { + clickAndDropElement(nodeTypes.task, taskPosition); + waitToRenderAllShapes(); + + getElementAtPosition(taskPosition).click(); + + // Enable conditional redirect + cy.get('[data-test=conditional-toggle]').click({ force: true }); + cy.get('[data-test=conditional-add-button]').should('be.visible'); + + const conditionalAddButtonDataTest = '[data-test=conditional-add-button]'; + + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 1); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 2); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 3); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 4); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 5); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 6); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 7); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 8); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 9); + + // Add condition default empty + cy.get(conditionalAddButtonDataTest).click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 10); + + cy.get(conditionalAddButtonDataTest).should('be.disabled'); + }); + + it('Duplicate condition', () => { + clickAndDropElement(nodeTypes.task, taskPosition); + waitToRenderAllShapes(); + + getElementAtPosition(taskPosition).click(); + + // Enable conditional redirect + cy.get('[data-test=conditional-toggle]').click({ force: true }); + cy.get('[data-test=conditional-add-button]').should('be.visible'); + + // Add condition default empty + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 1); + + cy.get('[data-test=conditional-box] .task-destination').first().within(() => { + cy.get('[data-test=conditional-task-condition]').type('score == 80'); + cy.get('[data-test=conditional-task-redirect]').click(); + + cy.get('.multiselect__content-wrapper').should('be.visible'); + cy.get('.multiselect__option').contains('Process Launchpad').click(); + + cy.get('[class=multiselect__single]').should('exist'); + cy.get('[class=multiselect__single]').should('contain', 'Process Launchpad'); + cy.get('[data-test=conditional-task-condition]').should('have.value', 'score == 80'); + }); + + // Duplicate condition + cy.get('[data-test=conditional-box] .task-destination').eq(0).within(() => { + cy.get('[data-test=conditional-duplicate-button]').click(); + }); + + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 2); + + cy.get('[data-test=conditional-box] .task-destination').last().within(() => { + cy.get('[data-test=conditional-task-condition]').should('have.value', 'score == 80'); + cy.get('[class=multiselect__single]').should('contain', 'Process Launchpad'); + }); + }); + + it('Remove condition', () => { + clickAndDropElement(nodeTypes.task, taskPosition); + waitToRenderAllShapes(); + + getElementAtPosition(taskPosition).click(); + + // Enable conditional redirect + cy.get('[data-test=conditional-toggle]').click({ force: true }); + cy.get('[data-test=conditional-add-button]').should('be.visible'); + + // Add condition default empty + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 1); + + cy.get('[data-test=conditional-add-button]').click(); + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 2); + + cy.get('[data-test=conditional-box] .task-destination').last().within(() => { + cy.get('[data-test=conditional-remove-button]').click(); + }); + + cy.get('[data-test=conditional-box] .task-destination').should('have.length', 1); + }); + +}); From 051ded0dd6fa41beff87b21b70785c64abc081c9 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Wed, 1 Oct 2025 09:01:23 -0400 Subject: [PATCH 4/4] test: clean up unused imports in conditional redirect tests --- tests/e2e/specs/conditionalRedirect/Tasks.cy.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/e2e/specs/conditionalRedirect/Tasks.cy.js b/tests/e2e/specs/conditionalRedirect/Tasks.cy.js index 2c36b3470..84fcaea0a 100644 --- a/tests/e2e/specs/conditionalRedirect/Tasks.cy.js +++ b/tests/e2e/specs/conditionalRedirect/Tasks.cy.js @@ -1,11 +1,8 @@ import { - addNodeTypeToPaper, clickAndDropElement, - getElementAtPosition, modalAnimationTime, - modalCancel, - modalConfirm, + getElementAtPosition, toggleInspector, - typeIntoTextInput, waitForAnimations, + typeIntoTextInput, waitToRenderAllShapes, } from '../../support/utils';