From 7c54444f468c6bd03a636ccc901a382c0b2bd131 Mon Sep 17 00:00:00 2001 From: Praveen Asokan Date: Tue, 9 Apr 2024 09:56:51 +0100 Subject: [PATCH] test: update e2e --- .cypress-cucumber-preprocessorrc.json | 9 + cypress/e2e/component_tests/muon_card.feature | 23 + .../component_tests/muon_card/muon_card.js | 71 +++ cypress/e2e/component_tests/muon_cta.feature | 29 ++ .../e2e/component_tests/muon_cta/muon_cta.js | 128 +++++ .../e2e/component_tests/muon_detail.feature | 13 + .../muon_detail/muon_detail.js | 42 ++ cypress/e2e/component_tests/muon_form.feature | 31 ++ .../component_tests/muon_form/muon_form.js | 82 ++++ cypress/e2e/component_tests/muon_icon.feature | 11 + .../component_tests/muon_icon/muon_icon.js | 10 + .../e2e/component_tests/muon_image.feature | 12 + .../component_tests/muon_image/muon_image.js | 29 ++ .../e2e/component_tests/muon_inputter.feature | 156 ++++++ .../muon_inputter/muon_inputter.js | 454 ++++++++++++++++++ .../e2e/example_app_tests/cake_ember.feature | 56 +++ .../cake_ember/cake_ember.js | 176 +++++++ cypress/support/e2e.js | 32 ++ 18 files changed, 1364 insertions(+) create mode 100644 .cypress-cucumber-preprocessorrc.json create mode 100644 cypress/e2e/component_tests/muon_card.feature create mode 100644 cypress/e2e/component_tests/muon_card/muon_card.js create mode 100644 cypress/e2e/component_tests/muon_cta.feature create mode 100755 cypress/e2e/component_tests/muon_cta/muon_cta.js create mode 100644 cypress/e2e/component_tests/muon_detail.feature create mode 100644 cypress/e2e/component_tests/muon_detail/muon_detail.js create mode 100644 cypress/e2e/component_tests/muon_form.feature create mode 100644 cypress/e2e/component_tests/muon_form/muon_form.js create mode 100644 cypress/e2e/component_tests/muon_icon.feature create mode 100644 cypress/e2e/component_tests/muon_icon/muon_icon.js create mode 100644 cypress/e2e/component_tests/muon_image.feature create mode 100644 cypress/e2e/component_tests/muon_image/muon_image.js create mode 100644 cypress/e2e/component_tests/muon_inputter.feature create mode 100644 cypress/e2e/component_tests/muon_inputter/muon_inputter.js create mode 100644 cypress/e2e/example_app_tests/cake_ember.feature create mode 100644 cypress/e2e/example_app_tests/cake_ember/cake_ember.js create mode 100644 cypress/support/e2e.js diff --git a/.cypress-cucumber-preprocessorrc.json b/.cypress-cucumber-preprocessorrc.json new file mode 100644 index 00000000..f04645af --- /dev/null +++ b/.cypress-cucumber-preprocessorrc.json @@ -0,0 +1,9 @@ +{ + "nonGlobalStepDefinitions": true, + "stepDefinitions": [ + "cypress/**/*.{js,ts}" + ], + "html": { + "enabled": true + } +} \ No newline at end of file diff --git a/cypress/e2e/component_tests/muon_card.feature b/cypress/e2e/component_tests/muon_card.feature new file mode 100644 index 00000000..e1e12b80 --- /dev/null +++ b/cypress/e2e/component_tests/muon_card.feature @@ -0,0 +1,23 @@ +@card +Feature: muon card component + + Scenario Outline: muon card component + + Given Launch the '' component '' type in the browser + When the user changes the content in the '' card + Then Validate the shadow dom and elements in '' type + + Examples: + |component |type | + |muon-card |standard | + |muon-card |standard-with-image | + + Scenario Outline: muon card with cta component + + Given Launch the '' component '' type in the browser + When the user changes the content in the '' card + Then Validate the shadow dom and elements in '' type + + Examples: + |component |type | + |muon-card |standard-with-cta | diff --git a/cypress/e2e/component_tests/muon_card/muon_card.js b/cypress/e2e/component_tests/muon_card/muon_card.js new file mode 100644 index 00000000..5d62c146 --- /dev/null +++ b/cypress/e2e/component_tests/muon_card/muon_card.js @@ -0,0 +1,71 @@ + +import { Given, When, Then} from '@badeball/cypress-cucumber-preprocessor'; +import {cardElement} from '../../../support/web_elements'; + +Given('Launch the {string} component {string} type in the browser', (component, type) => { + cy.launchComponent(component, type); + cy.wait(3000) +}); + +When('the user changes the content in the {string} card', (type) => { + + cy.document().then((doc)=>{ + + const cardComponent = doc.querySelector('muon-card'); + + cardComponent.querySelector('[slot="header"]').innerText = "Heading of the card component"; + cardComponent.querySelector('p').innerText = "test the paragraph in card"; + + let footerSlot = cardComponent.querySelector('[slot="footer"]') + let CTA = footerSlot.querySelector('muon-cta') + + if (type === 'standard-with-cta'){ + CTA.innerText = "Nucleus, the best"; + CTA.setAttribute('href','#!') + + } else { + footerSlot.innerText = "Nucleus, the best"; + } + + + }) + +}); + +Then('Validate the shadow dom and elements in {string} type', (type) => { + + + cy.document().then((doc)=>{ + + cy.get('muon-card').shadow().find('.card').as('cardShadow') + + cy.get('@cardShadow').should('exist'); + cy.get('@cardShadow').find('.body').should('exist'); + + const cardComponent = doc.querySelector('muon-card'); + + const header = cardComponent.shadowRoot.querySelector(cardElement.header).querySelector('slot[name="header"]').assignedNodes()[0].innerText; + const paragraph = cardComponent.shadowRoot.querySelector(cardElement.content).querySelector('slot').assignedNodes()[2].innerText; + const footer = cardComponent.shadowRoot.querySelector(cardElement.footer).querySelector('slot[name="footer"]').assignedNodes()[0].innerText; + + assert.equal("Heading of the card component", header,'Header is different in shadowroot slot'); + assert.equal("test the paragraph in card", paragraph,'Paragraph is different in shadowroot slot'); + assert.equal("Nucleus, the best", footer,'Footer text is different in shadowroot slot'); + + if (type.includes('image')){ + + //alias + cy.get('muon-card').shadow().find('.card').find('.media').as('cardMedia') + cy.get('@cardMedia').find('card-image').as('cardImage') + cy.get('@cardImage').find('div.image').find('img').as('tagImage') + + + cy.get('@cardMedia').should('exist'); + cy.get('@cardImage').invoke('attr','src').should('eq','https://blog.nucleus.design/vanilla-first/vanilla-ice-cream-cone.jpg'); + cy.get('@cardImage').invoke('attr','alt').should('be.empty'); + cy.get('@tagImage').invoke('attr','src').should('eq','https://blog.nucleus.design/vanilla-first/vanilla-ice-cream-cone.jpg'); + cy.get('@tagImage').invoke('attr','class').should('eq','blur-out image-lazy'); + + } + }) +}) diff --git a/cypress/e2e/component_tests/muon_cta.feature b/cypress/e2e/component_tests/muon_cta.feature new file mode 100644 index 00000000..2a436028 --- /dev/null +++ b/cypress/e2e/component_tests/muon_cta.feature @@ -0,0 +1,29 @@ +@cta +Feature: muon CTA component + + Scenario Outline: muon CTA component + + Given Launch the '' component '' type in the browser + Then Validate the elements and attributes in the '' component + + Examples: + |component |type | + |muon-cta |standard | + |muon-cta |disabled | + |muon-cta |loading | + |muon-cta |hidden | + |muon-cta |standard-link | + |muon-cta |disabled-link | + |muon-cta |loading-link | + |muon-cta |standard-button | + |muon-cta |disabled-button | + |muon-cta |loading-button | + |muon-cta |standard-within-link | + |muon-cta |disabled-within-link | + |muon-cta |loading-within-link | + |muon-cta |standard-within-button| + |muon-cta |disabled-within-button| + |muon-cta |loading-within-button | + |muon-cta |standard-form | + |muon-cta |disabled-form | + |muon-cta |loading-form | \ No newline at end of file diff --git a/cypress/e2e/component_tests/muon_cta/muon_cta.js b/cypress/e2e/component_tests/muon_cta/muon_cta.js new file mode 100755 index 00000000..9ac53f97 --- /dev/null +++ b/cypress/e2e/component_tests/muon_cta/muon_cta.js @@ -0,0 +1,128 @@ + +import {Then} from '@badeball/cypress-cucumber-preprocessor'; + + +Then('Validate the elements and attributes in the {string} component', (type) => { + + // eslint-disable-next-line default-case + switch (type) { + + case 'standard': + cy.get('muon-cta').invoke('attr', 'role').should('eq', 'button'); + cy.validateCTAShadow('div', 'cta standard', 'arrow-right'); + break; + + case 'disabled': + cy.get('muon-cta').invoke('attr', 'disabled').should('exist'); + cy.validateCTAShadow('div', 'cta standard disabled', 'arrow-right'); + break; + + case 'loading': + cy.get('muon-cta').invoke('attr', 'loading').should('exist'); + cy.validateCTAShadow('div', 'cta standard loading', 'spinner'); + break; + + case 'hidden': + cy.get('muon-cta').should('have.css', 'display', 'inline-block'); + cy.get('muon-cta').invoke('attr', 'role').should('eq', 'button'); + cy.validateCTAShadow('div', 'cta standard', 'arrow-right'); + + break; + + case 'standard-link': + case 'disabled-link': + cy.get('muon-cta').shadow().find('a').then((shadowLink=>{ + cy.wrap(shadowLink).invoke('attr', 'href').should('exist'); + })) + + if(type === 'disabled-link'){ + cy.get('muon-cta').invoke('attr', 'disabled').should('exist'); + } + + let shadowClass = (type === 'standard-link') ? 'cta standard' : 'cta standard disabled' + cy.validateCTAShadow('a', shadowClass, 'arrow-right'); + break; + + case 'loading-link': + cy.get('muon-cta').then((shadowLink=>{ + cy.wrap(shadowLink).shadow().find('a').invoke('attr', 'href').should('exist'); + cy.wrap(shadowLink).invoke('attr', 'tabindex').should('eq', '-1'); + })) + cy.loadingShadowSpan('div'); + cy.validateCTAShadow('a', 'cta standard loading', 'spinner'); + break; + + case 'standard-button': + cy.validateCTAShadow('button', 'cta standard', 'arrow-right'); + break; + + case 'disabled-button': + cy.get('muon-cta').invoke('attr', 'aria-disabled').should('eq', 'true'); + cy.get('muon-cta').invoke('attr', 'disabled').should('exist'); + cy.validateCTAShadow('button', 'cta standard disabled', 'arrow-right'); + break; + + case 'loading-button': + cy.get('muon-cta').invoke('attr', 'loading').should('exist'); + cy.loadingShadowSpan('div'); + cy.validateCTAShadow('button', 'cta standard loading', 'spinner'); + break; + + case 'standard-within-link': + cy.get('a').invoke('attr', 'href').should('exist'); + cy.validateCTAShadow('div', 'cta standard', 'arrow-right'); + break; + + case 'disabled-within-link': + cy.get('a').get('muon-cta').then(ctaLink=>{ + cy.wrap(ctaLink).invoke('attr', 'aria-disabled').should('eq', 'true'); + }) + cy.get('a').invoke('attr', 'href').should('exist'); + cy.validateCTAShadow('div', 'cta standard disabled', 'arrow-right'); + break; + + case 'loading-within-link': + cy.get('a').invoke('attr', 'href').should('exist'); + cy.loadingShadowSpan('a'); + cy.validateCTAShadow('div', 'cta standard loading', 'spinner'); + break; + + case 'standard-within-button': + cy.get('button').get('muon-cta').should('exist'); + cy.validateCTAShadow('div', 'cta standard', 'arrow-right'); + break; + + case 'disabled-within-button': + cy.get('button').then((ctaButton=>{ + cy.wrap(ctaButton).invoke('attr', 'disabled').should('exist'); + cy.wrap(ctaButton).get('muon-cta').invoke('attr', 'disabled').should('exist'); + cy.wrap(ctaButton).get('muon-cta').invoke('attr', 'aria-disabled').should('eq', 'true'); + })) + cy.get('button').invoke('attr', 'disabled').should('exist'); + cy.validateCTAShadow('div', 'cta standard disabled', 'arrow-right'); + break; + + case 'loading-within-button': + cy.get('button').find('muon-cta').invoke('attr', 'loading').should('exist'); + cy.validateCTAShadow('div', 'cta standard loading', 'spinner'); + break; + + case 'standard-form': + cy.get('form').get('muon-cta').should('exist'); + cy.validateCTAShadow('button', 'cta standard', 'arrow-right'); + break; + + case 'disabled-form': + cy.get('form').get('muon-cta').invoke('attr', 'disabled').should('exist'); + cy.validateCTAShadow('button', 'cta standard disabled', 'arrow-right'); + break; + + case 'loading-form': + cy.get('form').get('muon-cta').invoke('attr', 'loading').should('exist'); + cy.loadingShadowSpan('form'); + cy.validateCTAShadow('button', 'cta standard loading', 'spinner'); + break; + + } + +}); diff --git a/cypress/e2e/component_tests/muon_detail.feature b/cypress/e2e/component_tests/muon_detail.feature new file mode 100644 index 00000000..49932978 --- /dev/null +++ b/cypress/e2e/component_tests/muon_detail.feature @@ -0,0 +1,13 @@ +@detail +Feature: muon detail component + + Scenario Outline: muon detail component + + Given Launch the '' component '' type in the browser + When User clicks to expand the detail + Then Validate the attributes and elements in the '' detail component + + Examples: + |component |type | + |muon-detail |standard | + |muon-detail |with-icon | \ No newline at end of file diff --git a/cypress/e2e/component_tests/muon_detail/muon_detail.js b/cypress/e2e/component_tests/muon_detail/muon_detail.js new file mode 100644 index 00000000..23ad5647 --- /dev/null +++ b/cypress/e2e/component_tests/muon_detail/muon_detail.js @@ -0,0 +1,42 @@ +/* eslint-disable no-undef */ +import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'; + + +When('User clicks to expand the detail', () => { + cy.get('muon-detail').find('div[slot="heading"]').click(); +}); + +Then('Validate the attributes and elements in the {string} detail component', (type) => { + + cy.get('muon-detail').shadow().find('details').as('details') + cy.get('@details').find('summary.heading').find('detail-icon.toggle').as('toggle') + + if (type === 'with-icon') { + cy.get('muon-detail').invoke('attr', 'icon').should('eq', 'dot-circle'); + cy.get('@details').invoke('attr', 'class').should('eq', ' details toggle-end has-icon '); + cy.get('@details').find('summary.heading').find('detail-icon.icon').invoke('attr', 'name').should('eq', 'dot-circle'); + } else { + cy.get('@details').invoke('attr', 'class').should('eq', ' details toggle-end '); + } + + //validate the component when open + cy.get('muon-detail').invoke('attr', 'open').should('exist'); + cy.get('@details').invoke('attr', 'open').should('exist'); + cy.get('@toggle').invoke('attr', 'name').should('eq', 'chevron-circle-up'); + + //Heading and paragraph validation + cy.fixture('data').then((detail)=>{ + cy.get('muon-detail').find('div[slot="heading"]').should('have.text', detail.detail_heading); + cy.get('muon-detail').invoke('text').should('contains', detail.detail_content); + }); + + + //Click the expander to close the content + cy.get('muon-detail').find('div[slot="heading"]').click(); + cy.get('muon-detail').invoke('attr', 'open').should('not.exist'); + cy.get('@details').invoke('attr', 'open').should('not.exist'); + cy.get('@toggle').invoke('attr', 'name').should('eq', 'chevron-circle-down'); + + cy.get('muon-detail').children().invoke('attr', 'slot').should('eq', 'heading'); + +}); diff --git a/cypress/e2e/component_tests/muon_form.feature b/cypress/e2e/component_tests/muon_form.feature new file mode 100644 index 00000000..286deb15 --- /dev/null +++ b/cypress/e2e/component_tests/muon_form.feature @@ -0,0 +1,31 @@ +@form +Feature: muon form component + + Scenario Outline: muon form standard component with valid + + Given Launch the muon-form component standard type in the browser + When User enters values in all fields + Then User clicks on submit and validate the '' form + And User resets the form + + Examples: + |validation | + |valid | + + Scenario Outline: muon form standard component with invalid + + Given Launch the muon-form component standard type in the browser + When User clicks on submit and validate the '' form + And User resets the form + + Examples: + |validation | + |invalid | + + Scenario: muon form standard component with focusing error field and enter submission + + Given Launch the muon-form component standard type in the browser + When User enter the value only in first field and press enter + Then Validate that the remaining fields are highlighted with error message + + diff --git a/cypress/e2e/component_tests/muon_form/muon_form.js b/cypress/e2e/component_tests/muon_form/muon_form.js new file mode 100644 index 00000000..ff772f71 --- /dev/null +++ b/cypress/e2e/component_tests/muon_form/muon_form.js @@ -0,0 +1,82 @@ +/* eslint-disable no-undef */ +import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'; +import {formElement} from '../../../support/web_elements'; + +Given('Launch the muon-form component standard type in the browser', () => { + cy.launchComponent('muon-form', 'standard'); +}); + +When('User enters values in all fields', () => { + cy.get('form').invoke('attr','novalidate').should('eq','true') + cy.enterFormValue({useremail: 'nuke@mail.com',userid: '6thgh',username: 'test nuke',checkinput: ['a','b'],title: 'Value two',DOB: '31101994'}) +}); + +When('User enter the value only in first field and press enter', () => { + + cy.get('muon-form').get('form').then((form)=>{ + cy.wrap(form).find(formElement.username).find('input[type="text"]').clear() + cy.wrap(form).find(formElement.username).find('input[type="text"]').type('brand') + cy.wrap(form).find(formElement.username).invoke('attr','value').should('eq','brand') + cy.wrap(form).find(formElement.dob).find('input[type="text"]').type('02/02/2023') + cy.wrap(form).find(formElement.useremail).find('input').type('test@123.com') + cy.wrap(form).find('input[id="user-id"]').type('trip08{enter}') + }) +}); + + +Then('User clicks on submit and validate the {string} form', (validation) => { + + + cy.get('muon-form').get('form').then((form)=>{ + cy.wrap(form).find('muon-cta[type="submit"]').click() + + if(validation==='valid'){ + cy.wrap(form).find(formElement.title).shadow().find('div.validation').should('not.exist') + cy.wrap(form).find(formElement.username).shadow().find('div.validation').should('not.exist') + cy.wrap(form).find(formElement.useremail).shadow().find('div.validation').should('not.exist') + cy.wrap(form).find(formElement.dob).shadow().find('div.validation').should('not.exist') + cy.wrap(form).find(formElement.inputterCheckbox).shadow().find('div.validation').should('not.exist') + }else{ + cy.wrap(form).find(formElement.useremail).find('input').should('have.css', 'outline-color', 'rgb(178, 139, 255)') + cy.wrap(form).find(formElement.title).find('select').select('Please select') + cy.wrap(form).find(formElement.username).find('input[type="text"]').clear(); + cy.wrap(form).find(formElement.dob).find('input[type="text"]').type('02/02/2023') + cy.wrap(form).find(formElement.inputterCheckbox).find(formElement.inputCheckbox).uncheck(); + + // validation message part + cy.wrap(form).find(formElement.title).shadow().find('div.validation').find('div.message').should('contain','This field is required.') + cy.wrap(form).find(formElement.username).shadow().find('div.validation').find('div.message').should('contain','This field is required.') + cy.wrap(form).find(formElement.useremail).shadow().find('div.validation').find('div.message').should('contain','This field is required.') + cy.wrap(form).find(formElement.dob).shadow().find('div.validation').find('div.message').should('contain','Date must be on or before 31/12/2022.') + cy.wrap(form).find(formElement.inputterCheckbox).shadow().find('div.validation') + .find('div.message').should('contain','This field is required.') + } + + }) + +}); + +Then('Validate that the remaining fields are highlighted with error message', () => { + + cy.get('muon-form').get('form').then((form)=>{ + cy.wrap(form).find(formElement.dob).shadow().find('div.validation').find('div.message').should('contain','Date must be on or before 31/12/2022.') + cy.wrap(form).find(formElement.dob).find('input').should('have.css', 'outline-color', 'rgb(178, 139, 255)') + }) + +}); + +Then('User resets the form', () => { + + cy.get('muon-form').get('form').then((form)=>{ + cy.wrap(form).find('input[type="reset"]').click() + + cy.wrap(form).find(formElement.username).invoke('attr','value').should('eq','text') + cy.wrap(form).find(formElement.useremail).invoke('attr','value').should('eq','') + cy.wrap(form).find(formElement.inputterCheckbox).invoke('attr','value').should('eq','b') + + cy.wrap(form).find(formElement.username).shadow().find('div.validation').should('not.exist') + cy.wrap(form).find(formElement.useremail).shadow().find('div.validation').should('not.exist') + cy.wrap(form).find(formElement.inputterCheckbox).shadow().find('div.validation').should('not.exist') + }) + +}); \ No newline at end of file diff --git a/cypress/e2e/component_tests/muon_icon.feature b/cypress/e2e/component_tests/muon_icon.feature new file mode 100644 index 00000000..e19e3c54 --- /dev/null +++ b/cypress/e2e/component_tests/muon_icon.feature @@ -0,0 +1,11 @@ +@icon +Feature: muon icon component + + Scenario Outline: muon icon standard component + + Given Launch the '' component '' type in the browser + Then Validate the svg element + + Examples: + |component |type | + |muon-icon |standard | \ No newline at end of file diff --git a/cypress/e2e/component_tests/muon_icon/muon_icon.js b/cypress/e2e/component_tests/muon_icon/muon_icon.js new file mode 100644 index 00000000..f281d2be --- /dev/null +++ b/cypress/e2e/component_tests/muon_icon/muon_icon.js @@ -0,0 +1,10 @@ +/* eslint-disable no-undef */ +import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'; + + +Then('Validate the svg element', () => { + cy.get('muon-icon') + .shadow() + .find('svg') + .should('be.visible'); +}); diff --git a/cypress/e2e/component_tests/muon_image.feature b/cypress/e2e/component_tests/muon_image.feature new file mode 100644 index 00000000..aa528707 --- /dev/null +++ b/cypress/e2e/component_tests/muon_image.feature @@ -0,0 +1,12 @@ +@image +Feature: muon image component + + Scenario Outline: muon image component + + Given Launch the '' component '' type in the browser + Then Validate the image src and elements in '' type + + Examples: + |component |type | + |muon-image |standard | + |muon-image |background | \ No newline at end of file diff --git a/cypress/e2e/component_tests/muon_image/muon_image.js b/cypress/e2e/component_tests/muon_image/muon_image.js new file mode 100644 index 00000000..2309f7c1 --- /dev/null +++ b/cypress/e2e/component_tests/muon_image/muon_image.js @@ -0,0 +1,29 @@ +/* eslint-disable no-undef */ +{/* */} + +import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'; +import {imageElement} from '../../../support/web_elements'; + +Then('Validate the image src and elements in {string} type', (type) => { + + const placeholder = '(src).thumb.48.48.png'; + + cy.get('muon-image').invoke('attr', 'placeholder').should('eq', placeholder); + + if (type === 'standard') { + cy.get('muon-image').shadow().find(imageElement.imageSelector).find('img').as('image'); + + cy.get('muon-image').invoke('attr', 'src').should('eq', 'https://blog.nucleus.design/vanilla-first/vanilla-ice-cream-cone.jpg'); + cy.get('@image').invoke('attr', 'src').should('eq', 'https://blog.nucleus.design/vanilla-first/vanilla-ice-cream-cone.jpg.thumb.48.48.png'); + cy.get('@image').invoke('attr', 'class').should('eq', 'image-lazy blur'); + + } else { + cy.get('muon-image').shadow().find(imageElement.backgroundImageSelector).find('div').as('backgroundImage') + + cy.get('muon-image').invoke('attr', 'src').should('eq', 'https://blog.nucleus.design/multi-branding/Multibrand.jpg'); + cy.get('muon-image').invoke('attr', 'background').should('exist'); + cy.get('@backgroundImage').should('have.css', 'background-image').and('include', 'https://blog.nucleus.design/multi-branding/Multibrand.jpg'); + cy.get('@backgroundImage').invoke('attr', 'class').should('eq', 'image-holder blur'); + } + +}); diff --git a/cypress/e2e/component_tests/muon_inputter.feature b/cypress/e2e/component_tests/muon_inputter.feature new file mode 100644 index 00000000..ab6b898c --- /dev/null +++ b/cypress/e2e/component_tests/muon_inputter.feature @@ -0,0 +1,156 @@ +@inputter +Feature: muon inputter component + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + When User enter the input + Then Validate the elements and validation message + + Examples: + |component |type | + |muon-inputter |text | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes in inputter '' type + And Validate the helper and tip details in '' field + And Enter the email in the inputter and validate the message + + Examples: + |component |type | + |muon-inputter |email | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes in inputter '' type + And Validate the helper and tip details in '' field + And Enter the telephone number in the inputter and validate the message + + Examples: + |component |type | + |muon-inputter |tel | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in '' type + And Enter the input in '' and validate the value + + Examples: + |component |type | + |muon-inputter |search | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in '' type + And Enter the input in '' and validate the value + + Examples: + |component |type | + |muon-inputter |password | + + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in textarea type + And Enter the input in textarea and validate the value + + Examples: + |component |type | + |muon-inputter |textarea | + + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes in inputter '' type + + Examples: + |component |type | + |muon-inputter |disabled | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in number type + And Enter the input in number and validate the value + + Examples: + |component |type | + |muon-inputter |number | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in select type + And Select the option and validate the value + + Examples: + |component |type | + |muon-inputter |select | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in mask type + And Enter the input in the mask and validate the value + + Examples: + |component |type | + |muon-inputter |mask | + + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the elements in '' type + And Enter the input in the separator and validate the value + + Examples: + |component |type | + |muon-inputter |separator | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the elements in '' type + And Enter the input in the date-mask and validate the value and message + + Examples: + |component |type | + |muon-inputter |date-mask | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in date type + And Enter the input in the date and validate the value and message + + Examples: + |component |type | + |muon-inputter |date | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in radio type + And Select the radio options and validate the value + + Examples: + |component |type | + |muon-inputter |radio | + + Scenario Outline: muon inputter type + + Given Launch the '' component '' type in the browser + Then Validate the attributes and elements in checkbox type + And Select the checkbox and validate the value + + Examples: + |component |type | + |muon-inputter |checkbox | diff --git a/cypress/e2e/component_tests/muon_inputter/muon_inputter.js b/cypress/e2e/component_tests/muon_inputter/muon_inputter.js new file mode 100644 index 00000000..c21de2d2 --- /dev/null +++ b/cypress/e2e/component_tests/muon_inputter/muon_inputter.js @@ -0,0 +1,454 @@ +/* eslint-disable no-undef */ + +import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'; +import {inputElement} from '../../../support/web_elements'; + + +When('User enter the input', () => { + cy.clearInput(); + cy.enterValue('Cypress test'); +}); + +Then('Validate the elements and validation message', () => { + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'Cypress test'); + cy.wrap(inputter).invoke('attr', 'helper').should('eq', 'Useful information to help populate this field.'); + cy.wrap(inputter).find('label').should('have.text', 'Text'); + cy.wrap(inputter).find('input').invoke('attr', 'placeholder').should('eq', 'e.g. Placeholder'); + cy.wrap(inputter).shadow().find(inputElement.inputSelectorText).find(inputElement.helperSelector).should('have.text', 'Useful information to help populate this field.'); + cy.wrap(inputter).invoke('attr', 'validation').should('eq', '["isRequired"]'); + }) + cy.clearInput(); + cy.validateMessage('This field is required.'); +}); + +When('User clicks the {string} and validate the value attriute', (type) => { + + if (type === 'radio') { + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find('input[value="electricity"]').click(); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'electricity'); + + cy.wrap(inputter).find('input[value="gas"]').click(); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'gas'); + }) + + } else { + + + cy.get('muon-inputter').then((inputter)=>{ + + //check only one checkbox + cy.wrap(inputter).find('input[value="electricity"]').click(); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'electricity'); + + // check the next check box + cy.wrap(inputter).find('input[value="gas"]').click(); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'gas,electricity'); + + //Uncheck both the checkbox and validate the message + cy.wrap(inputter).find('input[value="gas"]').click(); + cy.wrap(inputter).find('input[value="electricity"]').click(); + cy.wrap(inputter).invoke('attr', 'value').should('eq', ''); + cy.wrap(inputter).shadow().find(inputElement.validationSelector).contains('This field is required.'); + + }) + } + +}); + +Then('Validate the elements and attriutes in the {string} inputter', (type) => { + cy.get('muon-inputter').find('input[value="electricity"]').invoke('attr', 'type').should('eq', type); + cy.get('muon-inputter').find('input[value="gas"]').invoke('attr', 'type').should('eq', type); +}); + +Then('Validate the attributes in inputter {string} type', (type) => { + + if (type === 'email') { + cy.validateAttribute('email', 'Enter email ID', '["isRequired","isEmail"]', 'inputter type-email autocomplete-email'); + cy.get('muon-inputter').shadow().find(inputElement.inputSelectorEmail).find(inputElement.inputWrapper).should('exist'); + } else if (type === 'tel') { + cy.validateAttribute('tel','Enter telephone No', '["isRequired"]', 'inputter type-tel autocomplete-tel'); + cy.get('muon-inputter').shadow().find(inputElement.inputSelectorTel).find(inputElement.inputWrapper).should('exist'); + } else { + cy.validateAttribute('text', 'Disabled Text', '["isRequired"]', 'inputter has-disabled type-text'); + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find('input').invoke('attr', 'disabled').should('exist'); + cy.wrap(inputter).find('input').invoke('css', 'color').should('eq', 'rgb(176, 176, 176)'); + cy.wrap(inputter).shadow().find(inputElement.disabledInputSelector).find(inputElement.inputWrapper).should('exist'); + }) + + + } + +}); + +Then('Validate the helper and tip details in {string} field', (type) => { + let className = (type==='email')?'inputter type-email autocomplete-email':'inputter type-tel autocomplete-tel' + cy.validateHelper('How can we help you?', className); +}); + +Then('Enter the email in the inputter and validate the message', () => { + + if (Cypress.isBrowser('firefox')) { + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test@', `Your email does not look right. Please enter an email address..`, true); + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test1@t.', `Your email does not look right. Please enter an email address..`, true); + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test', `Your email does not look right. Please enter an email address..`, true); + } else { + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test@', `Your email does not look right. Please enter a part following '@'. 'test@' is incomplete.`,true); + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test1@t.', `Your email does not look right. '.' is used at a wrong position in 't.'.`, true); + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test', `Your email does not look right. Please include an '@' in the email address. 'test' is missing an '@'.`, true); + } + + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test123@g', `Your email does not look right.`, true); + cy.enterAndValidateMessage('inputter type-email autocomplete-email','test@g.com', false, true); + cy.enterAndValidateMessage('inputter type-email autocomplete-email','mbappe123@bk.in', false, true); +}); + +Then('Enter the telephone number in the inputter and validate the message', () => { + cy.enterAndValidateMessage('inputter type-tel autocomplete-tel','07404537288', false, true); +}); + +Then('Validate the attributes and elements in {string} type', (type) => { + + let text; + + if (type === 'search') { + text = 'Search'; + cy.get('muon-inputter').shadow().find(inputElement.searchSelector).find(inputElement.inputWrapper).find('inputter-icon').invoke('attr', 'name').should('eq', type); + } else { + text = 'Password'; + cy.get('muon-inputter').shadow().find(inputElement.passwordSelector).find(inputElement.inputWrapper).should('exist'); + } + + cy.get('muon-inputter').find(inputElement.label).should('have.text', text); + cy.get('muon-inputter').find('input').invoke('attr', 'type').should('eq', type); + +}); + +Then('Enter the input in {string} and validate the value', () => { + cy.enterValue('muon-test'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', 'muon-test'); + cy.clearInput(); + cy.get('muon-inputter').invoke('attr', 'value').should('be.empty'); + +}); + +Then('Validate the attributes and elements in textarea type', () => { + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'validation').should('eq', '["isRequired"]'); + cy.wrap(inputter).find(inputElement.label).should('have.text', 'Textarea'); + cy.wrap(inputter).find('textarea').invoke('attr', 'placeholder').should('eq', 'e.g. Provide information'); + + cy.wrap(inputter).shadow().find(inputElement.inputSelector).then((inputSelec)=>{ + cy.wrap(inputSelec).find(inputElement.inputWrapper).should('exist'); + cy.wrap(inputSelec).find('slot[name="label"]').should('exist'); + }) + + }) + + +}); + +Then('Enter the input in textarea and validate the value', () => { + + const input = 'Cypress is an automation framework to automate web pages and components.'; + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find('textarea').type(input); + cy.wrap(inputter).invoke('attr', 'value').should('eq', input); + cy.wrap(inputter).find('textarea').clear(); + cy.wrap(inputter).invoke('attr', 'value').should('eq', ''); + }) + + cy.validateMessage('This field is required.'); +}); + +Then('Validate the attributes and elements in number type', () => { + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find(inputElement.label).should('have.text', 'Number'); + cy.wrap(inputter).find('input').invoke('attr', 'type').should('eq', 'number'); + + cy.wrap(inputter).shadow().find(inputElement.numberSelector).then((inputSelect)=>{ + cy.wrap(inputSelect).find(inputElement.inputWrapper).should('exist'); + cy.wrap(inputSelect).find(inputElement.labelSlot).should('exist'); + }) + }) + +}); + +Then('Enter the input in number and validate the value', () => { + + cy.enterValue('545657654'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', '545657654'); + cy.clearInput(); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', ''); + + cy.enterValue('muonpack'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', ''); + +}); + +Then('Validate the attributes and elements in select type', () => { + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'validation').should('eq', '["isRequired"]'); + cy.wrap(inputter).find(inputElement.label).should('have.text', 'Select'); + cy.wrap(inputter).find('select').then((select)=>{ + cy.wrap(select).invoke('attr', 'name').should('eq', 'select'); + cy.wrap(select).select('Please select').should('have.value', ''); + cy.wrap(select).select('Value one').should('have.value', 'value-01'); + cy.wrap(select).select('Value two').should('have.value', 'value-02'); + cy.wrap(select).select('Value three').should('have.value', 'value-03'); + cy.wrap(select).select('Value four').should('have.value', 'value-04'); + }) + }) + +}); + +Then('Select the option and validate the value', () => { + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find('select').select('Value one'); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'value-01'); + cy.wrap(inputter).find('select').select('Value two'); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'value-02'); + cy.wrap(inputter).find('select').select('Value three'); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'value-03'); + cy.wrap(inputter).find('select').select('Value four'); + cy.wrap(inputter).invoke('attr', 'value').should('eq', 'value-04'); + cy.wrap(inputter).find('select').select('Please select'); + cy.wrap(inputter).invoke('attr', 'value').should('eq', ''); + }) + + cy.validateMessage('This field is required.'); +}); + +Then('Validate the attributes and elements in mask type', () => { + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'mask').should('eq', '000000'); + cy.wrap(inputter).find('input').invoke('attr', 'maxlength').should('eq', '6'); + cy.wrap(inputter).find(inputElement.label).should('have.text', 'Mask'); + cy.wrap(inputter).find('input').invoke('attr', 'type').should('eq', 'text'); + + cy.wrap(inputter).shadow().find(inputElement.maskSelector).then((mask)=>{ + cy.wrap(mask).find(inputElement.inputWrapper).find(inputElement.inputMaskSelector).invoke('attr', 'aria-hidden').should('eq', 'true'); + cy.wrap(mask).find(inputElement.inputWrapper).find(inputElement.inputMaskSelector).should('have.text', '000000'); + cy.wrap(mask).find(inputElement.labelSlot).should('exist'); + }) + }) + + +}); + +Then('Enter the input in the mask and validate the value', () => { + + cy.enterValue('test32'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', 'test32'); + cy.clearInput(); + cy.enterValue('messi10'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', 'messi1'); +}); + +Then('Validate the elements in {string} type', (type) => { + + let text; let mask; let separator; let maxlength; + + if (type === 'separator') { + text = 'Separator'; + mask = ' - - '; + separator = '-'; + maxlength = '8'; + } else { + text = 'Date Mask'; + mask = 'dd/mm/yyyy'; + separator = '/'; + maxlength = '10'; + cy.get('muon-inputter').invoke('attr', 'validation').should('eq', `["isRequired","minDate(\\"01/01/2022\\")"]`); + } + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'separator').should('eq', separator); + cy.wrap(inputter).invoke('attr', 'mask').should('eq', mask); + cy.wrap(inputter).find('input').invoke('attr', 'maxlength').should('eq', maxlength); + cy.wrap(inputter).find(inputElement.label).should('have.text', text); + cy.wrap(inputter).find('input').invoke('attr', 'type').should('eq', 'text'); + + cy.wrap(inputter).shadow().find(inputElement.maskSelector).then((maskShadow)=>{ + cy.wrap(maskShadow).find(inputElement.inputWrapper).find(inputElement.inputMaskSelector).then((maskSelector)=>{ + cy.wrap(maskSelector).invoke('attr', 'aria-hidden').should('eq', 'true'); + cy.wrap(maskSelector).should('have.text', mask); + }) + cy.wrap(maskShadow).find(inputElement.labelSlot).should('exist'); + }); + }) +}) + +Then('Enter the input in the separator and validate the value', () => { + + cy.enterValue('test32'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', 'te-st-32'); + cy.clearInput(); + cy.enterValue('30031'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', '30-03-1'); + cy.clearInput(); + cy.enterValue('3003145'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', '30-03-14'); + +}); + +Then('Enter the input in the date-mask and validate the value and message', () => { + + cy.enterValue('05012022'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', '05/01/2022'); + cy.clearInput(); + cy.enterValue('01012022'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', '01/01/2022'); + cy.clearInput(); + cy.enterValue('31122021'); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', '31/12/2021'); + cy.get('muon-inputter').shadow().find(inputElement.validationSelector).find(inputElement.messageSelector).contains('Date must be on or after 01/01/2022.'); + + cy.clearInput(); + cy.validateMessage('This field is required.'); +}); + +Then('Validate the attributes and elements in date type', () => { + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'validation').should('eq', `["isRequired","minDate(\\"01/01/2022\\")"]`); + cy.wrap(inputter).find(inputElement.label).should('have.text', 'Date'); + cy.wrap(inputter).find('input').invoke('attr', 'type').should('eq', 'date'); + + cy.wrap(inputter).shadow().find(inputElement.dateSelector).then((date)=>{ + cy.wrap(date).find(inputElement.inputWrapper).should('exist'); + cy.wrap(date).find(inputElement.labelSlot).should('exist'); + cy.wrap(date).find(inputElement.inputWrapper).find('inputter-icon').invoke('attr', 'name').should('eq', 'calendar'); + }) + + }) + +}); + +Then('Enter the input in the date and validate the value and message', () => { + + // date within range + cy.validateDate('2022-02-01'); + + // date out of range + cy.validateDate('2021-12-01'); + cy.validateMessage('Date must be on or after 01/01/2022.'); + +}); + +Then('Validate the attributes and elements in radio type', () => { + + const heading = 'Which choice would you prefer?'; + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'heading').should('eq', heading); + cy.wrap(inputter).invoke('attr', 'validation').should('eq', '["isRequired"]'); + + cy.wrap(inputter).find('input').invoke('attr', 'type').should('eq', 'radio'); + cy.wrap(inputter).find('input[id="radio-01"]').should('be.checked'); + cy.wrap(inputter).find('input[id="radio-04"]').should('be.disabled'); + cy.wrap(inputter).find('input[id="radio-04"]').invoke('attr', 'disabled').should('exist'); + + }) + + + // validating all radio inputs and its text + for (let i = 0; i < 4; i++) { + const text = ['Choice A', 'Choice B', 'Choice C', 'Choice D']; + const value = ['a', 'b', 'c', 'd']; + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find(`input[id="radio-0${i + 1}"]`).should('exist'); + cy.wrap(inputter).find(`label[for="radio-0${i + 1}"]`).should('have.text', text[i]); + cy.wrap(inputter).find(`input[id="radio-0${i + 1}"]`).invoke('attr', 'value').should('eq', value[i]); + + // shadow dom elements + cy.get('muon-inputter').shadow().find(inputElement.radioSelector).then((radio)=>{ + cy.wrap(radio).find(inputElement.headingSpan).should('have.text', heading); + cy.wrap(radio).find(inputElement.inputWrapper).should('exist'); + }) + }) + } + cy.validateHelper('How can we help you?', 'inputter radio has-disabled'); + +}); + +Then('Select the radio options and validate the value', () => { + + const value = ['a', 'b', 'c']; + + for (let i = 3; i > 1; i--) { + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find(`label[for="radio-0${i}"]`).click(); + cy.wrap(inputter).find(`input[id="radio-0${i}"]`).should('be.checked'); + cy.wrap(inputter).invoke('attr', 'value').should('eq', value[i - 1]); + }) + } +}); + +Then('Validate the attributes and elements in checkbox type', () => { + + const heading = 'What options do you like?'; + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).invoke('attr', 'heading').should('eq', heading); + cy.wrap(inputter).invoke('attr', 'validation').should('eq', '["isRequired"]'); + + cy.wrap(inputter).find('input').invoke('attr', 'type').should('eq', 'checkbox'); + cy.wrap(inputter).find('input[id="checkbox-01"]').should('be.checked'); + cy.wrap(inputter).find('input[id="checkbox-04"]').should('be.disabled'); + cy.wrap(inputter).find('input[id="checkbox-04"]').invoke('attr', 'disabled').should('exist'); + + }) + + // validating all radio inputs and its text + for (let i = 0; i < 4; i++) { + const text = ['Option A', 'Option B', 'Option C', 'Option D']; + const value = ['a', 'b', 'c', 'd']; + + cy.get('muon-inputter').then((inputter)=>{ + cy.wrap(inputter).find(`input[id="checkbox-0${i + 1}"]`).should('exist'); + cy.wrap(inputter).find(`label[for="checkbox-0${i + 1}"]`).should('have.text', text[i]); + cy.wrap(inputter).find(`input[id="checkbox-0${i + 1}"]`).invoke('attr', 'value').should('eq', value[i]); + + + // shadow dom elements + cy.wrap(inputter).shadow().find(inputElement.checkboxSelector).then((checkbox)=>{ + cy.wrap(checkbox).find(inputElement.headingSpan).should('have.text', heading); + cy.wrap(checkbox).find(inputElement.inputWrapper).should('exist'); + }) + }) + } + + cy.validateHelper('How can we help you?', 'inputter checkbox has-disabled'); + +}); + +Then('Select the checkbox and validate the value', () => { + + cy.get('muon-inputter').as('inputter') + + cy.get('@inputter').find('[type="checkbox"]').as('checkbox') + cy.get('@inputter').invoke('attr', 'value').as('attValue') + + cy.get('@checkbox').check(['b', 'c'], { force: true }); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', 'a,b,c'); + + cy.get('@checkbox').uncheck(['a', 'b'], { force: true }); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', 'c'); + + cy.get('@checkbox').uncheck('c', { force: true }); + cy.get('muon-inputter').invoke('attr', 'value').should('eq', ''); + + cy.validateMessage('This field is required.'); +}); \ No newline at end of file diff --git a/cypress/e2e/example_app_tests/cake_ember.feature b/cypress/e2e/example_app_tests/cake_ember.feature new file mode 100644 index 00000000..9bbad220 --- /dev/null +++ b/cypress/e2e/example_app_tests/cake_ember.feature @@ -0,0 +1,56 @@ +@cake +Feature: Order the cake in ember app + + # This scenario is just to run percy + @percy + Scenario Outline: Order cake with own configuration + + Given Launch the ember cake website + When the user views the welcome page and clicks on make your cake + And select the shape of the cake as '' + And enter the tiers count + And select the flavour sponge as '' + And select the icing colour as '' + And select the filling from the list + And select the occasion as '' + And select the decoration from the list + And enter the personal and delivery details + Then validate '' '' '' details in the comfirmation page + + Examples: + |shape |flavour |colour |occasion | + |Round |Vanilla |Black |Birthday | + + Scenario Outline: Order cake with own configuration + + Given Launch the ember cake website + When the user views the welcome page and clicks on make your cake + And select the shape of the cake as '' + And enter the tiers count + And select the flavour sponge as '' + And select the icing colour as '' + And select the filling from the list + And select the occasion as '' + And select the decoration from the list + And enter the personal and delivery details + Then validate '' '' '' details in the comfirmation page + + Examples: + |shape |flavour |colour |occasion | + |Square |Chocolate|Purple |Wedding | + |Triangle |Ginger |Pink |Funeral | + |Round |Vanilla |Blue |Anniversary| + |Square |Chocolate|Green |Other | + |Triangle |Ginger |Brown | | + + Scenario Outline: Validate the navigation to previous page + + Given Launch the ember cake website + When the user views the welcome page and clicks on make your cake + And select the shape of the cake as '' + Then click CTA and navigate to previous page + + Examples: + |shape | + |Round | + \ No newline at end of file diff --git a/cypress/e2e/example_app_tests/cake_ember/cake_ember.js b/cypress/e2e/example_app_tests/cake_ember/cake_ember.js new file mode 100644 index 00000000..094afd7b --- /dev/null +++ b/cypress/e2e/example_app_tests/cake_ember/cake_ember.js @@ -0,0 +1,176 @@ +/* eslint-disable no-undef */ +{/* */} + +import { Given, When, Then} from '@badeball/cypress-cucumber-preprocessor'; +import {inputElement} from '../../../support/web_elements'; + +Given('Launch the ember cake website', () => { + cy.visit('http://localhost:4200/'); +}); + +When('the user views the welcome page and clicks on make your cake', () => { + cy.title().should('eq','Ember App'); + cy.get('main').find('h1').should('have.text','Cake Config v 1.0') + cy.percySnapshot('Home page') + cy.get('a').find('muon-cta').should('have.text','Make your Cake!').click(); +}); + +Then('select the shape of the cake as {string}', (shape) => { + cy.title().should('eq','Choose a shape | Configurator'); + cy.get('form').find('muon-inputter').invoke('attr', 'heading').should('eq', 'What shaped cake do you want?'); + cy.get('form').find('muon-inputter').invoke('attr', 'value').should('be.empty'); + cy.get('form').find('muon-inputter').find('input[type="radio"]').check(shape,{force: true}); + cy.get('form').find('muon-inputter').invoke('attr', 'value').should('eq',shape); + cy.percySnapshot('Shape selection of cake') + cy.get('form').find('muon-cta').should('have.text','Next').click(); +}); + +Then('enter the tiers count', () => { + cy.title().should('eq','Pick number of tiers | Configurator'); + cy.get('muon-inputter').find(inputElement.label).should('have.text','Tiers') + cy.validateHelper('How many tiers would you like?', 'inputter type-number'); + cy.get('muon-inputter').find('input').invoke('attr','type').should('eq','number'); + + if(Cypress.isBrowser('firefox')) { + cy.enterAndValidateMessage('inputter type-number','4','Please select a value that is no more than 3.', true); + } else { + cy.enterAndValidateMessage('inputter type-number','4','Value must be less than or equal to 3.', true); + } + + cy.enterAndValidateMessage('inputter type-number','3',false); + cy.percySnapshot('Tiers count') + cy.clickCTA('Next'); +}); + +Then('select the flavour sponge as {string}', (flavour) => { + cy.title().should('eq','PickSponge | Configurator'); + cy.checkRadioInput('What flavour sponge?',flavour) + cy.percySnapshot('Cake flavour') + cy.clickCTA('Next'); +}); + +Then('select the icing colour as {string}', (colour) => { + cy.title().should('eq','Pick your cake colour | Configurator'); + cy.checkRadioInput('What colour icing?',colour) + cy.percySnapshot('Cake icing colour') + cy.clickCTA('Next'); +}); + +Then('select the filling from the list', (s) => { + cy.title().should('eq','PickFilling | Configurator'); + cy.selectCheckbox('What fillings?',['Buttercream','Strawberry jam','Cream cheese','Lemon mascarpone']); + cy.percySnapshot('Cake fillings') + cy.clickCTA('Next'); +}); + +Then('select the occasion as {string}', (occasion) => { + cy.title().should('eq','PickOccasion | Configurator'); + cy.get('muon-inputter').find('input').invoke('attr','placeholder').should('eq', 'e.g. Graduation'); + + if (!occasion){ + cy.get('muon-inputter').find('select').select('Select your occasion'); + cy.get('muon-inputter').first().find('label').should('have.text', 'Select an option').click(); + cy.get('muon-inputter').invoke('attr','value').should('be.empty'); + cy.validateMessage('This field is required'); + } else if (occasion === 'Other'){ + cy.get('select').select('Other (please specify)'); + cy.get('muon-inputter').invoke('attr','value').should('eq', 'Other (please specify)'); + cy.get('muon-inputter').get('[type="text"]').type('Graduation Party'); + cy.get('muon-inputter').first().next().invoke('attr','value').should('eq', 'Graduation Party'); + } else { + cy.get('select').select(occasion); + cy.get('muon-inputter').invoke('attr','value').should('eq', occasion); + } + + cy.clickCTA('Next'); +}); + +Then('select the decoration from the list', () => { + cy.title().should('eq','PickAddon | Configurator'); + cy.selectCheckbox('Which decorations?',['Candles', 'Ribbon', 'Flowers', 'Writing']); + cy.percySnapshot('Cake decoration') + cy.clickCTA('Next'); +}); + +Then('enter the personal and delivery details', () => { + + // delivery date out of range + cy.validateDate('2021-12-01'); + cy.validateMessage('Date must be on or after 01/01/2022.'); + + // delivery date within range + cy.validateDate('2022-03-01'); + + //allergies or intolerances + cy.get('muon-inputter').find('textarea').type('No allergies, so you can use any ingredients'); + cy.get('muon-inputter').find('textarea').prev().should('have.text', 'Provide further information').click(); + cy.contains('label', 'Provide further information').parent().should('have.attr', 'value', 'No allergies, so you can use any ingredients'); + + //number of slices + cy.get('input[type="number"]').parent().shadow().find(inputElement.numberSelector).find('inputter-detail').find(inputElement.headingSlot).click(); + cy.get('input[type="number"]').parent().shadow().find(inputElement.numberSelector).find('inputter-detail').invoke('attr', 'open').should('exist'); + const rnd = Math.floor((Math.random() * 20) + 1); + cy.get('muon-inputter').find('input[type="number"]').type(`${rnd}`); + + let message = (Cypress.isBrowser('firefox')) ? 'Please select a value that is no more than 16. ' + : 'Value must be less than or equal to 16.' + + if(rnd > 16){ + cy.get('input[type="number"]').parent().shadow().find(inputElement.validationSelector).find(inputElement.messageSelector).contains(message); + } else{ + cy.get('input[type="number"]').parent().shadow().find('div[class="validation"]').should('not.exist'); + } + cy.get('input[type="number"]').parent().should('have.attr', 'value', rnd); + + //persional details + cy.personalDetails('Mr', 'Jeorge', 'Lantham', 'name@test.com', '07489437832'); + + //delivery address + cy.deliveryAddress('101', 'Hobbit road', 'Titans', 'TQ10 2SD'); + + cy.percySnapshot('Personal details and delivery address') + cy.clickCTA('Checkout'); + +}); + +Then('validate {string} {string} {string} details in the comfirmation page', (shape, icing, occasion) => { + + cy.get('dt').contains('Shape').next().should('have.text',shape); + cy.get('dt').contains('Tiers').next().should('have.text','3'); + cy.get('dt').contains('Icing').next().should('have.text',icing); + + + let event; + + if(!occasion){ + event = ''; + } else if(occasion === 'Other'){ + event = 'Graduation Party'; + }else{ + event = occasion; + } + cy.get('dt').contains('Decoration').next().should('have.text','Candles'); + cy.get('dd').contains('Candles').next().should('have.text','Ribbon'); + cy.get('dd').contains('Ribbon').next().should('have.text','Flowers'); + cy.get('dd').contains('Flowers').next().should('have.text','Writing'); + + cy.get('h2').contains('Allergies or intolerances').next().should('have.text', 'No allergies, so you can use any ingredients'); + + cy.get('dt').contains('Date due').next().should('have.text','2022-03-01'); + cy.get('dt').contains('Ordered by').next().should('have.text','Mr Jeorge Lantham'); + cy.get('dt').contains('Email').next().should('have.text','name@test.com'); + cy.get('dt').contains('Phone').next().should('have.text','0748-943-7832'); + + cy.get('dt').contains('Address').next().contains('TQ10 2SD'); + + cy.clickCTA('Buy Now'); + cy.percySnapshot('Confirmation page') + + cy.clickCTA('Reconfigure', true); + cy.title().should('eq','Choose a shape | Configurator'); +}); + +Then('click CTA and navigate to previous page', () => { + cy.clickCTA('Previous',true); + cy.title().should('eq','Choose a shape | Configurator'); +}); \ No newline at end of file diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js new file mode 100644 index 00000000..5f8c87e6 --- /dev/null +++ b/cypress/support/e2e.js @@ -0,0 +1,32 @@ +// *********************************************************** +// This example support/e2e.js 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 "allure-cypress/commands"; +import './functions/component'; +import './functions/ember'; +import '@percy/cypress'; + +// Alternatively you can use CommonJS syntax: +// require('./commands') +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false; + }); + + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file