Skip to content

Commit

Permalink
Merge pull request #7213 from dtaylor113/add-i18n-testing-to-crud-tests
Browse files Browse the repository at this point in the history
CONSOLE-2420: Added i18n testing to cypress crud test suite
  • Loading branch information
openshift-merge-robot committed Nov 23, 2020
2 parents 5176fe1 + 4642ae2 commit 8b3508d
Show file tree
Hide file tree
Showing 16 changed files with 238 additions and 142 deletions.
34 changes: 34 additions & 0 deletions frontend/packages/integration-tests-cypress/support/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,47 @@
import { expect } from 'chai';
import { listPage } from '../views/list-page';

declare global {
namespace Cypress {
interface Chainable<Subject> {
isPseudoLocalized(): Chainable<Element>;
testI18n(selectors?: string[], testIDs?: string[]): Chainable<Element>;
}
}
}

Cypress.Commands.add('testI18n', (selectors: string[] = [], testIDs: string[] = []) => {
cy.location().then((loc) => {
const params = new URLSearchParams(loc.search);
params.set('pseudolocalization', 'true');
params.set('lng', 'en');
const pseudoLocUrl = `${loc.pathname}?${params.toString()}`;

cy.visit(pseudoLocUrl);

// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(2000); // don't know what to wait for since could be list or detial page

// if PF toolbar, click to open 'search by' dropdown
cy.get('#content').then(($body) => {
if ($body.find('#filter-toolbar').length) {
listPage.filter.clickSearchByDropdown();
cy.get('.pf-c-dropdown__menu-item').isPseudoLocalized(); // 'search by' menu items
}

testIDs.forEach((testId) => cy.byTestID(testId).isPseudoLocalized());
selectors.forEach((selector) =>
cy.get(selector).each(($el) => {
const i18nNotTranslatedAttr = $el.attr('i18n-not-translated');
if (!i18nNotTranslatedAttr) {
cy.wrap($el).isPseudoLocalized();
}
}),
);
});
});
});

