From 4a75852e5c10f75555b671fcc7804b355e8d3c43 Mon Sep 17 00:00:00 2001 From: Zein Sleiman Date: Wed, 1 May 2024 16:08:27 -0500 Subject: [PATCH 1/3] add basic component cypress tests --- cypress/component/Ansible.cy.tsx | 15 +++ cypress/component/CloseButton.cy.tsx | 10 +- cypress/component/ErrorBoundry.cy.tsx | 9 ++ cypress/component/ErrorState.cy.tsx | 21 ++++ cypress/component/InvalidObject.cy.tsx | 11 ++ cypress/component/LogSnippet.cy.tsx | 9 ++ cypress/component/MultiContentCard.cy.tsx | 106 ++++++++++++++++++++ cypress/component/NotAuthorized.cy.tsx | 34 +++++++ cypress/component/ShortcutGrid.cy.tsx | 18 ++++ cypress/component/SkeletonTable.cy.tsx | 12 +++ cypress/component/TagCount.cy.tsx | 15 +++ cypress/component/UnavailableContent.cy.tsx | 10 ++ cypress/component/WarningModal.cy.tsx | 28 ++++++ 13 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 cypress/component/Ansible.cy.tsx create mode 100644 cypress/component/ErrorBoundry.cy.tsx create mode 100644 cypress/component/ErrorState.cy.tsx create mode 100644 cypress/component/InvalidObject.cy.tsx create mode 100644 cypress/component/LogSnippet.cy.tsx create mode 100644 cypress/component/MultiContentCard.cy.tsx create mode 100644 cypress/component/NotAuthorized.cy.tsx create mode 100644 cypress/component/ShortcutGrid.cy.tsx create mode 100644 cypress/component/SkeletonTable.cy.tsx create mode 100644 cypress/component/TagCount.cy.tsx create mode 100644 cypress/component/UnavailableContent.cy.tsx create mode 100644 cypress/component/WarningModal.cy.tsx diff --git a/cypress/component/Ansible.cy.tsx b/cypress/component/Ansible.cy.tsx new file mode 100644 index 00000000..5f6b21fd --- /dev/null +++ b/cypress/component/Ansible.cy.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import Ansible from '../../packages/module/dist/dynamic/Ansible'; + +describe('Ansible', () => { + it('renders supported Ansible', () => { + /* eslint-disable no-console */ + cy.mount() + cy.get('i').should('have.class', 'ansibleSupported-0-2-2'); + }); + it('renders unsupported Ansible', () => { + /* eslint-disable no-console */ + cy.mount() + cy.get('i').should('have.class', 'ansibleUnsupported-0-2-3'); + }); +}); \ No newline at end of file diff --git a/cypress/component/CloseButton.cy.tsx b/cypress/component/CloseButton.cy.tsx index 7b2c485c..e1523463 100644 --- a/cypress/component/CloseButton.cy.tsx +++ b/cypress/component/CloseButton.cy.tsx @@ -2,9 +2,15 @@ import React from 'react'; import CloseButton from '../../packages/module/dist/dynamic/CloseButton'; describe('CloseButton', () => { + /* eslint-disable no-console */ it('renders the Close button', () => { - /* eslint-disable no-console */ cy.mount({console.log('Close button clicked')}} style={{ float: 'none' }}/>) cy.get('[data-test-id="close-button-example"]').should('exist'); - }) + }); + it('should call callback on click', () => { + const onClickSpy = cy.spy().as('onClickSpy'); + cy.mount(); + cy.get('[data-test-id="close-button-example"]').click(); + cy.get('@onClickSpy').should('have.been.called'); + }); }) \ No newline at end of file diff --git a/cypress/component/ErrorBoundry.cy.tsx b/cypress/component/ErrorBoundry.cy.tsx new file mode 100644 index 00000000..3712ed08 --- /dev/null +++ b/cypress/component/ErrorBoundry.cy.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ErrorBoundary from '../../packages/module/dist/dynamic/ErrorBoundary'; + +describe('ErrorBoundary', () => { + it('renders the ErrorBoundary ', () => { + cy.mount() + // cy.get('div').debug(); + }); +}) \ No newline at end of file diff --git a/cypress/component/ErrorState.cy.tsx b/cypress/component/ErrorState.cy.tsx new file mode 100644 index 00000000..0cfaa19e --- /dev/null +++ b/cypress/component/ErrorState.cy.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import ErrorState from '../../packages/module/dist/dynamic/ErrorState'; +import { ActionButton } from '../../packages/module/dist/dynamic/ActionButton' + +describe('ErrorState', () => { + /* eslint-disable no-console */ + it('renders the Close button', () => { + cy.mount(); + cy.get('h4').should('have.text', 'Sample error title'); + }); + + it('render with a custom footer', () => { + const onClickSpy = cy.spy().as('onClickSpy'); + cy.mount( + Custom action + }/>); + cy.get('button').should('exist'); + cy.get('button').click(); + cy.get('@onClickSpy').should('have.been.called'); + }) +}) \ No newline at end of file diff --git a/cypress/component/InvalidObject.cy.tsx b/cypress/component/InvalidObject.cy.tsx new file mode 100644 index 00000000..02b2603e --- /dev/null +++ b/cypress/component/InvalidObject.cy.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import InvalidObject from '../../packages/module/dist/dynamic/InvalidObject'; + +describe('InvalidObject', () => { + /* eslint-disable no-console */ + it('renders InvalidObject', () => { + cy.mount() + cy.get('[class="pf-v5-c-empty-state"]').should('exist') + cy.get('h1').should('have.text', 'We lost that page'); + }); +}) \ No newline at end of file diff --git a/cypress/component/LogSnippet.cy.tsx b/cypress/component/LogSnippet.cy.tsx new file mode 100644 index 00000000..0052fa87 --- /dev/null +++ b/cypress/component/LogSnippet.cy.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import LogSnippet from '../../packages/module/dist/dynamic/LogSnippet'; + +describe('LogSnippet', () => { + it('renders LogSnippet', () => { + cy.mount() + cy.get('div div p').should('have.text', 'A test message'); + }); +}); \ No newline at end of file diff --git a/cypress/component/MultiContentCard.cy.tsx b/cypress/component/MultiContentCard.cy.tsx new file mode 100644 index 00000000..8fda3142 --- /dev/null +++ b/cypress/component/MultiContentCard.cy.tsx @@ -0,0 +1,106 @@ +import React from 'react'; +import MultiContentCard from "@patternfly/react-component-groups/dist/dynamic/MultiContentCard"; +import { Button, Card, CardHeader, CardBody, Text, TextContent, TextVariants, Icon, TextList, TextListItem, CardFooter } from '@patternfly/react-core'; +import { ArrowRightIcon, BellIcon, CogIcon, LockIcon } from '@patternfly/react-icons'; + +const cards = [ + + + + Getting Started + + + + + + + + + Configure application + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + , + + + + + + + + Configure access + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + + + + + + + + + , + + + + Next Steps + + + + + + + + + Configure notifications + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + +]; + +const MultiContentCardExample: React.FunctionComponent = () => ; + +describe('MultiContentCard', () => { + it('renders MultiContentCard', () => { + cy.mount(); + cy.get('[class="pf-v5-c-card pf-m-expanded"').should('exist'); + }); +}); diff --git a/cypress/component/NotAuthorized.cy.tsx b/cypress/component/NotAuthorized.cy.tsx new file mode 100644 index 00000000..83e70261 --- /dev/null +++ b/cypress/component/NotAuthorized.cy.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Button } from '@patternfly/react-core'; +import NotAuthorized from '../../packages/module/dist/dynamic/NotAuthorized'; + +describe('NotAuthorized', () => { + it('renders basic NotAuthorized', () => { + cy.mount(); + cy.get('div div div h5').should('have.text', 'You do not have access to Test bundle'); + }); + + it('renders NotAuthorized with custom action buttons', () => { + const onClickSpy = cy.spy().as('onClickSpy'); + const primaryAction = + ; + const customNotAuthorized = + cy.mount(customNotAuthorized); + const customButton = cy.get('div div div div button') + customButton.should('exist'); + customButton.should('have.text', 'Custom primary action'); + customButton.click(); + cy.get('@onClickSpy').should('have.been.called'); + }); +}); \ No newline at end of file diff --git a/cypress/component/ShortcutGrid.cy.tsx b/cypress/component/ShortcutGrid.cy.tsx new file mode 100644 index 00000000..cf585c73 --- /dev/null +++ b/cypress/component/ShortcutGrid.cy.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import ShortcutGrid from '../../packages/module/dist/dynamic/ShortcutGrid'; + +describe('ShortcutGrid', () => { + /* eslint-disable no-console */ + it('renders ShortcutGrid', () => { + const shortCutGridExample = + cy.mount(shortCutGridExample); + cy.get('[class="pf-v5-l-grid pf-m-all-6-col pf-m-gutter"]').should('exist'); + cy.get('div div').should('have.text', '⌘ Cmd + ⇧ Shift + TOpen new tab⌥ Opt + NOpen new page^ Ctrl + DragMove object⌘ Cmd + ⇧ Shift + T⌘ Cmd⇧ ShiftTOpen new tab⌥ Opt + N⌥ OptNOpen new page^ Ctrl + Drag^ Ctrl DragMove object'); + }); +}) \ No newline at end of file diff --git a/cypress/component/SkeletonTable.cy.tsx b/cypress/component/SkeletonTable.cy.tsx new file mode 100644 index 00000000..8139601a --- /dev/null +++ b/cypress/component/SkeletonTable.cy.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import SkeletonTable from '../../packages/module/dist/dynamic/SkeletonTable'; + +describe('SkeletonTable', () => { + /* eslint-disable no-console */ + it('renders SkeletonTable', () => { + const SkeletonTableExample = ; + cy.mount(SkeletonTableExample); + cy.get('table').should('exist'); + cy.get('table thead tr').should('have.text', 'firstsecond'); + }); +}) \ No newline at end of file diff --git a/cypress/component/TagCount.cy.tsx b/cypress/component/TagCount.cy.tsx new file mode 100644 index 00000000..40d68032 --- /dev/null +++ b/cypress/component/TagCount.cy.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import TagCount from '../../packages/module/dist/dynamic/TagCount'; + +describe('TagCount', () => { + it('renders TagCount', () => { + cy.mount() + cy.get('button').should('exist'); + cy.get('button span').should('have.text', '50'); + }); + + it('render disabled', () => { + cy.mount() + cy.get('button').should('be.disabled'); + }); +}); \ No newline at end of file diff --git a/cypress/component/UnavailableContent.cy.tsx b/cypress/component/UnavailableContent.cy.tsx new file mode 100644 index 00000000..545ca1cf --- /dev/null +++ b/cypress/component/UnavailableContent.cy.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import UnavailableContent from '../../packages/module/dist/dynamic/UnavailableContent'; + +describe('UnavailableContent', () => { + it('renders UnavailableContent', () => { + cy.mount() + cy.get('[class="pf-v5-c-empty-state__content"').should('exist'); + cy.get('div div div h5').should('have.text', 'This page is temporarily unavailable'); + }); +}); \ No newline at end of file diff --git a/cypress/component/WarningModal.cy.tsx b/cypress/component/WarningModal.cy.tsx new file mode 100644 index 00000000..dcc57a09 --- /dev/null +++ b/cypress/component/WarningModal.cy.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Button } from '@patternfly/react-core'; +import WarningModal from '../../packages/module/dist/dynamic/WarningModal'; + +const BasicModal: React.FunctionComponent = () => { + const [ isOpen, setIsOpen ] = React.useState(false); + return <> + + setIsOpen(false)} + onConfirm={() => setIsOpen(false)}> + Your page contains unsaved changes. Do you want to leave? + + +}; + +describe('WarningModal', () => { + it('renders WarningModal', () => { + cy.mount() + cy.get('button').click(); + cy.get('[class="pf-v5-c-modal-box pf-m-warning pf-m-sm"').should('exist'); + cy.get('div header h1 span').should('have.text', 'Warning alert:Unsaved changes'); + }); +}); \ No newline at end of file From c1035c264c09ea976244fa83e4f17490fa91c886 Mon Sep 17 00:00:00 2001 From: Zein Sleiman Date: Thu, 2 May 2024 16:05:18 -0500 Subject: [PATCH 2/3] add more assertions; remove old eslint disable comment --- cypress/component/Ansible.cy.tsx | 2 -- .../component/{ErrorBoundry.cy.tsx => ErrorBoundary.cy.tsx} | 4 ++-- cypress/component/ErrorState.cy.tsx | 2 +- cypress/component/InvalidObject.cy.tsx | 1 - cypress/component/LogSnippet.cy.tsx | 1 + cypress/component/NotAuthorized.cy.tsx | 1 + cypress/component/ShortcutGrid.cy.tsx | 1 - cypress/component/SkeletonTable.cy.tsx | 1 - cypress/component/UnavailableContent.cy.tsx | 1 + 9 files changed, 6 insertions(+), 8 deletions(-) rename cypress/component/{ErrorBoundry.cy.tsx => ErrorBoundary.cy.tsx} (58%) diff --git a/cypress/component/Ansible.cy.tsx b/cypress/component/Ansible.cy.tsx index 5f6b21fd..997e5666 100644 --- a/cypress/component/Ansible.cy.tsx +++ b/cypress/component/Ansible.cy.tsx @@ -3,12 +3,10 @@ import Ansible from '../../packages/module/dist/dynamic/Ansible'; describe('Ansible', () => { it('renders supported Ansible', () => { - /* eslint-disable no-console */ cy.mount() cy.get('i').should('have.class', 'ansibleSupported-0-2-2'); }); it('renders unsupported Ansible', () => { - /* eslint-disable no-console */ cy.mount() cy.get('i').should('have.class', 'ansibleUnsupported-0-2-3'); }); diff --git a/cypress/component/ErrorBoundry.cy.tsx b/cypress/component/ErrorBoundary.cy.tsx similarity index 58% rename from cypress/component/ErrorBoundry.cy.tsx rename to cypress/component/ErrorBoundary.cy.tsx index 3712ed08..dd4519d5 100644 --- a/cypress/component/ErrorBoundry.cy.tsx +++ b/cypress/component/ErrorBoundary.cy.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import ErrorBoundary from '../../packages/module/dist/dynamic/ErrorBoundary'; +import ErrorBoundary from '../../packages/module/dist/esm/ErrorBoundary'; describe('ErrorBoundary', () => { it('renders the ErrorBoundary ', () => { cy.mount() - // cy.get('div').debug(); + // cy.get('div h1').should('have.text', 'Something wrong happened'); }); }) \ No newline at end of file diff --git a/cypress/component/ErrorState.cy.tsx b/cypress/component/ErrorState.cy.tsx index 0cfaa19e..2360d62b 100644 --- a/cypress/component/ErrorState.cy.tsx +++ b/cypress/component/ErrorState.cy.tsx @@ -3,10 +3,10 @@ import ErrorState from '../../packages/module/dist/dynamic/ErrorState'; import { ActionButton } from '../../packages/module/dist/dynamic/ActionButton' describe('ErrorState', () => { - /* eslint-disable no-console */ it('renders the Close button', () => { cy.mount(); cy.get('h4').should('have.text', 'Sample error title'); + cy.get('div div div div div div').should('have.text', 'Sample error description'); }); it('render with a custom footer', () => { diff --git a/cypress/component/InvalidObject.cy.tsx b/cypress/component/InvalidObject.cy.tsx index 02b2603e..7e64dad5 100644 --- a/cypress/component/InvalidObject.cy.tsx +++ b/cypress/component/InvalidObject.cy.tsx @@ -2,7 +2,6 @@ import React from 'react'; import InvalidObject from '../../packages/module/dist/dynamic/InvalidObject'; describe('InvalidObject', () => { - /* eslint-disable no-console */ it('renders InvalidObject', () => { cy.mount() cy.get('[class="pf-v5-c-empty-state"]').should('exist') diff --git a/cypress/component/LogSnippet.cy.tsx b/cypress/component/LogSnippet.cy.tsx index 0052fa87..b52ca3e5 100644 --- a/cypress/component/LogSnippet.cy.tsx +++ b/cypress/component/LogSnippet.cy.tsx @@ -5,5 +5,6 @@ describe('LogSnippet', () => { it('renders LogSnippet', () => { cy.mount() cy.get('div div p').should('have.text', 'A test message'); + cy.get('div div div div pre').should('have.text', 'test test code'); }); }); \ No newline at end of file diff --git a/cypress/component/NotAuthorized.cy.tsx b/cypress/component/NotAuthorized.cy.tsx index 83e70261..51269f3a 100644 --- a/cypress/component/NotAuthorized.cy.tsx +++ b/cypress/component/NotAuthorized.cy.tsx @@ -10,6 +10,7 @@ describe('NotAuthorized', () => { prevPageButtonText="Go to previous page" />); cy.get('div div div h5').should('have.text', 'You do not have access to Test bundle'); + cy.get('[class="pf-v5-c-empty-state__body"').should('have.text', 'Test text'); }); it('renders NotAuthorized with custom action buttons', () => { diff --git a/cypress/component/ShortcutGrid.cy.tsx b/cypress/component/ShortcutGrid.cy.tsx index cf585c73..fa242a5f 100644 --- a/cypress/component/ShortcutGrid.cy.tsx +++ b/cypress/component/ShortcutGrid.cy.tsx @@ -2,7 +2,6 @@ import React from 'react'; import ShortcutGrid from '../../packages/module/dist/dynamic/ShortcutGrid'; describe('ShortcutGrid', () => { - /* eslint-disable no-console */ it('renders ShortcutGrid', () => { const shortCutGridExample = { - /* eslint-disable no-console */ it('renders SkeletonTable', () => { const SkeletonTableExample = ; cy.mount(SkeletonTableExample); diff --git a/cypress/component/UnavailableContent.cy.tsx b/cypress/component/UnavailableContent.cy.tsx index 545ca1cf..93fb19bf 100644 --- a/cypress/component/UnavailableContent.cy.tsx +++ b/cypress/component/UnavailableContent.cy.tsx @@ -6,5 +6,6 @@ describe('UnavailableContent', () => { cy.mount() cy.get('[class="pf-v5-c-empty-state__content"').should('exist'); cy.get('div div div h5').should('have.text', 'This page is temporarily unavailable'); + cy.get('[class="pf-v5-c-empty-state__body"').should('have.text', 'Try refreshing the page. If the problem persists, contact your organization administrator or visit our status page for known outages.'); }); }); \ No newline at end of file From 99b4d46685edc5233a37b0180f8bc902acb16bf9 Mon Sep 17 00:00:00 2001 From: Zein Sleiman Date: Mon, 6 May 2024 14:28:33 -0500 Subject: [PATCH 3/3] fix ErrorBoundary import --- cypress/component/ErrorBoundary.cy.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/component/ErrorBoundary.cy.tsx b/cypress/component/ErrorBoundary.cy.tsx index dd4519d5..8bf9cc44 100644 --- a/cypress/component/ErrorBoundary.cy.tsx +++ b/cypress/component/ErrorBoundary.cy.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import ErrorBoundary from '../../packages/module/dist/esm/ErrorBoundary'; +import ErrorBoundary from '../../packages/module/dist/dynamic/ErrorBoundary'; describe('ErrorBoundary', () => { it('renders the ErrorBoundary ', () => { cy.mount() - // cy.get('div h1').should('have.text', 'Something wrong happened'); + cy.get('div h1').should('have.text', 'Something wrong happened'); }); }) \ No newline at end of file