From 5b4f8fdaa0f9b46c606c63967330bee19523d32b Mon Sep 17 00:00:00 2001 From: Rebecca Alpert Date: Wed, 13 Jan 2021 13:40:34 -0500 Subject: [PATCH] CONSOLE-2530: Migrate labels tests Migrated labels CRUD tests from Protractor to Cypress. Fixes https://issues.redhat.com/projects/CONSOLE/issues/CONSOLE-2530 --- frontend/integration-tests/protractor.conf.ts | 5 - .../integration-tests/tests/crud.scenario.ts | 94 ------------------- .../tests/crud/labels.spec.ts | 66 +++++++++++++ .../integration-tests-cypress/views/labels.ts | 6 ++ .../public/components/utils/label-list.tsx | 4 +- 5 files changed, 75 insertions(+), 100 deletions(-) delete mode 100644 frontend/integration-tests/tests/crud.scenario.ts create mode 100644 frontend/packages/integration-tests-cypress/tests/crud/labels.spec.ts create mode 100644 frontend/packages/integration-tests-cypress/views/labels.ts diff --git a/frontend/integration-tests/protractor.conf.ts b/frontend/integration-tests/protractor.conf.ts index 0641c22562d..082a33001fc 100644 --- a/frontend/integration-tests/protractor.conf.ts +++ b/frontend/integration-tests/protractor.conf.ts @@ -55,13 +55,11 @@ const testSuites = { secrets: suite(['tests/secrets.scenario.ts']), storage: suite(['tests/storage.scenario.ts']), crud: suite([ - 'tests/crud.scenario.ts', 'tests/secrets.scenario.ts', 'tests/filter.scenario.ts', 'tests/environment.scenario.ts', ]), event: suite(['tests/event.scenario.ts']), - crudBasic: suite(['tests/crud.scenario.ts']), monitoring: suite(['tests/monitoring.scenario.ts']), newApp: suite(['tests/overview/overview.scenario.ts', 'tests/deploy-image.scenario.ts']), performance: suite(['tests/performance.scenario.ts']), @@ -76,7 +74,6 @@ const testSuites = { crdExtensions: suite(['tests/crd-extensions.scenario.ts']), oauth: suite(['tests/oauth.scenario.ts']), e2e: suite([ - 'tests/crud.scenario.ts', 'tests/filter.scenario.ts', 'tests/secrets.scenario.ts', 'tests/storage.scenario.ts', @@ -95,7 +92,6 @@ const testSuites = { 'tests/cluster-settings.scenario.ts', ]), release: suite([ - 'tests/crud.scenario.ts', 'tests/secrets.scenario.ts', 'tests/filter.scenario.ts', 'tests/environment.scenario.ts', @@ -109,7 +105,6 @@ const testSuites = { 'tests/event.scenario.ts', ]), all: suite([ - 'tests/crud.scenario.ts', 'tests/overview/overview.scenario.ts', 'tests/secrets.scenario.ts', 'tests/storage.scenario.ts', diff --git a/frontend/integration-tests/tests/crud.scenario.ts b/frontend/integration-tests/tests/crud.scenario.ts deleted file mode 100644 index e9f5e9728ec..00000000000 --- a/frontend/integration-tests/tests/crud.scenario.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* eslint-disable no-console */ - -import { browser, $, $$, ExpectedConditions as until, Key } from 'protractor'; -import { safeLoad, safeDump } from 'js-yaml'; -import * as _ from 'lodash'; -import { execSync } from 'child_process'; - -import { appHost, testName, checkLogs, checkErrors } from '../protractor.conf'; -import * as crudView from '../views/crud.view'; -import * as yamlView from '../views/yaml.view'; - -describe('Kubernetes resource CRUD operations', () => { - const leakedResources = new Set(); - - afterEach(() => { - checkLogs(); - checkErrors(); - }); - - afterAll(() => { - const leakedArray: Array = [...leakedResources]; - if (!_.isEmpty(leakedArray)) { - console.error(`Leaked ${leakedArray.length} resources\n${leakedArray.join('\n')}.`); - } else { - console.log('No resources leaked.'); - } - - leakedArray - .map((r) => JSON.parse(r) as { name: string; plural: string; namespace?: string }) - .filter((r) => r.namespace === undefined) - .forEach(({ name, plural }) => { - try { - execSync(`kubectl delete --cascade ${plural} ${name}`); - } catch (error) { - console.error(`Failed to delete ${plural} ${name}:\n${error}`); - } - }); - }); - - describe('Editing labels', () => { - const name = `${testName}-editlabels`; - const plural = 'configmaps'; - const kind = 'ConfigMap'; - const labelValue = 'appblah'; - - beforeAll(async () => { - await browser.get(`${appHost}/k8s/ns/${testName}/${plural}/~new`); - await yamlView.isLoaded(); - const content = await yamlView.getEditorContent(); - const newContent = _.defaultsDeep( - {}, - { metadata: { name, namespace: testName } }, - safeLoad(content), - ); - await yamlView.setEditorContent(safeDump(newContent)); - leakedResources.add(JSON.stringify({ name, plural, namespace: testName })); - await yamlView.saveButton.click(); - }); - - it('displays modal for editing resource instance labels', async () => { - await crudView.clickDetailsPageAction(crudView.actions.labels); - await browser.wait(until.presenceOf($('.tags input'))); - await $('.tags input').sendKeys(labelValue, Key.ENTER); - // This only works because there's only one label - await browser.wait(until.textToBePresentInElement($('.tags .tag-item'), labelValue), 1000); - await $('.modal-footer #confirm-action').click(); - }); - - it('updates the resource instance labels', async () => { - await browser.wait(until.presenceOf($('.co-m-label.co-m-label--expand'))); - expect( - $$('.co-m-label__key') - .first() - .getText(), - ).toEqual(labelValue); - }); - - it('sees if label links still work', async () => { - await $$('.co-m-label') - .first() - .click(); - await browser.wait( - until.urlContains(`/search/ns/${testName}?kind=core~v1~ConfigMap&q=${labelValue}`), - ); - - expect($('.pf-c-chip__text').isDisplayed()).toBe(true); - }); - - afterAll(async () => { - await crudView.deleteResource(plural, kind, name); - leakedResources.delete(JSON.stringify({ name, plural, namespace: testName })); - }); - }); -}); diff --git a/frontend/packages/integration-tests-cypress/tests/crud/labels.spec.ts b/frontend/packages/integration-tests-cypress/tests/crud/labels.spec.ts new file mode 100644 index 00000000000..c2032dd83d1 --- /dev/null +++ b/frontend/packages/integration-tests-cypress/tests/crud/labels.spec.ts @@ -0,0 +1,66 @@ +import { safeLoad, safeDump } from 'js-yaml'; +import * as _ from 'lodash'; + +import { checkErrors, testName } from '../../support'; +import { nav } from '../../views/nav'; +import { detailsPage } from '../../views/details-page'; +import * as yamlEditor from '../../views/yaml-editor'; +import { errorMessage } from '../../views/form'; +import { modal } from '../../views/modal'; +import { labels } from '../../views/labels'; +import { ConfigMapKind } from '@console/internal/module/k8s'; + +describe('Editing labels', () => { + const name = `${testName}-editlabels`; + const plural = 'configmaps'; + const kind = 'ConfigMap'; + const labelValue = 'appblah'; + const yaml: ConfigMapKind = { + apiVersion: 'v1', + kind, + metadata: { + name, + namespace: testName, + }, + }; + + before(() => { + cy.login(); + cy.visit('/'); + nav.sidenav.switcher.changePerspectiveTo('Administrator'); + nav.sidenav.switcher.shouldHaveText('Administrator'); + cy.createProject(testName); + cy.visit(`k8s/ns/${testName}/${plural}/~new`); + yamlEditor.isLoaded(); + yamlEditor.getEditorContent().then((content) => { + const newContent = _.defaultsDeep({}, yaml, safeLoad(content)); + yamlEditor.setEditorContent(safeDump(newContent, { sortKeys: true })).then(() => { + yamlEditor.clickSaveCreateButton(); + cy.get(errorMessage).should('not.exist'); + }); + }); + }); + + afterEach(() => { + checkErrors(); + }); + + after(() => { + cy.deleteProject(testName); + cy.logout(); + }); + + it(`Adds a resource instance label, updates the resource instance label, and makes sure the link works`, () => { + detailsPage.isLoaded(); + detailsPage.clickPageActionFromDropdown('Edit labels'); + modal.shouldBeOpened(); + labels.inputLabel(labelValue); + modal.submit(); + detailsPage.isLoaded(); + labels.confirmDetailsPageLabelExists(labelValue); + labels.clickDetailsPageLabel(); + detailsPage.isLoaded(); + cy.url().should('include', `/search/ns/${testName}?kind=core~v1~ConfigMap&q=${labelValue}`); + labels.chipExists(); + }); +}); diff --git a/frontend/packages/integration-tests-cypress/views/labels.ts b/frontend/packages/integration-tests-cypress/views/labels.ts new file mode 100644 index 00000000000..21cca00382c --- /dev/null +++ b/frontend/packages/integration-tests-cypress/views/labels.ts @@ -0,0 +1,6 @@ +export const labels = { + inputLabel: (label: string) => cy.byTestID('tags-input').type(label), + confirmDetailsPageLabelExists: (label: string) => cy.byTestID('label-key').contains(label), + clickDetailsPageLabel: () => cy.byTestID('label-key').click(), + chipExists: () => cy.get('.pf-c-chip-group__label').should('exist'), +}; diff --git a/frontend/public/components/utils/label-list.tsx b/frontend/public/components/utils/label-list.tsx index 66ae9824bf6..e0ff3a735bd 100644 --- a/frontend/public/components/utils/label-list.tsx +++ b/frontend/public/components/utils/label-list.tsx @@ -14,7 +14,9 @@ export const Label: React.SFC = ({ kind, name, value, expand }) => { return (
- {name} + + {name} + {value && =} {value && {value}}