test(ui): add first Cypress test
Cypress is a comprehensive e2e testing framework that runs through a
browser (e.g. chrome, firefox), and allows simulation of real users
interacting directly with the system.
Closes
ADD
cypress.json
+{
+ "defaultCommandTimeout":10000
+}

ADD
cypress/integration/Basic_Functionality.js
+describe('My First Test', () => {
+
+ before(() => {
+ cy.clearCookies();
+ cy.visit('localhost:8080/apimanui');
+ cy.typeLogin('admin', 'admin123!')
+ });
+
+ beforeEach(() => {
+ Cypress.Cookies.preserveOnce('JSESSIONID', 'OAuth_Token_Request_State');
+ cy.visit('localhost:8080/apimanui');
+ });
+
+ it('Create the Organization via NavBar and edit the description', () => {
+ cy.get('[title="Organizations"]').click();
+ cy.contains('New Organization').click();
+ cy.get('.btn-primary').should('be.disabled');
+ cy.get('#apiman-entityname').type('TestOrganization');
+ cy.get('#apiman-description').type('Description of TestOrganization');
+ cy.get('.btn-primary').should('be.enabled').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Description of TestOrganization');
+ cy.get('#descriptionWrapper').click();
+ cy.get('.autoExpand').type('{selectall}{del}Edited Description of TestOrganization');
+ cy.get('.fa-check').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Edited Description of TestOrganization');
+ })
+
+ it('Delete the Organization', () => {
+ cy.visitTestOrganization();
+ cy.server();
+ cy.route('DELETE', 'apiman/organizations/**').as('deleteOrg');
+ cy.get('.dropdown-cog').click();
+ cy.get('.org-delete').click();
+ cy.get('.btn-danger').should('be.disabled');
+ cy.get('.apiman-form-control').click();
+ cy.get('.apiman-form-control').type('TestOrganization');
+ cy.get('.btn-danger').should('be.enabled').click();
+ cy.wait('@deleteOrg').should('have.property', 'status', 204);
+ })
+
+ it('Recreate the Organization via Button', () => {
+ cy.get('[title="Organizations"]').click();
+ cy.contains('My Organizations').click();
+ cy.get('#new-org').click();
+ cy.get('.btn-primary').should('be.disabled');
+ cy.get('#apiman-entityname').click();
+ cy.get('#apiman-entityname').type('TestOrganization');
+ cy.get('#apiman-description').type('Description of TestOrganization');
+ cy.get('.btn-primary').should('be.enabled').click();
+ })
+
+ it('Create the Plan and edit the description', () => {
+ cy.visitTestOrganization();
+ cy.contains('New Plan').click();
+ cy.get('#apiman-entityname').type('TestPlan');
+ cy.get('#apiman-description').click();
+ cy.get('#apiman-description').type('Description of TestPlan');
+ cy.get('#create-plan').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Description of TestPlan');
+ cy.get('#descriptionWrapper').click();
+ cy.get('.autoExpand').type('{selectall}{del}Edited Description of TestPlan');
+ cy.get('.fa-check').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Edited Description of TestPlan');
+ });
+
+ it('Delete the unlocked Plan', () => {
+ cy.visitTestPlan();
+ cy.server()
+ cy.route('DELETE', 'apiman/organizations/*/plans/*').as('deletePlan');
+ cy.get('.dropdown-cog').click();
+ cy.get('.plan-delete').click();
+ cy.get('.btn-danger').should('be.disabled');
+ cy.get('.apiman-form-control').click();
+ cy.get('.apiman-form-control').type('TestPlan');
+ cy.get('.btn-danger').should('be.enabled').click();
+ cy.get('@deletePlan').should('have.property', 'status', 204)
+ });
+
+ it('Recreate the Plan', () => {
+ cy.visitTestOrganization();
+ cy.contains('New Plan').click();
+ cy.get('#apiman-entityname').type('TestPlan');
+ cy.get('#apiman-description').click();
+ cy.get('#apiman-description').type('Description of TestPlan');
+ cy.get('#create-plan').click();
+ });
+
+ it('Add Rate Limiting Policy to the Plan and lock it', () => {
+ cy.visitTestPlan();
+ cy.get('#tab-policies').click();
+ cy.get('.pull-right:nth-child(1)').click();
+ cy.get('.select2-chosen:nth-child(1)').click();
+ cy.get('#ui-select-choices-row-0-8 > .select2-result-label').click();
+ cy.get('#add-policy').should('be.disabled');
+ cy.get('#num-requests').click();
+ cy.get('#num-requests').type('1');
+ cy.get('.btn-group:nth-child(4) > .btn .apiman-label-faded').click();
+ cy.get('.btn-group:nth-child(4) li:nth-child(2) .text').click();
+ cy.get('.filter-option > .apiman-label-faded').click();
+ cy.get('.btn-group:nth-child(6) li:nth-child(2) .text').click();
+ cy.get('#add-policy').should('be.enabled').click();
+ cy.get('.col-md-5 > :nth-child(3) > .btn').click();
+ cy.get('.apiman-label').should('have.text', 'Locked');
+
+
+ })
+
+ it('Create the API via NavBar and edit the description', () => {
+ cy.get('[title="APIs"]').click();
+ cy.contains('New API').click();
+ cy.get('#create-api').should('be.disabled');
+ cy.get('#apiman-entityname').type('TestApi');
+ cy.get('#apiman-description').click();
+ cy.get('#apiman-description').type('Description of TestApi');
+ cy.get('#create-api').should('be.enabled').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Description of TestApi');
+ cy.get('#descriptionWrapper').click();
+ cy.get('.autoExpand').type('{selectall}{del}Edited Description of TestApi');
+ cy.get('.fa-check').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Edited Description of TestApi');
+ });
+
+ it('Deletes the API', () => {
+ cy.visitTestApi();
+ cy.get('.dropdown-cog').click();
+ cy.get('.api-delete').click();
+ cy.get('.btn-danger').should('be.disabled');
+ cy.get('.apiman-form-control').click();
+ cy.get('.apiman-form-control').type('TestApi');
+ cy.get('.btn-danger').should('be.enabled').click();
+ })
+
+ it('Recreates the API via Button', () => {
+ cy.visitTestOrganization();
+ cy.get('#tab-apis').click();
+ cy.get('.btn-primary:nth-child(1)').click();
+ cy.get('#create-api').should('be.disabled');
+ cy.get('#apiman-entityname').type('TestApi');
+ cy.get('#apiman-description').click();
+ cy.get('#apiman-description').type('Description of TestApi');
+ cy.get('#create-api').should('be.enabled').click();
+ });
+
+ it('Add the API Implementation', () => {
+ cy.visitTestApi();
+ cy.get('#tab-impl').click();
+ cy.get('.apiman-form-control:nth-child(2)').click();
+ cy.get('.apiman-form-control:nth-child(2)').type('https://petstore.swagger.io/v2/');
+ cy.get('.actions > .btn-primary').click();
+ });
+
+ it('Choose Plan and publish API', () => {
+ cy.visitTestApi();
+ cy.get('#tab-plans').click();
+ cy.get('[style="padding: 4px 0;"] > .ng-pristine').click();
+ cy.contains('Save').click();
+ cy.contains('Publish').should('be.enabled');
+ cy.contains('Publish').click();
+ })
+
+ it('Create the Client via NavBar and edit the description', () => {
+ cy.get('[title="Clients"]').click();
+ cy.contains('New Client').click();
+ cy.get('#apiman-entityname').type('TestClient');
+ cy.get('#apiman-description').type('Description of TestClient');
+ cy.get('#create-client').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Description of TestClient')
+ cy.get('#descriptionWrapper').click();
+ cy.get('.autoExpand').type('{selectall}{del}Edited Description of TestClient');
+ cy.get('.fa-check').click();
+ cy.get('#descriptionWrapper').should('include.text', 'Edited Description of TestClient')
+ });
+
+ it('Delete the Client', () => {
+ cy.visitTestClient();
+ cy.get('.fa-cog').should('be.visible').click();
+ cy.get('.client-app-delete').click();
+ cy.get('.btn-danger').should('be.disabled');
+ cy.get('.apiman-form-control').click();
+ cy.get('.apiman-form-control').type('TestClient');
+ cy.get('.btn-danger').should('be.enabled').click();
+ });
+
+ it('Recreate the Client via Button', () => {
+ cy.visitTestOrganization();
+ cy.get('#tab-clients').click();
+ cy.get('.btn-primary').click();
+ cy.get('#create-client').should('be.disabled');
+ cy.get('#apiman-entityname').type('TestClient');
+ cy.get('#apiman-description').type('Description of TestClient');
+ cy.get('#create-client').should('be.enabled').click();
+ });
+
+ it('Create the Contract', () => {
+ cy.visitTestClient();
+ cy.get('#tab-contracts').click();
+ cy.get('.pull-right:nth-child(2)').click();
+ cy.get('.api > .body').click();
+ cy.get('#api > span').click();
+ cy.get('.item').click();
+ cy.get('.modal-footer > .btn-primary').click();
+ cy.get('#create-contract').click();
+ });
+
+ it('Register the Client', () => {
+ cy.visitTestClient();
+ cy.get('.btn-primary:nth-child(1)').click();
+ cy.get('.apiman-label-success').should('have.text', 'Registered');
+ });
+});