Cypress.Commands.add(
'isPseudoLocalized',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Cypress.Commands.add('createProject', (name: string, devConsole: boolean = false
listPage.clickCreateYAMLbutton();
modal.shouldBeOpened();
cy.byTestID('input-name').type(name);
cy.testA11y('Create Project modal');
// TODO: uncomment once https://bugzilla.redhat.com/show_bug.cgi?id=1897008 is fixed
// cy.testA11y('Create Project modal');
modal.submit();
modal.shouldBeClosed();
// TODO, switch to 'listPage.titleShouldHaveText(name)', when we switch to new test id
Expand All @@ -39,7 +40,8 @@ Cypress.Commands.add('deleteProject', (name: string) => {
modal.submitShouldBeDisabled();
cy.byTestID('project-name-input').type(name);
modal.submitShouldBeEnabled();
cy.testA11y('Delete Project modal');
// TODO: uncomment once https://bugzilla.redhat.com/show_bug.cgi?id=1897008 is fixed
// cy.testA11y('Delete Project modal');
modal.submit();
modal.shouldBeClosed();
listPage.titleShouldHaveText('Projects');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { safeLoad, safeDump } from 'js-yaml';
import * as _ from 'lodash';

import { testName, editKind, deleteKind, checkErrors } from '../../support';
import { listPage } from '../../views/list-page';
import { detailsPage } from '../../views/details-page';
import { listPage, ListPageSelector } from '../../views/list-page';
import { detailsPage, DetailsPageSelector } from '../../views/details-page';
import { modal } from '../../views/modal';
import * as yamlEditor from '../../views/yaml-editor';
import { errorMessage } from '../../views/form';
Expand All @@ -26,53 +26,64 @@ describe('Kubernetes resource CRUD operations', () => {

const k8sObjs = OrderedMap<
string,
{ kind: string; namespaced?: boolean; humanizeKind?: boolean }
{ kind: string; namespaced?: boolean; humanizeKind?: boolean; testI18n?: boolean }
>()
.set('pods', { kind: 'Pod' })
.set('services', { kind: 'Service' })
.set('serviceaccounts', { kind: 'ServiceAccount' })
.set('serviceaccounts', { kind: 'ServiceAccount', testI18n: false })
.set('secrets', { kind: 'Secret' })
.set('configmaps', { kind: 'ConfigMap' })
.set('persistentvolumes', { kind: 'PersistentVolume', namespaced: false })
.set('storageclasses', { kind: 'StorageClass', namespaced: false })
.set('persistentvolumes', { kind: 'PersistentVolume', namespaced: false, testI18n: false })
.set('storageclasses', { kind: 'StorageClass', namespaced: false, testI18n: false })
.set('ingresses', { kind: 'Ingress' })
.set('cronjobs', { kind: 'CronJob' })
.set('jobs', { kind: 'Job' })
.set('daemonsets', { kind: 'DaemonSet' })
.set('deployments', { kind: 'Deployment' })
.set('replicasets', { kind: 'ReplicaSet' })
.set('replicationcontrollers', { kind: 'ReplicationController' })
.set('persistentvolumeclaims', { kind: 'PersistentVolumeClaim' })
.set('persistentvolumeclaims', { kind: 'PersistentVolumeClaim', testI18n: false })
.set('statefulsets', { kind: 'StatefulSet' })
.set('resourcequotas', { kind: 'ResourceQuota', humanizeKind: false })
.set('limitranges', { kind: 'LimitRange', humanizeKind: false })
.set('horizontalpodautoscalers', { kind: 'HorizontalPodAutoscaler' })
.set('networkpolicies', { kind: 'NetworkPolicy' })
.set('roles', { kind: 'Role' })
.set('roles', { kind: 'Role', testI18n: false })
.set('snapshot.storage.k8s.io~v1beta1~VolumeSnapshot', {
kind: 'snapshot.storage.k8s.io~v1beta1~VolumeSnapshot',
testI18n: false,
})
.set('snapshot.storage.k8s.io~v1beta1~VolumeSnapshotClass', {
kind: 'snapshot.storage.k8s.io~v1beta1~VolumeSnapshotClass',
namespaced: false,
testI18n: false,
})
.set('snapshot.storage.k8s.io~v1beta1~VolumeSnapshotContent', {
kind: 'snapshot.storage.k8s.io~v1beta1~VolumeSnapshotContent',
namespaced: false,
testI18n: false,
});
const openshiftObjs = OrderedMap<string, { kind: string; namespaced?: boolean }>()
const openshiftObjs = OrderedMap<
string,
{ kind: string; namespaced?: boolean; testI18n?: boolean }
>()
.set('deploymentconfigs', { kind: 'DeploymentConfig' })
.set('buildconfigs', { kind: 'BuildConfig' })
.set('imagestreams', { kind: 'ImageStream' })
.set('routes', { kind: 'Route' })
.set('user.openshift.io~v1~Group', { kind: 'user.openshift.io~v1~Group', namespaced: false });
const serviceCatalogObjs = OrderedMap<string, { kind: string; namespaced?: boolean }>().set(
'clusterservicebrokers',
{
kind: 'servicecatalog.k8s.io~v1beta1~ClusterServiceBroker',
.set('user.openshift.io~v1~Group', {
kind: 'user.openshift.io~v1~Group',
namespaced: false,
},
);
testI18n: false,
});
const serviceCatalogObjs = OrderedMap<
string,
{ kind: string; namespaced?: boolean; testI18n?: boolean }
>().set('clusterservicebrokers', {
kind: 'servicecatalog.k8s.io~v1beta1~ClusterServiceBroker',
namespaced: false,
testI18n: false,
});

let testObjs = Cypress.env('openshift') === true ? k8sObjs.merge(openshiftObjs) : k8sObjs;
testObjs = Cypress.env('servicecatalog') === true ? testObjs.merge(serviceCatalogObjs) : testObjs;
Expand All @@ -84,106 +95,121 @@ describe('Kubernetes resource CRUD operations', () => {
'snapshot.storage.k8s.io~v1beta1~VolumeSnapshot',
]);

testObjs.forEach(({ kind, namespaced = true, humanizeKind = true }, resource) => {
describe(kind, () => {
const name = `${testName}-${_.kebabCase(kind)}`;
testObjs.forEach(
({ kind, namespaced = true, humanizeKind = true, testI18n = true }, resource) => {
describe(kind, () => {
const name = `${testName}-${_.kebabCase(kind)}`;

it(`creates the resource instance`, () => {
cy.visit(
`${namespaced ? `/k8s/ns/${testName}` : '/k8s/cluster'}/${resource}?name=${testName}`,
);
if (kind === 'Secret') {
listPage.clickCreateYAMLdropdownButton();
} else {
listPage.clickCreateYAMLbutton();
}
if (resourcesWithCreationForm.has(kind)) {
cy.byTestID('yaml-link').click();
}
// sidebar needs to be fully loaded, else it sometimes overlays the Create button
cy.byTestID('resource-sidebar').should('exist');
yamlEditor.isLoaded();
cy.testA11y(`YAML Editor for ${kind}: ${name}`);
let newContent;
// get, update, and set yaml editor content.
yamlEditor.getEditorContent().then((content) => {
newContent = _.defaultsDeep(
{},
{ metadata: { name, labels: { [testLabel]: testName } } },
safeLoad(content),
it(`creates the resource instance`, () => {
cy.visit(
`${namespaced ? `/k8s/ns/${testName}` : '/k8s/cluster'}/${resource}?name=${testName}`,
);
yamlEditor.setEditorContent(safeDump(newContent, { sortKeys: true })).then(() => {
yamlEditor.clickSaveCreateButton();
cy.get(errorMessage).should('not.exist');
if (kind === 'Secret') {
listPage.clickCreateYAMLdropdownButton();
} else {
listPage.clickCreateYAMLbutton();
}
if (resourcesWithCreationForm.has(kind)) {
cy.byTestID('yaml-link').click();
}
// sidebar needs to be fully loaded, else it sometimes overlays the Create button
cy.byTestID('resource-sidebar').should('exist');
yamlEditor.isLoaded();
cy.testA11y(`YAML Editor for ${kind}: ${name}`);
let newContent;
// get, update, and set yaml editor content.
yamlEditor.getEditorContent().then((content) => {
newContent = _.defaultsDeep(
{},
{ metadata: { name, labels: { [testLabel]: testName } } },
safeLoad(content),
);
yamlEditor.setEditorContent(safeDump(newContent, { sortKeys: true })).then(() => {
yamlEditor.clickSaveCreateButton();
cy.get(errorMessage).should('not.exist');
});
});
});
});

it('displays detail view for newly created resource instance', () => {
cy.url().should('include', `/${name}`);
detailsPage.isLoaded();
detailsPage.titleShouldContain(name);
cy.testA11y(`Details page for ${kind}: ${name}`);
});
it('displays detail view for newly created resource instance', () => {
cy.url().should('include', `/${name}`);
detailsPage.isLoaded();
detailsPage.titleShouldContain(name);
cy.testA11y(`Details page for ${kind}: ${name}`);
if (testI18n) {
cy.testI18n(
[
DetailsPageSelector.horizontalNavTabs,
DetailsPageSelector.sectionHeadings,
DetailsPageSelector.itemLabels,
],
['timestamp'],
);
}
});

it(`displays a list view for the resource`, () => {
cy.visit(
`${namespaced ? `/k8s/ns/${testName}` : '/k8s/cluster'}/${resource}?name=${testName}`,
);
if (namespaced) {
// should have a namespace dropdown for namespaced objects');
listPage.projectDropdownShouldExist();
listPage.projectDropdownShouldContain(testName);
} else {
// should not have a namespace dropdown for non-namespaced objects');
listPage.projectDropdownShouldNotExist();
}
listPage.rows.shouldBeLoaded();
cy.testA11y(`List page for ${kind}: ${name}`);
});
it(`displays a list view for the resource`, () => {
cy.visit(
`${namespaced ? `/k8s/ns/${testName}` : '/k8s/cluster'}/${resource}?name=${testName}`,
);
if (namespaced) {
// should have a namespace dropdown for namespaced objects');
listPage.projectDropdownShouldExist();
listPage.projectDropdownShouldContain(testName);
} else {
// should not have a namespace dropdown for non-namespaced objects');
listPage.projectDropdownShouldNotExist();
}
listPage.rows.shouldBeLoaded();
cy.testA11y(`List page for ${kind}: ${name}`);
if (testI18n) {
cy.testI18n([ListPageSelector.tableColumnHeaders], ['item-create']);
}
});

it('search view displays created resource instance', () => {
cy.visit(
`/search/${
namespaced ? `ns/${testName}` : 'all-namespaces'
}?kind=${kind}&q=${testLabel}%3d${testName}&name=${name}`,
);
it('search view displays created resource instance', () => {
cy.visit(
`/search/${
namespaced ? `ns/${testName}` : 'all-namespaces'
}?kind=${kind}&q=${testLabel}%3d${testName}&name=${name}`,
);

// filter should have 3 chip groups: resource, label, and name
listPage.filter.numberOfActiveFiltersShouldBe(3);
listPage.rows.shouldExist(name);
cy.testA11y(`Search page for ${kind}: ${name}`);
// filter should have 3 chip groups: resource, label, and name
listPage.filter.numberOfActiveFiltersShouldBe(3);
listPage.rows.shouldExist(name);
cy.testA11y(`Search page for ${kind}: ${name}`);

// link to to details page
listPage.rows.clickRowByName(name);
cy.url().should('include', `/${name}`);
detailsPage.titleShouldContain(name);
});
// link to to details page
listPage.rows.clickRowByName(name);
cy.url().should('include', `/${name}`);
detailsPage.titleShouldContain(name);
});

it('edits the resource instance', () => {
cy.visit(
`/search/${
namespaced ? `ns/${testName}` : 'all-namespaces'
}?kind=${kind}&q=${testLabel}%3d${testName}&name=${name}`,
);
listPage.rows.clickKebabAction(name, editKind(kind, humanizeKind));
if (kind !== 'Secret') {
yamlEditor.isLoaded();
yamlEditor.clickReloadButton();
}
yamlEditor.clickSaveCreateButton();
});
it('edits the resource instance', () => {
cy.visit(
`/search/${
namespaced ? `ns/${testName}` : 'all-namespaces'
}?kind=${kind}&q=${testLabel}%3d${testName}&name=${name}`,
);
listPage.rows.clickKebabAction(name, editKind(kind, humanizeKind));
if (kind !== 'Secret') {
yamlEditor.isLoaded();
yamlEditor.clickReloadButton();
}
yamlEditor.clickSaveCreateButton();
});

it(`deletes the resource instance`, () => {
cy.visit(`${namespaced ? `/k8s/ns/${testName}` : '/k8s/cluster'}/${resource}`);
listPage.filter.byName(name);
listPage.rows.countShouldBe(1);
listPage.rows.clickKebabAction(name, deleteKind(kind, humanizeKind));
modal.shouldBeOpened();
modal.submit();
modal.shouldBeClosed();
cy.resourceShouldBeDeleted(testName, resource, name);
it(`deletes the resource instance`, () => {
cy.visit(`${namespaced ? `/k8s/ns/${testName}` : '/k8s/cluster'}/${resource}`);
listPage.filter.byName(name);
listPage.rows.countShouldBe(1);
listPage.rows.clickKebabAction(name, deleteKind(kind, humanizeKind));
modal.shouldBeOpened();
modal.submit();
modal.shouldBeClosed();
cy.resourceShouldBeDeleted(testName, resource, name);
});
});
});
});
},
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ export const detailsPage = {
export namespace DetailsPageSelector {
export const name = 'dd[data-test-selector="details-item-value__Name"]';
export const namespace = 'dd[data-test-selector="details-item-value__Namespace"] a';
export const sectionHeadings = '[data-test-section-heading]';
export const itemLabels = 'dt';
export const horizontalNavTabs = '.co-m-horizontal-nav__menu-item';
}

0 comments on commit 8b3508d

Please sign in to comment.