From 4ee94fa5afc9305c042c6756ca27b50a0e4f90e1 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Wed, 18 Dec 2024 16:31:04 -0500 Subject: [PATCH 01/15] prep for cypress test automation for mix in PD' --- cypress.config.ts | 9 ++++ cypress/fixtures/example.json | 5 ++ cypress/support/commands.ts | 37 +++++++++++++ cypress/support/e2e.ts | 20 +++++++ protocol-designer/cypress.config.js | 2 +- .../cypress/e2e/mixSettings.cy.js | 54 +++++++++++++++++++ protocol-designer/cypress/support/commands.ts | 18 +++++++ 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 cypress.config.ts create mode 100644 cypress/fixtures/example.json create mode 100644 cypress/support/commands.ts create mode 100644 cypress/support/e2e.ts diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 00000000000..17161e32e08 --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 00000000000..02e4254378e --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts new file mode 100644 index 00000000000..698b01a42c3 --- /dev/null +++ b/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 00000000000..f80f74f8e1f --- /dev/null +++ b/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/protocol-designer/cypress.config.js b/protocol-designer/cypress.config.js index 98d139cdcbc..4ae03d41a41 100644 --- a/protocol-designer/cypress.config.js +++ b/protocol-designer/cypress.config.js @@ -10,6 +10,6 @@ module.exports = defineConfig({ setupNodeEvents(on, config) { return require('./cypress/plugins/index.js')(on, config) }, - baseUrl: 'http://localhost:5178', + baseUrl: 'https://sandbox.designer.opentrons.com/edge', }, }) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.js b/protocol-designer/cypress/e2e/mixSettings.cy.js index 600d25971be..0def005c4f0 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.js +++ b/protocol-designer/cypress/e2e/mixSettings.cy.js @@ -1,3 +1,57 @@ +import '../support/commands.ts'; // Importing the custom commands file + +const Flex_Home = 'Opentrons Flex'; +const OT2_Home = 'Opentrons OT-2'; + + +describe('Happy Path Mixing Tests', () => { + it('It should verify the working function of every permutation of transfer checkboxes', () => { + + cy.visit('/'); // Replace with the appropriate URL or navigation + cy.verifyHomePage(); // This calls the custom command from commands.ts + cy.clickCreateNew() + cy.robotSelection(Flex_Home) + + + /* Is it correct to assume that, for example, testing mix settings, that we would need to run functions that at least perform XYZ tasks to get to that point?*/ + + //we need a function to run through the pipette/volume/tiprack selection flow (Add Pipettes Page) + //We need a function to run through your pipettes and add a pipette (Robot Pipettes Page) + //Add a gripper page + //Add modules + //add fixtures + + + const pipette = '1-Channel' + function putPipette(pipette) { + cy.contains('label', pipette).should('exist').and('be.visible').click() + } + putPipette(pipette) + // Check step 2 has the right text + cy.contains('Step 2') + cy.contains('Add a pipette') + cy.contains('Pick your first pipette. If you need a second pipette, you can add it next.') + // Check + cy.contains('button', 'Go back').click() + cy.robotSelection(Flex_Home) + putPipette(pipette) + }); +}); + + + + + + + + + + + + + + + // TODO: refactor to test with new navigation // const isMacOSX = Cypress.platform === 'darwin' // const invalidInput = 'abcdefghijklmnopqrstuvwxyz!@#$%^&*()<>?,-' diff --git a/protocol-designer/cypress/support/commands.ts b/protocol-designer/cypress/support/commands.ts index 3f9ffd8ddd8..9bd00058c1f 100644 --- a/protocol-designer/cypress/support/commands.ts +++ b/protocol-designer/cypress/support/commands.ts @@ -27,6 +27,7 @@ declare global { openDesignPage: () => Cypress.Chainable addStep: (stepName: string) => Cypress.Chainable openSettingsPage: () => Cypress.Chainable + robotSelection: (robotName: string) => Cypress.Chainable verifySettingsPage: () => Cypress.Chainable verifyCreateNewPage: () => Cypress.Chainable togglePreWetTip: () => Cypress.Chainable @@ -54,6 +55,8 @@ export const locators = { import: 'Import', createNew: 'Create new', createProtocol: 'Create a protocol', + Flex_Home: 'Opentrons Flex', + OT2_Home: "Opentrons OT-2", editProtocol: 'Edit existing protocol', settingsDataTestid: 'SettingsIconButton', settings: 'Settings', @@ -119,6 +122,21 @@ Cypress.Commands.add('importProtocol', (protocolFilePath: string) => { .selectFile(protocolFilePath, { force: true }) }) +Cypress.Commands.add('robotSelection',(robotName:string) =>{ + if (robotName ==='Opentrons OT-2') { + cy.contains('label', locators.OT2_Home ).should('be.visible').click() + + } + else { + // Just checking that the selection modal works + cy.contains('label', locators.OT2_Home ).should('be.visible').click() + cy.contains('label', locators.Flex_Home).should('be.visible').click() + + } + cy.contains('button', "Confirm").should('be.visible').click() + +}) + // Settings Page Actions Cypress.Commands.add('openSettingsPage', () => { cy.getByTestId(locators.settingsDataTestid).click() From 0deebbe608b66664cccba998d8354934be94c43f Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Fri, 10 Jan 2025 15:34:24 -0500 Subject: [PATCH 02/15] test(change baseurl to localhost): changed the url from sandbox back to localhost --- protocol-designer/cypress.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol-designer/cypress.config.js b/protocol-designer/cypress.config.js index 4ae03d41a41..98d139cdcbc 100644 --- a/protocol-designer/cypress.config.js +++ b/protocol-designer/cypress.config.js @@ -10,6 +10,6 @@ module.exports = defineConfig({ setupNodeEvents(on, config) { return require('./cypress/plugins/index.js')(on, config) }, - baseUrl: 'https://sandbox.designer.opentrons.com/edge', + baseUrl: 'http://localhost:5178', }, }) From 5cace8199dbd401cd3596ce3c3283e5581f801cd Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Fri, 10 Jan 2025 15:35:09 -0500 Subject: [PATCH 03/15] test: remove incorrect file type --- .../cypress/e2e/mixSettings.cy.js | 353 ------------------ 1 file changed, 353 deletions(-) delete mode 100644 protocol-designer/cypress/e2e/mixSettings.cy.js diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.js b/protocol-designer/cypress/e2e/mixSettings.cy.js deleted file mode 100644 index 0def005c4f0..00000000000 --- a/protocol-designer/cypress/e2e/mixSettings.cy.js +++ /dev/null @@ -1,353 +0,0 @@ -import '../support/commands.ts'; // Importing the custom commands file - -const Flex_Home = 'Opentrons Flex'; -const OT2_Home = 'Opentrons OT-2'; - - -describe('Happy Path Mixing Tests', () => { - it('It should verify the working function of every permutation of transfer checkboxes', () => { - - cy.visit('/'); // Replace with the appropriate URL or navigation - cy.verifyHomePage(); // This calls the custom command from commands.ts - cy.clickCreateNew() - cy.robotSelection(Flex_Home) - - - /* Is it correct to assume that, for example, testing mix settings, that we would need to run functions that at least perform XYZ tasks to get to that point?*/ - - //we need a function to run through the pipette/volume/tiprack selection flow (Add Pipettes Page) - //We need a function to run through your pipettes and add a pipette (Robot Pipettes Page) - //Add a gripper page - //Add modules - //add fixtures - - - const pipette = '1-Channel' - function putPipette(pipette) { - cy.contains('label', pipette).should('exist').and('be.visible').click() - } - putPipette(pipette) - // Check step 2 has the right text - cy.contains('Step 2') - cy.contains('Add a pipette') - cy.contains('Pick your first pipette. If you need a second pipette, you can add it next.') - // Check - cy.contains('button', 'Go back').click() - cy.robotSelection(Flex_Home) - putPipette(pipette) - }); -}); - - - - - - - - - - - - - - - -// TODO: refactor to test with new navigation -// const isMacOSX = Cypress.platform === 'darwin' -// const invalidInput = 'abcdefghijklmnopqrstuvwxyz!@#$%^&*()<>?,-' -// const batchEditClickOptions = { [isMacOSX ? 'metaKey' : 'ctrlKey']: true } - -// function importProtocol() { -// cy.fixture('../../fixtures/protocol/5/mixSettings.json').then(fileContent => { -// cy.get('input[type=file]').upload({ -// fileContent: JSON.stringify(fileContent), -// fileName: 'fixture.json', -// mimeType: 'application/json', -// encoding: 'utf8', -// }) -// cy.get('div') -// .contains( -// 'Your protocol will be automatically updated to the latest version.' -// ) -// .should('exist') -// cy.get('button').contains('ok', { matchCase: false }).click() -// // wait until computation is done before proceeding, with generous timeout -// cy.get('[data-test="ComputingSpinner"]', { timeout: 30000 }).should( -// 'not.exist' -// ) -// }) -// } - -// function openDesignTab() { -// cy.get('button[id=NavTab_design]').click() -// cy.get('button').contains('ok').click() - -// // Verify the Design Page -// cy.get('#TitleBar_main > h1').contains('Multi select banner test protocol') -// cy.get('#TitleBar_main > h2').contains('STARTING DECK STATE') -// cy.get('button[id=StepCreationButton]').contains('+ Add Step') -// } - -// function enterBatchEdit() { -// cy.get('[data-test="StepItem_1"]').click(batchEditClickOptions) -// cy.get('button').contains('exit batch edit').should('exist') -// } - -describe('Advanced Settings for Mix Form', () => { - // before(() => { - // cy.visit('/') - // cy.closeAnnouncementModal() - // importProtocol() - // openDesignTab() - // }) - // it('should verify the batch edit form works as expected', () => { - // // Verify functionality of mix settings with different labware - // enterBatchEdit() - // // Different labware disbales aspirate and dispense Flowrate , tipPosition, delay and touchTip - // // step 4 has different labware than step 1 - // cy.get('[data-test="StepItem_4"]').click(batchEditClickOptions) - // // well-order is always enabled - // cy.get('[id=WellOrderField_button_mix]').should('be.visible') - // // Aspirate Flowrate disabled - // cy.get('input[name="aspirate_flowRate"]').should('be.disabled') - // // TipPosition Aspirate should be disabled - // cy.get('[id=TipPositionIcon_mix_mmFromBottom]').should('not.be.enabled') - // // Dispense Flowrate disbled - // cy.get('input[name="dispense_flowRate"]').should('be.disabled') - // // Delay aspirate & dispense and Touch tip is disabled - // cy.get('input[name="aspirate_delay_checkbox"]').should('be.disabled') - // cy.get('input[name="dispense_delay_checkbox"]').should('be.disabled') - // cy.get('input[name="mix_touchTip_checkbox"]').should('be.disabled') - // // Save button is disabled - // cy.get('button').contains('save').should('be.disabled') - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Verify functionality of mix settings with same labware - // enterBatchEdit() - // // Same labware enables aspirate and dispense Flowrate ,tipPosition ,delay and touchTip - // // deslecting step 4 - // cy.get('[data-test="StepItem_4"]').click(batchEditClickOptions) - // // step 2 has same labware as step 1 - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // Aspirate Flowrate are enabled - // cy.get('input[name="aspirate_flowRate"]').should('be.enabled') - // // Dispense Flowrate are enabled - // cy.get('input[name="dispense_flowRate"]').should('be.enabled') - // // TipPosition Aspirate should be enabled - // cy.get('[id=TipPositionIcon_mix_mmFromBottom]').should('not.be.disabled') - // // Delay in aspirate and Dispense settings is enabled - // cy.get('input[name="aspirate_delay_checkbox"]').should('be.enabled') - // cy.get('input[name="dispense_delay_checkbox"]').should('be.enabled') - // // Touchtip in Dispense settings is enabled - // cy.get('input[name="mix_touchTip_checkbox"]').should('be.enabled') - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Verify invalid input in delay field - // // click on step 2 in batch edit mode - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // cy.get('input[name="aspirate_delay_checkbox"]').click({ force: true }) - // cy.get('input[name="aspirate_delay_seconds"]') - // .type(invalidInput) - // .should('be.empty') - // // click on Discard Changes button to not save the changes - // cy.get('button').contains('discard changes').click() - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Verify indeterminate state of flowrate - // // click on step 2 in batch edit mode - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // cy.get('input[name="aspirate_flowRate"]').click({ force: true }) - // cy.contains( - // 'The default P1000 Single-Channel GEN2 flow rate is optimal for handling aqueous liquids' - // ) - // cy.get('input[name="aspirate_flowRate_customFlowRate"]').type('100') - // cy.get('button').contains('Done').click() - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Click on step 1 as it has flowrate set to 100 from previous testcase - // cy.get('[data-test="StepItem_1"]').click(batchEditClickOptions) - // // indeterminate state in flowrate is empty - // cy.get('input[name="aspirate_flowRate"]').should('have.value', '') - // // Verify functionality of flowrate in batch edit mix form - // // Batch editing the Flowrate value - // cy.get('input[name="aspirate_flowRate"]').click({ force: true }) - // cy.contains( - // 'The default P1000 Single-Channel GEN2 flow rate is optimal for handling aqueous liquids' - // ) - // cy.get('input[name="aspirate_flowRate_customFlowRate"]').type('100') - // cy.get('button').contains('Done').click() - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Click on step 2 to verify that flowrate is updated to 100 - // cy.get('[data-test="StepItem_2"]').click() - // cy.get('button[id="AspDispSection_settings_button_aspirate"]').click() - // // Verify that flowrate value - // cy.get('input[name="aspirate_flowRate"]').should('have.value', 100) - // // Click on step 1 to verify that flowrate is updated to 100 - // cy.get('[data-test="StepItem_1"]').click() - // cy.get('button[id="AspDispSection_settings_button_aspirate"]').click() - // // Verify that flowrate value - // cy.get('input[name="aspirate_flowRate"]').should('have.value', 100) - // // Verify delay settings indeterminate value - // // Click on step 2, to enter batch edit mode - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // Select delay settings - // cy.get('input[name="aspirate_delay_checkbox"]') - // .check({ force: true }) - // .should('be.checked') - // cy.get('input[name="aspirate_delay_seconds"]').type('2') - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Click on step 3 to generate indertminate state for delay settings. - // cy.get('[data-test="StepItem_3"]').click(batchEditClickOptions) - // // Verify the tooltip here - // cy.contains('delay').trigger('pointerover') - // cy.get('div[role="tooltip"]').should( - // 'contain', - // 'Not all selected steps are using this setting' - // ) - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Verify delay settings batch editing in mix form - // // Click on step 1, to enter batch edit mode - // cy.get('[data-test="StepItem_1"]').click(batchEditClickOptions) - // // Click on step 2 to batch edit mix settings - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // Select delay settings - // cy.get('input[name="aspirate_delay_checkbox"]').click({ force: true }) - // cy.get('input[name="aspirate_delay_seconds"]').clear().type('2') - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Click on step 1 to verify that delay has volume set to 2 - // cy.get('[data-test="StepItem_1"]').click() - // cy.get('button[id="AspDispSection_settings_button_aspirate"]').click() - // // Verify that volume is set to 2 - // cy.get('input[name="aspirate_delay_seconds"]').should('have.value', 2) - // // Click on step 2 to verify that delay has volume set to 2 - // cy.get('[data-test="StepItem_2"]').click() - // cy.get('button[id="AspDispSection_settings_button_aspirate"]').click() - // // Verify that volume is set to 2 - // cy.get('input[name="aspirate_delay_seconds"]').should('have.value', 2) - // // Verify touchTip settings indeterminate value - // cy.get('[data-test="StepItem_2"]').click() - // // Click on step 2, to enter batch edit mode - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // Select touchTip settings - // cy.get('input[name="mix_touchTip_checkbox"]').click({ force: true }) - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Click on step 1 to generate indertminate state for touchTip settings. - // cy.get('[data-test="StepItem_1"]').click(batchEditClickOptions) - // // Verify the tooltip here - // cy.contains('touch tip').trigger('pointerover') - // cy.get('div[role="tooltip"]').should( - // 'contain', - // 'Not all selected steps are using this setting' - // ) - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Verify touchTip settings batch editing in mix form - // cy.get('[data-test="StepItem_2"]').click() - // // Click on step 2, to enter batch edit mode - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // Click on step 3 to batch edit mix settings - // cy.get('[data-test="StepItem_3"]').click(batchEditClickOptions) - // // Select touchTip settings - // cy.get('input[name="mix_touchTip_checkbox"]').click({ force: true }) - // // cy.get('[id=TipPositionField_mix_touchTip_mmFromBottom]').type('24') - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Click on step 2 to verify that touchTip has volume set to 2 - // cy.get('[data-test="StepItem_2"]').click() - // cy.get('button[id="AspDispSection_settings_button_dispense"]').click() - // // Verify that volume is set - // cy.get('[id=TipPositionField_mix_touchTip_mmFromBottom]').should( - // 'have.value', - // 16.4 - // ) - // // Click on step 1 to verify that touchTip has volume set - // cy.get('[data-test="StepItem_3"]').click() - // cy.get('button[id="AspDispSection_settings_button_dispense"]').click() - // // Verify that volume is set - // cy.get('[id=TipPositionField_mix_touchTip_mmFromBottom]').should( - // 'have.value', - // 16.4 - // ) - // // Verify blowout settings indeterminate value - // // Click on step 2, to enter batch edit mode - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // Select blowout settings - // cy.get('input[name="blowout_checkbox"]').click({ force: true }) - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Click on step 1 to generate indertminate state for blowout settings. - // cy.get('[data-test="StepItem_1"]').click(batchEditClickOptions) - // // Verify the tooltip here - // cy.contains('blowout').trigger('pointerover') - // cy.get('div[role="tooltip"]').should( - // 'contain', - // 'Not all selected steps are using this setting' - // ) - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Verify blowout settings batch editing in mix form - // // Click on step 2, to enter batch edit mode - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // Click on step 3 to batch edit mix settings - // cy.get('[data-test="StepItem_3"]').click(batchEditClickOptions) - // // Select blowout settings - // cy.get('input[name="blowout_checkbox"]').click({ force: true }) - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // // Click on step 2 to verify that blowout has dest well selected - // cy.get('[data-test="StepItem_2"]').click() - // cy.get('button[id="AspDispSection_settings_button_aspirate"]').click() - // // Verify dest well is selected - // cy.get('[id=BlowoutLocationField_dropdown]').should($input => { - // const value = $input.val() - // const expectedSubstring = 'trashBin' - // expect(value).to.include(expectedSubstring) - // }) - // // Click on step 3 to verify the batch editing - // cy.get('[data-test="StepItem_3"]').click() - // cy.get('button[id="AspDispSection_settings_button_aspirate"]').click() - // // Verify that dest well is selected for the blowout option - // cy.get('[id=BlowoutLocationField_dropdown]').should($input => { - // const value = $input.val() - // const expectedSubstring = 'trashBin' - // expect(value).to.include(expectedSubstring) - // }) - // // verify well-order indeterminate state - // // Click on step 2, to enter batch edit and click on well order to change the order - // cy.get('[data-test="StepItem_2"]').click(batchEditClickOptions) - // // click on well-order and change the order - // cy.get('[id=WellOrderField_button_mix]').click({ force: true }) - // cy.get('h4').contains('Well Order') - // cy.get('p').contains( - // 'Change the order in which the robot aspirates from the selected wells' - // ) - // cy.get('select[name="mix_wellOrder_first"]') - // .select('Bottom to top') - // .should('have.value', 'b2t') - // cy.get('select[name="mix_wellOrder_second"]') - // .select('Left to right') - // .should('have.value', 'l2r') - // // Click done button to save the changes - // cy.get('button').contains('done').click() - // // Click save button to save the changes - // cy.get('button').contains('save').click() - // // Click on step 1, as it has different well order - // cy.get('[data-test="StepItem_1"]').click(batchEditClickOptions) - // cy.get('[id=WellOrderField_button_mix]').contains('mixed') - // // Exit batch edit mode - // cy.get('button').contains('exit batch edit').click() - // }) -}) From 0bb214d7b8179e4f43adc878d95cf479667f98ae Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Fri, 10 Jan 2025 15:40:24 -0500 Subject: [PATCH 04/15] test: added mix settings file and setup steps --- .../cypress/support/mixSetting.ts | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 protocol-designer/cypress/support/mixSetting.ts diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts new file mode 100644 index 00000000000..e70bcbb7b04 --- /dev/null +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -0,0 +1,161 @@ +import { executeUniversalAction, UniversalActions } from './universalActions' +import { isEnumValue } from './utils' + +export enum Actions { + Confirm = 'Confirm', + GoBack = 'Go back', + Edit = 'Edit', + + SelectLabware = 'Select on deck labware', + SelectWells = 'Select wells', + EnterVolume = 'Enter a valid volume to mix', + EnterMixReps = 'Enter number of repetions to mix', + SelectTipHandling = 'Select how/if tips should be picked up for each mix', + +} + +export enum Verifications { + // OnStep1 = 'On Step 1 page.', + // OnStep2 = 'On Step 2 page.', + // FlexSelected = 'Opentrons Flex selected.', + // OT2Selected = 'Opentrons OT-2 selected.', + // NinetySixChannel = '96-Channel option is available.', + // NotNinetySixChannel = '96-Channel option is not available.', + // ProtocolTitleHeader = 'Protocol Title is displayed', + +} + +export enum Content { + Move = 'Move', + Transfer = 'Transfer', + Mix = 'Mix', + Pause = 'Pause', + HeaterShaker = 'Heater-shaker', + Thermocyler = 'Thermocycler', + Pipette = 'Pipette', + Tiprack = 'Tiprack', + Labware = 'Labware', + SelectWells = 'Select wells', + VolumePerWell = 'Volume per well', + MixRepetitions = 'Mix repetitions', + TipHandling = 'Tip handling', + TipDropLocation = 'Tip drop location', + ChooseOption = 'Choose option', + Reservoir = 'Axygen 1 Well Reservoir 90 mL', + WellPlate = 'Opentrons Tough 96 Well Plate 200 µL PCR Full Skirt', +} + +export enum Locators { + Continue = 'button:contains("Continue")', + GoBack = 'button:contains("Go back")', + WellInputField = '[name="wells"]', + Save = 'button:contains("Save")' + // Step1Indicator = 'p:contains("Step 1")', + // Step2Indicator = 'p:contains("Step 2")', + // FlexOption = 'button:contains("Opentrons Flex")', + // OT2Option = 'button:contains("Opentrons OT-2")', + // NinetySixChannel = 'div:contains("96-Channel")', +} + +// export const selectWells = (wells: number): void => { +// cy.get(Locators.WellInputField).click() +// } + +const executeAction = (action: Actions | UniversalActions): void => { + if (isEnumValue([UniversalActions], [action])) { + executeUniversalAction(action as UniversalActions) + return + } + + + + switch (action) { + case Actions.SelectLabware: + cy.contains(Content.ChooseOption).should('be.visible').click() + cy.contains(Content.Reservoir).should('be.visible').click() + break + case Actions.SelectWells: + cy.get(Locators.WellInputField).should('be.visible').click() + cy.get(Locators.Save).click() + break + // case Actions.Confirm: + // cy.contains(Content.Confirm).should('be.visible').click() + // break + // case Actions.GoBack: + // cy.contains(Content.GoBack).should('be.visible').click() + // break + // default: + // throw new Error(`Unrecognized action: ${action as string}`) + } +} + +// const verifyStep = (verification: Verifications): void => { +// switch (verification) { +// case Verifications.OnStep1: +// cy.contains(Content.Step1Title).should('be.visible') +// break +// case Verifications.OnStep2: +// cy.contains(Content.Step2Title).should('be.visible') +// cy.contains(Content.AddPipette).should('be.visible') +// break +// case Verifications.FlexSelected: +// cy.contains(Content.OpentronsFlex).should( +// 'have.css', +// 'background-color', +// 'rgb(0, 108, 250)' +// ) +// break +// case Verifications.OT2Selected: +// cy.contains(Content.OpentronsOT2).should( +// 'have.css', +// 'background-color', +// 'rgb(0, 108, 250)' +// ) +// break +// case Verifications.NinetySixChannel: +// cy.contains(Content.NinetySixChannel).should('be.visible') +// break +// case Verifications.NotNinetySixChannel: +// cy.contains(Content.NinetySixChannel).should('not.exist') +// break +// default: +// throw new Error( +// `Unrecognized verification: ${verification as Verifications}` +// ) +// } +// } + +export const runMixSetup = ( + steps: Array +): void => { + const enumsToCheck = [Actions, Verifications, UniversalActions] + + if (!isEnumValue(enumsToCheck, steps)) { + throw new Error('One or more steps are unrecognized.') + } + + steps.forEach(step => { + if (isEnumValue([Actions], step)) { + executeAction(step as Actions) + // } else if (isEnumValue([Verifications], step)) { + // verifyStep(step as Verifications) + } else if (isEnumValue([UniversalActions], step)) { + executeAction(step as UniversalActions) + } + }) +} + +export const verifyMixSetup = (): void => { + cy.contains(Content.Pipette).should('exist').should('be.visible') + cy.contains(Content.Tiprack).should('exist').should('be.visible') + cy.contains(Content.Labware).should('exist').should('be.visible') + cy.contains(Content.SelectWells).should('exist').should('be.visible') + cy.contains(Content.VolumePerWell).should('exist').should('be.visible') + cy.contains(Content.MixRepetitions).should('exist').should('be.visible') + cy.contains(Content.TipHandling).should('exist').should('be.visible') + cy.contains(Content.TipDropLocation).should('exist').should('be.visible') +} + +export const selectMix = (): void => { + cy.get('button').contains('Mix').click() +} From d1d873243ebc8e2d4658bcfc9212ec5f03908049 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Fri, 10 Jan 2025 15:41:25 -0500 Subject: [PATCH 05/15] test: added mix settings file and import file for set up --- .../cypress/e2e/mixSettings.cy.ts | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 protocol-designer/cypress/e2e/mixSettings.cy.ts diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts new file mode 100644 index 00000000000..5f712a6e4ef --- /dev/null +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -0,0 +1,79 @@ +import '../support/commands.ts'; // Importing the custom commands file +import { + Actions, + selectMix, + Verifications, + verifyMixSetup, + runMixSetup, + Locators, + // selectWells +} from '../support/mixSetting' +import { UniversalActions } from '../support/universalActions' +import { TestFilePath, getTestFile } from '../support/testFiles' +import { + // verifyOldProtocolModal, + verifyImportProtocolPage, +} from '../support/import' + +describe('Redesigned Mixing Steps - Happy Path', () => { + beforeEach(() => { + cy.visit('/') + const protocol = getTestFile(TestFilePath.DoItAllV8) + cy.importProtocol(protocol.path) + verifyImportProtocolPage(protocol) + + // NOTE: vv make this chunk better// + cy.contains("Edit protocol").click() + cy.contains("Protocol steps").click() + cy.get('[id="AddStepButton"]').contains("+ Add Step").click() + cy.verifyOverflowBtn() + selectMix() + verifyMixSetup() + }); + + + it('It should verify the working function of every permutation of mix checkboxes', () => { + const steps: Array = [ + Actions.SelectLabware, + Actions.SelectWells, + + ] + + runMixSetup(steps) + // selectWells(1) + }); +}); + +/* +-make selector for confirming that the protocol was made on an older version << doesn't pop up +-edit protocol -DONE +-select protocol steps -DONE +-click add step -DONE +-validate move, transfer, mix, pause, and any modules are available options -DONE +-select mix +-validate step number followed by mix +-Side Panel Appears on the right +-check that it contains: + -Part 1/2 + -Pipette + -Textbox with selected pipette + -Tip rack + -dropdown with appropriate list of tip rack options + -Labware + -dropdown of all labware + -Choose wells - click + -pop up modal with grid of wells + -click and drag to highlight all + -after selection, the number should update + -click to deselect single well + -after selection, the number should update + -click to reselect single well + -after selection, the number should update + -Volume per well to mix + enter some number + -Tip handling + -check dropdown + -Tip drop location + -will display option with respect to deck configs + +*/ \ No newline at end of file From 7b4bbd6e5229fe9f0ef3b9f3ae71aa6a75489018 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Fri, 10 Jan 2025 15:46:51 -0500 Subject: [PATCH 06/15] test: added content, locators, and chainable object --- protocol-designer/cypress/support/commands.ts | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/protocol-designer/cypress/support/commands.ts b/protocol-designer/cypress/support/commands.ts index 9bd00058c1f..2235dcd4ebc 100644 --- a/protocol-designer/cypress/support/commands.ts +++ b/protocol-designer/cypress/support/commands.ts @@ -1,4 +1,5 @@ import 'cypress-file-upload' + declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace Cypress { @@ -27,11 +28,12 @@ declare global { openDesignPage: () => Cypress.Chainable addStep: (stepName: string) => Cypress.Chainable openSettingsPage: () => Cypress.Chainable - robotSelection: (robotName: string) => Cypress.Chainable verifySettingsPage: () => Cypress.Chainable verifyCreateNewPage: () => Cypress.Chainable togglePreWetTip: () => Cypress.Chainable mixaspirate: () => Cypress.Chainable + clickConfirm: () => Cypress.Chainable + verifyOverflowBtn: () => Cypress.Chainable } } } @@ -49,14 +51,18 @@ export const content = { appSettings: 'App Info', privacy: 'Privacy', shareSessions: 'Share analytics with Opentrons', + move: "Move", + transfer: "Transfer", + mix: "Mix", + pause: "Pause", + heaterShaker: "Heater-shaker", + thermocyler: "Thermocycler", } export const locators = { import: 'Import', createNew: 'Create new', createProtocol: 'Create a protocol', - Flex_Home: 'Opentrons Flex', - OT2_Home: "Opentrons OT-2", editProtocol: 'Edit existing protocol', settingsDataTestid: 'SettingsIconButton', settings: 'Settings', @@ -64,6 +70,7 @@ export const locators = { eula: 'a[href="https://opentrons.com/eula"]', privacyToggle: 'Settings_hotKeys', analyticsToggleTestId: 'analyticsToggle', + confirmButton: 'Confirm', } // General Custom Commands @@ -103,17 +110,22 @@ Cypress.Commands.add('verifyCreateNewHeader', () => { // Home Page Cypress.Commands.add('verifyHomePage', () => { cy.contains(content.welcome) + cy.get(locators.privacyPolicy).should('exist').and('be.visible') + cy.get(locators.eula).should('exist').and('be.visible') + cy.contains(locators.confirmButton).click() cy.contains('button', locators.createProtocol).should('be.visible') cy.contains('label', locators.editProtocol).should('be.visible') cy.getByTestId(locators.settingsDataTestid).should('be.visible') - cy.get(locators.privacyPolicy).should('exist').and('be.visible') - cy.get(locators.eula).should('exist').and('be.visible') }) Cypress.Commands.add('clickCreateNew', () => { cy.contains(locators.createProtocol).click() }) +Cypress.Commands.add('clickConfirm', () => { + cy.contains(locators.confirmButton).click() +}) + // Header Import Cypress.Commands.add('importProtocol', (protocolFilePath: string) => { cy.contains(locators.import).click() @@ -122,21 +134,6 @@ Cypress.Commands.add('importProtocol', (protocolFilePath: string) => { .selectFile(protocolFilePath, { force: true }) }) -Cypress.Commands.add('robotSelection',(robotName:string) =>{ - if (robotName ==='Opentrons OT-2') { - cy.contains('label', locators.OT2_Home ).should('be.visible').click() - - } - else { - // Just checking that the selection modal works - cy.contains('label', locators.OT2_Home ).should('be.visible').click() - cy.contains('label', locators.Flex_Home).should('be.visible').click() - - } - cy.contains('button', "Confirm").should('be.visible').click() - -}) - // Settings Page Actions Cypress.Commands.add('openSettingsPage', () => { cy.getByTestId(locators.settingsDataTestid).click() @@ -154,6 +151,15 @@ Cypress.Commands.add('verifySettingsPage', () => { .should('be.visible') }) +Cypress.Commands.add('verifyOverflowBtn', () => { + cy.contains(content.move).should('exist').should('be.visible') + cy.contains(content.transfer).should('exist').should('be.visible') + cy.contains(content.mix).should('exist').should('be.visible') + cy.contains(content.pause).should('exist').should('be.visible') + cy.contains(content.heaterShaker).should('exist').should('be.visible') + cy.contains(content.thermocyler).should('exist').should('be.visible') +}) + /// ///////////////////////////////////////////////////////////////// // Legacy Code Section // This code is deprecated and should be removed @@ -185,9 +191,7 @@ Cypress.Commands.add('openFilePage', () => { // Pipette Page Actions // -Cypress.Commands.add( - 'choosePipettes', - (leftPipetteSelector, rightPipetteSelector) => { +Cypress.Commands.add('choosePipettes', (leftPipetteSelector, rightPipetteSelector) => { cy.get('[id="PipetteSelect_left"]').click() cy.get(leftPipetteSelector).click() cy.get('[id="PipetteSelect_right"]').click() From 57649223b24c7bfdc57e3c3132e8c60d78bd30ea Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Mon, 13 Jan 2025 11:09:26 -0500 Subject: [PATCH 07/15] fix duplicate confirm locators --- protocol-designer/cypress/support/commands.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/protocol-designer/cypress/support/commands.ts b/protocol-designer/cypress/support/commands.ts index b8089b84c26..3dfc586999c 100644 --- a/protocol-designer/cypress/support/commands.ts +++ b/protocol-designer/cypress/support/commands.ts @@ -73,7 +73,6 @@ export const locators = { privacyToggle: 'Settings_hotKeys', analyticsToggleTestId: 'analyticsToggle', confirm: 'Confirm', - confirmButton: 'Confirm', } // General Custom Commands @@ -115,7 +114,7 @@ Cypress.Commands.add('verifyHomePage', () => { cy.contains(content.welcome) cy.get(locators.privacyPolicy).should('exist').and('be.visible') cy.get(locators.eula).should('exist').and('be.visible') - cy.contains(locators.confirmButton).click() + cy.contains(locators.confirm).click() cy.contains('button', locators.createProtocol).should('be.visible') cy.contains('label', locators.importProtocol).should('be.visible') cy.getByTestId(locators.settingsDataTestid).should('be.visible') @@ -133,7 +132,7 @@ Cypress.Commands.add('closeAnalyticsModal', () => { }) Cypress.Commands.add('clickConfirm', () => { - cy.contains(locators.confirmButton).click() + cy.contains(locators.confirm).click() }) // Header Import From b4679436748457e834ab1fd456735afc3720ad88 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Tue, 14 Jan 2025 16:03:54 -0500 Subject: [PATCH 08/15] refactor so that selecting mix and popout are under actions and verifications --- .../cypress/e2e/mixSettings.cy.ts | 10 +- .../cypress/support/mixSetting.ts | 99 ++++++++----------- 2 files changed, 44 insertions(+), 65 deletions(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index 5f712a6e4ef..469de93ee8e 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -1,12 +1,9 @@ import '../support/commands.ts'; // Importing the custom commands file import { Actions, - selectMix, Verifications, - verifyMixSetup, runMixSetup, Locators, - // selectWells } from '../support/mixSetting' import { UniversalActions } from '../support/universalActions' import { TestFilePath, getTestFile } from '../support/testFiles' @@ -18,6 +15,7 @@ import { describe('Redesigned Mixing Steps - Happy Path', () => { beforeEach(() => { cy.visit('/') + cy.closeAnalyticsModal() const protocol = getTestFile(TestFilePath.DoItAllV8) cy.importProtocol(protocol.path) verifyImportProtocolPage(protocol) @@ -25,15 +23,15 @@ describe('Redesigned Mixing Steps - Happy Path', () => { // NOTE: vv make this chunk better// cy.contains("Edit protocol").click() cy.contains("Protocol steps").click() - cy.get('[id="AddStepButton"]').contains("+ Add Step").click() + cy.get('[id="AddStepButton"]').contains("Add Step").click() cy.verifyOverflowBtn() - selectMix() - verifyMixSetup() }); it('It should verify the working function of every permutation of mix checkboxes', () => { const steps: Array = [ + Actions.SelectMix, + Verifications.MixPopout, Actions.SelectLabware, Actions.SelectWells, diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts index e70bcbb7b04..a21c22adc80 100644 --- a/protocol-designer/cypress/support/mixSetting.ts +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -5,7 +5,7 @@ export enum Actions { Confirm = 'Confirm', GoBack = 'Go back', Edit = 'Edit', - + SelectMix = "Select Mix", SelectLabware = 'Select on deck labware', SelectWells = 'Select wells', EnterVolume = 'Enter a valid volume to mix', @@ -15,13 +15,8 @@ export enum Actions { } export enum Verifications { - // OnStep1 = 'On Step 1 page.', - // OnStep2 = 'On Step 2 page.', - // FlexSelected = 'Opentrons Flex selected.', - // OT2Selected = 'Opentrons OT-2 selected.', - // NinetySixChannel = '96-Channel option is available.', - // NotNinetySixChannel = '96-Channel option is not available.', - // ProtocolTitleHeader = 'Protocol Title is displayed', + MixPopout = 'Verify the the configuration of mix settings', + } @@ -70,11 +65,14 @@ const executeAction = (action: Actions | UniversalActions): void => { switch (action) { + case Actions.SelectMix: + cy.get('button').contains('Mix').click() + break case Actions.SelectLabware: cy.contains(Content.ChooseOption).should('be.visible').click() cy.contains(Content.Reservoir).should('be.visible').click() break - case Actions.SelectWells: + case Actions.SelectWells: cy.get(Locators.WellInputField).should('be.visible').click() cy.get(Locators.Save).click() break @@ -89,41 +87,24 @@ const executeAction = (action: Actions | UniversalActions): void => { } } -// const verifyStep = (verification: Verifications): void => { -// switch (verification) { -// case Verifications.OnStep1: -// cy.contains(Content.Step1Title).should('be.visible') -// break -// case Verifications.OnStep2: -// cy.contains(Content.Step2Title).should('be.visible') -// cy.contains(Content.AddPipette).should('be.visible') -// break -// case Verifications.FlexSelected: -// cy.contains(Content.OpentronsFlex).should( -// 'have.css', -// 'background-color', -// 'rgb(0, 108, 250)' -// ) -// break -// case Verifications.OT2Selected: -// cy.contains(Content.OpentronsOT2).should( -// 'have.css', -// 'background-color', -// 'rgb(0, 108, 250)' -// ) -// break -// case Verifications.NinetySixChannel: -// cy.contains(Content.NinetySixChannel).should('be.visible') -// break -// case Verifications.NotNinetySixChannel: -// cy.contains(Content.NinetySixChannel).should('not.exist') -// break -// default: -// throw new Error( -// `Unrecognized verification: ${verification as Verifications}` -// ) -// } -// } +const verifyStep = (verification: Verifications): void => { + switch (verification) { + case Verifications.MixPopout: + cy.contains(Content.Pipette).should('exist').should('be.visible') + cy.contains(Content.Tiprack).should('exist').should('be.visible') + cy.contains(Content.Labware).should('exist').should('be.visible') + cy.contains(Content.SelectWells).should('exist').should('be.visible') + cy.contains(Content.VolumePerWell).should('exist').should('be.visible') + cy.contains(Content.MixRepetitions).should('exist').should('be.visible') + cy.contains(Content.TipHandling).should('exist').should('be.visible') + cy.contains(Content.TipDropLocation).should('exist').should('be.visible') + break + default: + throw new Error( + `Unrecognized verification: ${verification as Verifications}` + ) + } +} export const runMixSetup = ( steps: Array @@ -137,25 +118,25 @@ export const runMixSetup = ( steps.forEach(step => { if (isEnumValue([Actions], step)) { executeAction(step as Actions) - // } else if (isEnumValue([Verifications], step)) { - // verifyStep(step as Verifications) + } else if (isEnumValue([Verifications], step)) { + verifyStep(step as Verifications) } else if (isEnumValue([UniversalActions], step)) { executeAction(step as UniversalActions) } }) } -export const verifyMixSetup = (): void => { - cy.contains(Content.Pipette).should('exist').should('be.visible') - cy.contains(Content.Tiprack).should('exist').should('be.visible') - cy.contains(Content.Labware).should('exist').should('be.visible') - cy.contains(Content.SelectWells).should('exist').should('be.visible') - cy.contains(Content.VolumePerWell).should('exist').should('be.visible') - cy.contains(Content.MixRepetitions).should('exist').should('be.visible') - cy.contains(Content.TipHandling).should('exist').should('be.visible') - cy.contains(Content.TipDropLocation).should('exist').should('be.visible') -} +// export const verifyMixSetup = (): void => { +// cy.contains(Content.Pipette).should('exist').should('be.visible') +// cy.contains(Content.Tiprack).should('exist').should('be.visible') +// cy.contains(Content.Labware).should('exist').should('be.visible') +// cy.contains(Content.SelectWells).should('exist').should('be.visible') +// cy.contains(Content.VolumePerWell).should('exist').should('be.visible') +// cy.contains(Content.MixRepetitions).should('exist').should('be.visible') +// cy.contains(Content.TipHandling).should('exist').should('be.visible') +// cy.contains(Content.TipDropLocation).should('exist').should('be.visible') +// } -export const selectMix = (): void => { - cy.get('button').contains('Mix').click() -} +// export const selectMix = (): void => { +// cy.get('button').contains('Mix').click() +// } From a755f98ee424d7d1f6fb93b356d9f88266bdfeb2 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Wed, 15 Jan 2025 16:49:32 -0500 Subject: [PATCH 09/15] clean up comments, added content and verifications --- .../cypress/e2e/mixSettings.cy.ts | 20 +++-- .../cypress/support/mixSetting.ts | 77 +++++++++++-------- 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index 469de93ee8e..cf3fabff64d 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -31,14 +31,18 @@ describe('Redesigned Mixing Steps - Happy Path', () => { it('It should verify the working function of every permutation of mix checkboxes', () => { const steps: Array = [ Actions.SelectMix, + UniversalActions.Snapshot, + Verifications.PartOne, Verifications.MixPopout, Actions.SelectLabware, - Actions.SelectWells, + Actions.SelectWellInputField, + Verifications.WellSelectPopout, + UniversalActions.Snapshot, + Actions.Save, ] runMixSetup(steps) - // selectWells(1) }); }); @@ -48,16 +52,16 @@ describe('Redesigned Mixing Steps - Happy Path', () => { -select protocol steps -DONE -click add step -DONE -validate move, transfer, mix, pause, and any modules are available options -DONE --select mix --validate step number followed by mix +-select mix - Done +-validate step number followed by mix - Done -Side Panel Appears on the right -check that it contains: - -Part 1/2 - -Pipette + -Part 1/2 -DONE + -Pipette <<< NOTE: NEED TO THINK ABOUT THIS -Textbox with selected pipette - -Tip rack + -Tip rack <<< NOTE: NEED TO THINK ABOUT THIS -dropdown with appropriate list of tip rack options - -Labware + -Labware - DONE -dropdown of all labware -Choose wells - click -pop up modal with grid of wells diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts index a21c22adc80..4f7bdfdf24a 100644 --- a/protocol-designer/cypress/support/mixSetting.ts +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -3,11 +3,14 @@ import { isEnumValue } from './utils' export enum Actions { Confirm = 'Confirm', + Continue = 'Continue', GoBack = 'Go back', + Back = 'Back', + Save = 'Save', Edit = 'Edit', SelectMix = "Select Mix", SelectLabware = 'Select on deck labware', - SelectWells = 'Select wells', + SelectWellInputField = 'Select wells', EnterVolume = 'Enter a valid volume to mix', EnterMixReps = 'Enter number of repetions to mix', SelectTipHandling = 'Select how/if tips should be picked up for each mix', @@ -16,8 +19,9 @@ export enum Actions { export enum Verifications { MixPopout = 'Verify the the configuration of mix settings', - - + PartOne = 'Verify Part 1, and check continue button for mix set up', + PartTwo = 'Verify Part 2, and check goback and save button for mix set up', + WellSelectPopout = 'validate labware image and available wells', } export enum Content { @@ -38,13 +42,21 @@ export enum Content { ChooseOption = 'Choose option', Reservoir = 'Axygen 1 Well Reservoir 90 mL', WellPlate = 'Opentrons Tough 96 Well Plate 200 µL PCR Full Skirt', + PartOne = 'Part 1 / 2', + PartTwo = 'Part 2 / 2', + WellSelectTitle = 'Select wells using a Flex 1-Channel 1000 μL', + ClickAndDragWellSelect = "Click and drag to select wells", + PipettePreselect = 'Flex 1-Channel 1000 μL', + TiprackPreselect = 'Opentrons Flex 96 Tip Rack 1000 µL', } export enum Locators { Continue = 'button:contains("Continue")', GoBack = 'button:contains("Go back")', + Back = 'button:contains("Back")', WellInputField = '[name="wells"]', - Save = 'button:contains("Save")' + Save = 'button:contains("Save")', + OneWellReservoirImg = '[data-wellname="A1"]', // Step1Indicator = 'p:contains("Step 1")', // Step2Indicator = 'p:contains("Step 2")', // FlexOption = 'button:contains("Opentrons Flex")', @@ -52,9 +64,6 @@ export enum Locators { // NinetySixChannel = 'div:contains("96-Channel")', } -// export const selectWells = (wells: number): void => { -// cy.get(Locators.WellInputField).click() -// } const executeAction = (action: Actions | UniversalActions): void => { if (isEnumValue([UniversalActions], [action])) { @@ -72,26 +81,34 @@ const executeAction = (action: Actions | UniversalActions): void => { cy.contains(Content.ChooseOption).should('be.visible').click() cy.contains(Content.Reservoir).should('be.visible').click() break - case Actions.SelectWells: + case Actions.SelectWellInputField: cy.get(Locators.WellInputField).should('be.visible').click() - cy.get(Locators.Save).click() break - // case Actions.Confirm: - // cy.contains(Content.Confirm).should('be.visible').click() - // break - // case Actions.GoBack: - // cy.contains(Content.GoBack).should('be.visible').click() - // break - // default: - // throw new Error(`Unrecognized action: ${action as string}`) + case Actions.Save: + cy.get(Locators.Save).should('exist').should('be.visible').click() + break + case Actions.Back: + cy.get(Locators.Back).should('exist').should('be.visible').click() + break + case Actions.Continue: + cy.get(Locators.Continue).should('exist').should('be.visible').click() + + default: + throw new Error(`Unrecognized action: ${action as string}`) } } const verifyStep = (verification: Verifications): void => { switch (verification) { + case Verifications.PartOne: + cy.contains(Content.PartOne).should('exist').should('be.visible') + cy.get(Locators.Continue).should('exist').should('be.visible') + break case Verifications.MixPopout: cy.contains(Content.Pipette).should('exist').should('be.visible') + cy.contains(Content.PipettePreselect).should('exist').should('be.visible') cy.contains(Content.Tiprack).should('exist').should('be.visible') + cy.contains(Content.TiprackPreselect).should('exist').should('be.visible') cy.contains(Content.Labware).should('exist').should('be.visible') cy.contains(Content.SelectWells).should('exist').should('be.visible') cy.contains(Content.VolumePerWell).should('exist').should('be.visible') @@ -99,6 +116,18 @@ const verifyStep = (verification: Verifications): void => { cy.contains(Content.TipHandling).should('exist').should('be.visible') cy.contains(Content.TipDropLocation).should('exist').should('be.visible') break + case Verifications.WellSelectPopout: + cy.contains(Content.WellSelectTitle).should('exist').should('be.visible') + cy.contains(Content.ClickAndDragWellSelect).should('exist').should('be.visible') + cy.get(Locators.OneWellReservoirImg).should('exist').should('be.visible') + cy.get(Locators.Save).should('exist').should('be.visible') + cy.get(Locators.Back).should('exist').should('be.visible') + break + case Verifications.PartTwo: + cy.contains(Content.PartTwo).should('exist').should('be.visible') + cy.get(Locators.Back).should('exist').should('be.visible') + cy.get(Locators.Save).should('exist').should('be.visible') + break default: throw new Error( `Unrecognized verification: ${verification as Verifications}` @@ -126,17 +155,3 @@ export const runMixSetup = ( }) } -// export const verifyMixSetup = (): void => { -// cy.contains(Content.Pipette).should('exist').should('be.visible') -// cy.contains(Content.Tiprack).should('exist').should('be.visible') -// cy.contains(Content.Labware).should('exist').should('be.visible') -// cy.contains(Content.SelectWells).should('exist').should('be.visible') -// cy.contains(Content.VolumePerWell).should('exist').should('be.visible') -// cy.contains(Content.MixRepetitions).should('exist').should('be.visible') -// cy.contains(Content.TipHandling).should('exist').should('be.visible') -// cy.contains(Content.TipDropLocation).should('exist').should('be.visible') -// } - -// export const selectMix = (): void => { -// cy.get('button').contains('Mix').click() -// } From 4b18b8159d17c15023506781d5b539da1a4c8665 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Thu, 16 Jan 2025 10:21:08 -0500 Subject: [PATCH 10/15] added input for volume an mix repetitions --- protocol-designer/cypress/e2e/mixSettings.cy.ts | 4 +++- protocol-designer/cypress/support/mixSetting.ts | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index cf3fabff64d..385ed757975 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -19,7 +19,7 @@ describe('Redesigned Mixing Steps - Happy Path', () => { const protocol = getTestFile(TestFilePath.DoItAllV8) cy.importProtocol(protocol.path) verifyImportProtocolPage(protocol) - + // NOTE: vv make this chunk better// cy.contains("Edit protocol").click() cy.contains("Protocol steps").click() @@ -39,6 +39,8 @@ describe('Redesigned Mixing Steps - Happy Path', () => { Verifications.WellSelectPopout, UniversalActions.Snapshot, Actions.Save, + Actions.EnterVolume, + Actions.EnterMixReps ] diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts index 4f7bdfdf24a..9344f451638 100644 --- a/protocol-designer/cypress/support/mixSetting.ts +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -57,6 +57,8 @@ export enum Locators { WellInputField = '[name="wells"]', Save = 'button:contains("Save")', OneWellReservoirImg = '[data-wellname="A1"]', + Volume = '[name="volume"]', + MixReps = '[name="times"]', // Step1Indicator = 'p:contains("Step 1")', // Step2Indicator = 'p:contains("Step 2")', // FlexOption = 'button:contains("Opentrons Flex")', @@ -84,6 +86,11 @@ const executeAction = (action: Actions | UniversalActions): void => { case Actions.SelectWellInputField: cy.get(Locators.WellInputField).should('be.visible').click() break + case Actions.EnterVolume: + cy.get(Locators.Volume).should('exist').type('100') + break + case Actions.EnterMixReps: + cy.get(Locators.MixReps).should('exist').type('5') case Actions.Save: cy.get(Locators.Save).should('exist').should('be.visible').click() break From 044007d8ad27b88d83e88e3df27a41a0251f879c Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Thu, 16 Jan 2025 11:29:32 -0500 Subject: [PATCH 11/15] added select tip handling --- .../cypress/e2e/mixSettings.cy.ts | 5 ++++- .../cypress/support/mixSetting.ts | 21 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index 385ed757975..35a4c2b14ef 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -40,7 +40,10 @@ describe('Redesigned Mixing Steps - Happy Path', () => { UniversalActions.Snapshot, Actions.Save, Actions.EnterVolume, - Actions.EnterMixReps + Actions.EnterMixReps, + Actions.SelectTipHandling, + UniversalActions.Snapshot, + Actions.Continue, ] diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts index 9344f451638..7a4bcc351f1 100644 --- a/protocol-designer/cypress/support/mixSetting.ts +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -48,6 +48,13 @@ export enum Content { ClickAndDragWellSelect = "Click and drag to select wells", PipettePreselect = 'Flex 1-Channel 1000 μL', TiprackPreselect = 'Opentrons Flex 96 Tip Rack 1000 µL', + BeforeEveryAsp = 'Before every aspirate', + OnceAtStartStep = 'Once at the start of step', + PerSourceWell = 'Per source well', + PerDestWell = 'Per destination well', + Never = 'Never', + WasteChute = 'Waste chute', + } export enum Locators { @@ -91,6 +98,15 @@ const executeAction = (action: Actions | UniversalActions): void => { break case Actions.EnterMixReps: cy.get(Locators.MixReps).should('exist').type('5') + break + case Actions.SelectTipHandling: + cy.contains(Content.BeforeEveryAsp).should('exist').should('be.visible').click() + cy.contains(Content.OnceAtStartStep).should('exist').should('be.visible') + cy.contains(Content.PerSourceWell).should('exist').should('be.visible') + cy.contains(Content.PerDestWell).should('exist').should('be.visible') + cy.contains(Content.Never).should('exist').should('be.visible') + cy.contains(Content.OnceAtStartStep).click() + break case Actions.Save: cy.get(Locators.Save).should('exist').should('be.visible').click() break @@ -98,8 +114,8 @@ const executeAction = (action: Actions | UniversalActions): void => { cy.get(Locators.Back).should('exist').should('be.visible').click() break case Actions.Continue: - cy.get(Locators.Continue).should('exist').should('be.visible').click() - + cy.get(Locators.Continue).should('exist').should('be.visible').click({force: true}) + break default: throw new Error(`Unrecognized action: ${action as string}`) } @@ -122,6 +138,7 @@ const verifyStep = (verification: Verifications): void => { cy.contains(Content.MixRepetitions).should('exist').should('be.visible') cy.contains(Content.TipHandling).should('exist').should('be.visible') cy.contains(Content.TipDropLocation).should('exist').should('be.visible') + cy.contains(Content.WasteChute).should('exist').should('be.visible') break case Verifications.WellSelectPopout: cy.contains(Content.WellSelectTitle).should('exist').should('be.visible') From 5ff311363712a368c7f48592dcc03c8ab773e733 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Thu, 16 Jan 2025 11:49:59 -0500 Subject: [PATCH 12/15] refactor verification of part one mix pop out --- .../cypress/e2e/mixSettings.cy.ts | 3 +- .../cypress/support/mixSetting.ts | 29 +++++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index 35a4c2b14ef..a25ffd4bcd9 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -33,7 +33,6 @@ describe('Redesigned Mixing Steps - Happy Path', () => { Actions.SelectMix, UniversalActions.Snapshot, Verifications.PartOne, - Verifications.MixPopout, Actions.SelectLabware, Actions.SelectWellInputField, Verifications.WellSelectPopout, @@ -44,7 +43,7 @@ describe('Redesigned Mixing Steps - Happy Path', () => { Actions.SelectTipHandling, UniversalActions.Snapshot, Actions.Continue, - + Verifications.PartTwo, ] runMixSetup(steps) diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts index 7a4bcc351f1..7b969feda98 100644 --- a/protocol-designer/cypress/support/mixSetting.ts +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -18,9 +18,8 @@ export enum Actions { } export enum Verifications { - MixPopout = 'Verify the the configuration of mix settings', - PartOne = 'Verify Part 1, and check continue button for mix set up', - PartTwo = 'Verify Part 2, and check goback and save button for mix set up', + PartOne = 'Verify Part 1, the configuration of mix settings, and check continue button', + PartTwo = 'Verify Part 2, the configuration of asp/disp settings and check go back and save button', WellSelectPopout = 'validate labware image and available wells', } @@ -125,21 +124,19 @@ const verifyStep = (verification: Verifications): void => { switch (verification) { case Verifications.PartOne: cy.contains(Content.PartOne).should('exist').should('be.visible') + cy.contains(Content.Pipette).should('exist').should('be.visible') + cy.contains(Content.PipettePreselect).should('exist').should('be.visible') + cy.contains(Content.Tiprack).should('exist').should('be.visible') + cy.contains(Content.TiprackPreselect).should('exist').should('be.visible') + cy.contains(Content.Labware).should('exist').should('be.visible') + cy.contains(Content.SelectWells).should('exist').should('be.visible') + cy.contains(Content.VolumePerWell).should('exist').should('be.visible') + cy.contains(Content.MixRepetitions).should('exist').should('be.visible') + cy.contains(Content.TipHandling).should('exist').should('be.visible') + cy.contains(Content.TipDropLocation).should('exist').should('be.visible') + cy.contains(Content.WasteChute).should('exist').should('be.visible') cy.get(Locators.Continue).should('exist').should('be.visible') break - case Verifications.MixPopout: - cy.contains(Content.Pipette).should('exist').should('be.visible') - cy.contains(Content.PipettePreselect).should('exist').should('be.visible') - cy.contains(Content.Tiprack).should('exist').should('be.visible') - cy.contains(Content.TiprackPreselect).should('exist').should('be.visible') - cy.contains(Content.Labware).should('exist').should('be.visible') - cy.contains(Content.SelectWells).should('exist').should('be.visible') - cy.contains(Content.VolumePerWell).should('exist').should('be.visible') - cy.contains(Content.MixRepetitions).should('exist').should('be.visible') - cy.contains(Content.TipHandling).should('exist').should('be.visible') - cy.contains(Content.TipDropLocation).should('exist').should('be.visible') - cy.contains(Content.WasteChute).should('exist').should('be.visible') - break case Verifications.WellSelectPopout: cy.contains(Content.WellSelectTitle).should('exist').should('be.visible') cy.contains(Content.ClickAndDragWellSelect).should('exist').should('be.visible') From 43e18a1b4a7c4a720108f1afd994f040c3679404 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Thu, 16 Jan 2025 12:38:34 -0500 Subject: [PATCH 13/15] added verifications for part 2 of mix for asp and disp --- .../cypress/e2e/mixSettings.cy.ts | 7 ++- .../cypress/support/mixSetting.ts | 43 ++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index a25ffd4bcd9..007036c8733 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -43,7 +43,10 @@ describe('Redesigned Mixing Steps - Happy Path', () => { Actions.SelectTipHandling, UniversalActions.Snapshot, Actions.Continue, - Verifications.PartTwo, + Verifications.PartTwoAsp, + Actions.Dispense, + Verifications.PartTwoDisp, + ] runMixSetup(steps) @@ -51,6 +54,8 @@ describe('Redesigned Mixing Steps - Happy Path', () => { }); /* +NEED TO ADD RENAME + -make selector for confirming that the protocol was made on an older version << doesn't pop up -edit protocol -DONE -select protocol steps -DONE diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts index 7b969feda98..13c090e9a19 100644 --- a/protocol-designer/cypress/support/mixSetting.ts +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -14,12 +14,15 @@ export enum Actions { EnterVolume = 'Enter a valid volume to mix', EnterMixReps = 'Enter number of repetions to mix', SelectTipHandling = 'Select how/if tips should be picked up for each mix', + Aspirate = 'Select aspirate settings', + Dispense = 'Select dispnse settings', } export enum Verifications { PartOne = 'Verify Part 1, the configuration of mix settings, and check continue button', - PartTwo = 'Verify Part 2, the configuration of asp/disp settings and check go back and save button', + PartTwoAsp = 'Verify Part 2, the configuration of asp settings and check go back and save button', + PartTwoDisp = 'Verify Part 2, the configuration of disp settings and check go back and save button', WellSelectPopout = 'validate labware image and available wells', } @@ -53,6 +56,15 @@ export enum Content { PerDestWell = 'Per destination well', Never = 'Never', WasteChute = 'Waste chute', + AspFlowRate = 'Aspirate flow rate', + AspWellOrder = 'Aspirate well order', + MixTipPosition = 'Mix tip position', + AdvancedPipSettings = 'Advanced pipetting settings', + Delay = 'Delay', + DelayDuration = 'Delay Duration', + DispFlowRate = "Dispense flow rate", + Blowout = 'Blowout', + TouchTip = 'Touch tip' } @@ -65,6 +77,8 @@ export enum Locators { OneWellReservoirImg = '[data-wellname="A1"]', Volume = '[name="volume"]', MixReps = '[name="times"]', + Aspirate = 'button:contains("Aspirate")', + Dispense = 'button:contains("Dispense")', // Step1Indicator = 'p:contains("Step 1")', // Step2Indicator = 'p:contains("Step 2")', // FlexOption = 'button:contains("Opentrons Flex")', @@ -106,6 +120,12 @@ const executeAction = (action: Actions | UniversalActions): void => { cy.contains(Content.Never).should('exist').should('be.visible') cy.contains(Content.OnceAtStartStep).click() break + case Actions.Aspirate: + cy.get(Locators.Aspirate).should('exist').should('be.visible').click() + break + case Actions.Dispense: + cy.get(Locators.Dispense).should('exist').should('be.visible').click() + break case Actions.Save: cy.get(Locators.Save).should('exist').should('be.visible').click() break @@ -124,6 +144,7 @@ const verifyStep = (verification: Verifications): void => { switch (verification) { case Verifications.PartOne: cy.contains(Content.PartOne).should('exist').should('be.visible') + cy.contains(Content.Mix).should('exist').should('be.visible') cy.contains(Content.Pipette).should('exist').should('be.visible') cy.contains(Content.PipettePreselect).should('exist').should('be.visible') cy.contains(Content.Tiprack).should('exist').should('be.visible') @@ -144,10 +165,28 @@ const verifyStep = (verification: Verifications): void => { cy.get(Locators.Save).should('exist').should('be.visible') cy.get(Locators.Back).should('exist').should('be.visible') break - case Verifications.PartTwo: + case Verifications.PartTwoAsp: cy.contains(Content.PartTwo).should('exist').should('be.visible') + cy.contains(Content.Mix).should('exist').should('be.visible') + cy.get(Locators.Aspirate).should('exist').should('be.visible') + cy.contains(Content.AspFlowRate).should('exist').should('be.visible') + cy.contains(Content.AspWellOrder).should('exist').should('be.visible') + cy.contains(Content.MixTipPosition).should('exist').should('be.visible') + cy.contains(Content.AdvancedPipSettings).should('exist').should('be.visible') + cy.contains(Content.Delay).should('exist').should('be.visible') cy.get(Locators.Back).should('exist').should('be.visible') cy.get(Locators.Save).should('exist').should('be.visible') + break + case Verifications.PartTwoDisp: + cy.contains(Content.PartTwo).should('exist').should('be.visible') + cy.contains(Content.Mix).should('exist').should('be.visible') + cy.get(Locators.Dispense).should('exist').should('be.visible') + cy.contains(Content.DispFlowRate).should('exist').should('be.visible') + cy.contains(Content.AdvancedPipSettings).should('exist').should('be.visible') + cy.contains(Content.Delay).should('exist').should('be.visible') + cy.contains(Content.Blowout).should('exist').should('be.visible') + cy.contains(Content.TouchTip).should('exist').should('be.visible') + break default: throw new Error( From e08d71f60dcf3eeca054aa7cbf97bcb72a3c7a87 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Fri, 17 Jan 2025 10:00:11 -0500 Subject: [PATCH 14/15] remove unnecessary comments --- .../cypress/e2e/mixSettings.cy.ts | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index 007036c8733..bbd4587d2b1 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -55,36 +55,4 @@ describe('Redesigned Mixing Steps - Happy Path', () => { /* NEED TO ADD RENAME - --make selector for confirming that the protocol was made on an older version << doesn't pop up --edit protocol -DONE --select protocol steps -DONE --click add step -DONE --validate move, transfer, mix, pause, and any modules are available options -DONE --select mix - Done --validate step number followed by mix - Done --Side Panel Appears on the right --check that it contains: - -Part 1/2 -DONE - -Pipette <<< NOTE: NEED TO THINK ABOUT THIS - -Textbox with selected pipette - -Tip rack <<< NOTE: NEED TO THINK ABOUT THIS - -dropdown with appropriate list of tip rack options - -Labware - DONE - -dropdown of all labware - -Choose wells - click - -pop up modal with grid of wells - -click and drag to highlight all - -after selection, the number should update - -click to deselect single well - -after selection, the number should update - -click to reselect single well - -after selection, the number should update - -Volume per well to mix - enter some number - -Tip handling - -check dropdown - -Tip drop location - -will display option with respect to deck configs - */ \ No newline at end of file From a42308ca809c4a7389dbc423fd7bd20bbf5dacc9 Mon Sep 17 00:00:00 2001 From: Sara Kowalski Date: Fri, 17 Jan 2025 17:05:05 -0500 Subject: [PATCH 15/15] added aspiration setting verifications --- .../cypress/e2e/mixSettings.cy.ts | 9 +- .../cypress/support/mixSetting.ts | 125 ++++++++++++------ 2 files changed, 91 insertions(+), 43 deletions(-) diff --git a/protocol-designer/cypress/e2e/mixSettings.cy.ts b/protocol-designer/cypress/e2e/mixSettings.cy.ts index bbd4587d2b1..85252d762b2 100644 --- a/protocol-designer/cypress/e2e/mixSettings.cy.ts +++ b/protocol-designer/cypress/e2e/mixSettings.cy.ts @@ -3,7 +3,6 @@ import { Actions, Verifications, runMixSetup, - Locators, } from '../support/mixSetting' import { UniversalActions } from '../support/universalActions' import { TestFilePath, getTestFile } from '../support/testFiles' @@ -44,12 +43,16 @@ describe('Redesigned Mixing Steps - Happy Path', () => { UniversalActions.Snapshot, Actions.Continue, Verifications.PartTwoAsp, - Actions.Dispense, - Verifications.PartTwoDisp, + Actions.AspirateFlowRate, + Actions.AspWellOrder, + Verifications.AspWellOrder, + // Actions.Dispense, + // Verifications.PartTwoDisp, ] runMixSetup(steps) + // cy.contains('Primary order').closest('div') }); }); diff --git a/protocol-designer/cypress/support/mixSetting.ts b/protocol-designer/cypress/support/mixSetting.ts index 13c090e9a19..80fe00fd2d9 100644 --- a/protocol-designer/cypress/support/mixSetting.ts +++ b/protocol-designer/cypress/support/mixSetting.ts @@ -1,3 +1,4 @@ +import { contains } from 'cypress/types/jquery' import { executeUniversalAction, UniversalActions } from './universalActions' import { isEnumValue } from './utils' @@ -14,8 +15,10 @@ export enum Actions { EnterVolume = 'Enter a valid volume to mix', EnterMixReps = 'Enter number of repetions to mix', SelectTipHandling = 'Select how/if tips should be picked up for each mix', - Aspirate = 'Select aspirate settings', + AspirateFlowRate = 'Select aspirate settings', Dispense = 'Select dispnse settings', + AspWellOrder = 'Open well aspirate well order pop out', + EditWellOrder = 'Edit well order selects', } @@ -23,7 +26,9 @@ export enum Verifications { PartOne = 'Verify Part 1, the configuration of mix settings, and check continue button', PartTwoAsp = 'Verify Part 2, the configuration of asp settings and check go back and save button', PartTwoDisp = 'Verify Part 2, the configuration of disp settings and check go back and save button', - WellSelectPopout = 'validate labware image and available wells', + WellSelectPopout = 'Verify labware image and available wells', + AspWellOrder = 'Verify pop out for well order during aspirate', + AspMixTipPos = 'Verify pop out for mix tip position durin aspirate', } export enum Content { @@ -64,8 +69,18 @@ export enum Content { DelayDuration = 'Delay Duration', DispFlowRate = "Dispense flow rate", Blowout = 'Blowout', - TouchTip = 'Touch tip' - + TouchTip = 'Touch tip', + TopBottomLeRi = 'Top to bottom, Left to right', + EditWellOrder = 'Edit well order', + WellOrderDescrip = 'Change how the robot moves from well to well.', + PrimaryOrder = 'Primary order', + TopToBottom = 'Top to bottom', + BottomToTop = 'Bottom to top', + LeftToRight = 'Left to right', + RightToLeft = 'Right to left', + Then = 'then', + SecondaryOrder = 'Secondary order', + Cancel = 'Cancel', } export enum Locators { @@ -79,11 +94,11 @@ export enum Locators { MixReps = '[name="times"]', Aspirate = 'button:contains("Aspirate")', Dispense = 'button:contains("Dispense")', - // Step1Indicator = 'p:contains("Step 1")', - // Step2Indicator = 'p:contains("Step 2")', - // FlexOption = 'button:contains("Opentrons Flex")', - // OT2Option = 'button:contains("Opentrons OT-2")', - // NinetySixChannel = 'div:contains("96-Channel")', + AspFlowRateInput = '[name="aspirate_flowRate"]', + AspWellOrder = '[class="Flex-sc-1qhp8l7-0 ListButton___StyledFlex-sc-1lmhs3v-0 bToGfF bdMeyp"]', + ResetToDefault = 'button:contains("Reset to default")', + PrimaryOrderDropdown = 'div[tabindex="0"].sc-bqWxrE jKLbYH iFjNDq', + CancelWellOrder = '[class="SecondaryButton-sc-1opt1t9-0 kjpcRL"]', } @@ -120,12 +135,20 @@ const executeAction = (action: Actions | UniversalActions): void => { cy.contains(Content.Never).should('exist').should('be.visible') cy.contains(Content.OnceAtStartStep).click() break - case Actions.Aspirate: + case Actions.AspirateFlowRate: cy.get(Locators.Aspirate).should('exist').should('be.visible').click() + cy.get(Locators.AspFlowRateInput).should('exist') + cy.get(Locators.AspFlowRateInput).type('{selectAll}, {backspace}, 100') + break + case Actions.AspWellOrder: + cy.contains(Content.TopBottomLeRi).should('exist').should('be.visible') + cy.get(Locators.AspWellOrder).click() break case Actions.Dispense: cy.get(Locators.Dispense).should('exist').should('be.visible').click() break + // case Actions.FlowRateWarning: + // break case Actions.Save: cy.get(Locators.Save).should('exist').should('be.visible').click() break @@ -158,36 +181,58 @@ const verifyStep = (verification: Verifications): void => { cy.contains(Content.WasteChute).should('exist').should('be.visible') cy.get(Locators.Continue).should('exist').should('be.visible') break - case Verifications.WellSelectPopout: - cy.contains(Content.WellSelectTitle).should('exist').should('be.visible') - cy.contains(Content.ClickAndDragWellSelect).should('exist').should('be.visible') - cy.get(Locators.OneWellReservoirImg).should('exist').should('be.visible') - cy.get(Locators.Save).should('exist').should('be.visible') - cy.get(Locators.Back).should('exist').should('be.visible') - break - case Verifications.PartTwoAsp: - cy.contains(Content.PartTwo).should('exist').should('be.visible') - cy.contains(Content.Mix).should('exist').should('be.visible') - cy.get(Locators.Aspirate).should('exist').should('be.visible') - cy.contains(Content.AspFlowRate).should('exist').should('be.visible') - cy.contains(Content.AspWellOrder).should('exist').should('be.visible') - cy.contains(Content.MixTipPosition).should('exist').should('be.visible') - cy.contains(Content.AdvancedPipSettings).should('exist').should('be.visible') - cy.contains(Content.Delay).should('exist').should('be.visible') - cy.get(Locators.Back).should('exist').should('be.visible') - cy.get(Locators.Save).should('exist').should('be.visible') - break - case Verifications.PartTwoDisp: - cy.contains(Content.PartTwo).should('exist').should('be.visible') - cy.contains(Content.Mix).should('exist').should('be.visible') - cy.get(Locators.Dispense).should('exist').should('be.visible') - cy.contains(Content.DispFlowRate).should('exist').should('be.visible') - cy.contains(Content.AdvancedPipSettings).should('exist').should('be.visible') - cy.contains(Content.Delay).should('exist').should('be.visible') - cy.contains(Content.Blowout).should('exist').should('be.visible') - cy.contains(Content.TouchTip).should('exist').should('be.visible') - - break + case Verifications.WellSelectPopout: + cy.contains(Content.WellSelectTitle).should('exist').should('be.visible') + cy.contains(Content.ClickAndDragWellSelect).should('exist').should('be.visible') + cy.get(Locators.OneWellReservoirImg).should('exist').should('be.visible') + cy.get(Locators.Save).should('exist').should('be.visible') + cy.get(Locators.Back).should('exist').should('be.visible') + break + case Verifications.PartTwoAsp: + cy.contains(Content.PartTwo).should('exist').should('be.visible') + cy.contains(Content.Mix).should('exist').should('be.visible') + cy.get(Locators.Aspirate).should('exist').should('be.visible') + cy.contains(Content.AspFlowRate).should('exist').should('be.visible') + cy.contains(Content.AspWellOrder).should('exist').should('be.visible') + cy.contains(Content.MixTipPosition).should('exist').should('be.visible') + cy.contains(Content.AdvancedPipSettings).should('exist').should('be.visible') + cy.contains(Content.Delay).should('exist').should('be.visible') + cy.get(Locators.Back).should('exist').should('be.visible') + cy.get(Locators.Save).should('exist').should('be.visible') + break + case Verifications.PartTwoDisp: + cy.contains(Content.PartTwo).should('exist').should('be.visible') + cy.contains(Content.Mix).should('exist').should('be.visible') + cy.get(Locators.Dispense).should('exist').should('be.visible') + cy.contains(Content.DispFlowRate).should('exist').should('be.visible') + cy.contains(Content.AdvancedPipSettings).should('exist').should('be.visible') + cy.contains(Content.Delay).should('exist').should('be.visible') + cy.contains(Content.Blowout).should('exist').should('be.visible') + cy.contains(Content.TouchTip).should('exist').should('be.visible') + break + case Verifications.AspWellOrder: + cy.contains(Content.EditWellOrder).should('exist').should('be.visible') + cy.contains(Content.WellOrderDescrip).should('exist').should('be.visible') + cy.contains(Content.PrimaryOrder).should('exist').should('be.visible') + cy.contains(Content.TopToBottom).should('exist').should('be.visible').click() + cy.contains(Content.BottomToTop).should('exist').should('be.visible') + cy.contains(Content.LeftToRight).should('exist').should('be.visible') + cy.contains(Content.RightToLeft).should('exist').should('be.visible') + cy.contains(Content.BottomToTop).should('exist').should('be.visible').click() + cy.contains(Content.Then).should('exist').should('be.visible') + cy.contains(Content.SecondaryOrder).should('exist').should('be.visible') + cy.contains(Content.LeftToRight).should('exist').should('be.visible').click() + cy.contains(Content.RightToLeft).should('exist').should('be.visible').click() + cy.get(Locators.ResetToDefault).click() + cy.contains(Content.TopToBottom).should('exist').should('be.visible') + cy.contains(Content.LeftToRight).should('exist').should('be.visible') + cy.get(Locators.CancelWellOrder).should('exist').should('be.visible') + cy.get(Locators.Save).should('exist').should('be.visible') + break + // case Verifications.MixTipPos: + // break + // case Verifications.FlowRateRangeWarning: + // break default: throw new Error( `Unrecognized verification: ${verification as Verifications}`