ADD
cypress/plugins/index.js
+/// <reference types="cypress" />
+// ***********************************************************
+// This example plugins/index.js can be used to load plugins
+//
+// You can change the location of this file or turn off loading
+// the plugins file with the 'pluginsFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/plugins-guide
+// ***********************************************************
+
+// This function is called when a project is opened or re-opened (e.g. due to
+// the project's config changing)
+
+/**
+ * @type {Cypress.PluginConfig}
+ */
+// eslint-disable-next-line no-unused-vars
+module.exports = (on, config) => {
+ // `on` is used to hook into various events Cypress emits
+ // `config` is the resolved Cypress config
+}

ADD
cypress/support/commands.js
+// ***********************************************
+// This example commands.js shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add('login', (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
+
+
+Cypress.Commands.add('typeLogin', (user, pw) => {
+ cy.get('#username').type(user);
+ cy.get('#password').type(pw);
+ cy.get('#kc-login').click();
+})
+
+Cypress.Commands.add('visitTestOrganization', () => {
+ cy.get('[title="Organizations"]').click();
+ cy.contains('My Organizations').click();
+ cy.contains('TestOrganization').click();
+})
+
+Cypress.Commands.add('visitTestPlan', () => {
+ cy.visitTestOrganization();
+ cy.get('#tab-plans').click();
+ cy.contains('TestPlan').click();
+})
+
+Cypress.Commands.add('visitTestApi', () => {
+ cy.visitTestOrganization();
+ cy.get('#tab-apis').click();
+ cy.contains('TestApi').click();
+})
+
+Cypress.Commands.add('visitTestClient', () => {
+ cy.visitTestOrganization();
+ cy.get('#tab-clients').click();
+ cy.contains('TestClient').click();
+})

ADD
cypress/support/index.js
+// ***********************************************************
+// This example support/index.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 './commands'
+
+// Alternatively you can use CommonJS syntax:
+// require('./commands')

test(ui): add first Cypress test

Cypress is a comprehensive e2e testing framework that runs through a
browser (e.g. chrome, firefox), and allows simulation of real users
interacting directly with the system.

Closes #1049