Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing Exercise - E2E Cypress Testing #80

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ docker-compose.override.yml
docker-sync.yml
node
node_modules
e2e/cypress/support/pages
115 changes: 115 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# E2E Cypress Tests
Brightspot Training E2E Cypress Example

[Cypress](https://docs.cypress.io/guides/overview/why-cypress) is an automated testing tool for running end-to-end tests within the CMS and styleguide. With Cypress, you can easily create tests for modern web applications, debug them visually, and automatically run them in your continuous integration builds, on your local machine, or against lower environments.

As part of our testing practices, we’ve developed a library of useful commands that simplifies the process of writing scripts for complex CMS test cases. [cypress-brightspot](https://github.com/perfectsense/cypress-brightspot) provides extendable classes, ready-made page objects, useful custom commands to be used for writing quick Brightspot CMS Cypress tests.


Table Of Contents
-----------------
<!-- TOC -->

- [E2E Cypress Tests](#e2e-cypress-tests)
- [Table Of Contents](#table-of-contents)
- [Local Setup](#local-setup)
- [Development](#development)
- [Helpful Cypress Starter Kit](#helpful-cypress-starter-kit)
- [Cypress-Brightspot](#cypress-brightspot)
- [Edit Page Builder](#edit-page-builder)

<!-- /TOC -->
<!-- /TOC -->

Local Setup
-----------
1. Start the training projects local dev environment following the README in the project root.
1. Run `yarn cache clean && yarn`
2. Run `./gradlew`
3. Run `docker compose up -d`
2. Naviagate to the `/e2e` directory.
3. Run `npm install` to install Cypress and all necessary dependencies.
4. Run `npx cypress open` to open Cypress GUI and begin running tests!

When testing locally, occasionally wipe relevant docker volumes to ensure consistent E2E testing.
1. Run `docker-compose down`
2. Run `docker volume rm $(docker volume ls -q -f name=training-*)`
3. Run `docker-compose up -d`

Development
-----------

### Helpful Cypress Starter Kit
- [Getting Started](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress)
- [Test Organization](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress)
- [CSS Selectors and Cypress](https://www.browserstack.com/guide/cypress-css-selectors)

### Cypress-Brightspot
The test methods utilizes page object structure to complete standard Brightspot publishing functionality. Most of that logic is contained in the `cypress-brightspot` utility package which we can extend and augment for our own purposes.

An example test using an imported page object straight from our library might look like:

```
import { loginPage, sitesPage } from '@cypress-brightspot/cypress-brightspot'

describe('Example Login Test', () => {
it('should login and navigate to Sites and Settings', () => {
cy.visit('/cms')
loginPage.login(username, password)
sitesPage.openSiteSettings()

// And we can go on to publish Site Settings, Articles, etc...
})
})
```

If you're interested in changing some of our existing functionality by extending or overriding our exported objects or classes, it might look like:

```
// Extend All Page class from cypress-brightspot package
import { BaseCmsPage } from "@cypress-brightspot/cypress-brightspot";

class ExampleArticlePage extends BaseCmsPage {
constructor(){
super();
this.elements.headline = '.selector'
}

getHeadline(){
cy.log('Extending imported cypress-brightspot class');
return cy.get(this.elements.newPageElement);
}
}

// Export example page object
export const onExampleArticlePage = new ExampleArticlePage()
```

If you're interested in just updating field selectors without overriding existing logic use `setElementSelector(element, value)` utility method and pass the element name and update value you need to set

```
it('Should successfully allow the user to update page elements mid-test', () => {
loginPage.visit();
expect(loginPage.elements.loginButton).to.equal('old-selector');
loginPage.setElementSelector('loginButton', 'new-selector');
expect(loginPage.elements.loginButton).to.equal('new-selector');
});
```

### Edit Page Builder
To generate Page Object classes for Cypress from your JSON configuration, follow these steps:

1. Run the following command to generate the JSON file containing the object type definitions:
```
./gradlew web:exportObjectTypes
```

2. Once `objectTypes.json` is available, you can run the `editPageBuilder.js` script to generate Page Object files:

```
node ./node_modules/@cypress-brightspot/cypress-brightspot/examples/editPageBuilder.js "../web/build/objectTypes.json" "./cypress/support/pages"
```
The first argument (`../web/build/objectTypes.json`) specifies the path to the generated `objectTypes.json`.
The second argument (`./support/pages`) specifies the directory where the generated Page Object files will be created.

3. After running the script, you should see the generated Page Object classes in the specified directory. Each class file corresponds to an object type and follows the Cypress Page Object Model structure, ready for use in your tests.
44 changes: 44 additions & 0 deletions e2e/cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { defineConfig } = require("cypress");
const webpackPreprocessor = require("@cypress/webpack-preprocessor");

// Set isLower to true if you are targetting a lower environment
const isLower = false;

// Default values for environment variables
const defaultEnv = {
debugUsername: process.env.CYPRESS_debugUsername || "",
debugPassword: process.env.CYPRESS_debugPassword || "",
host: process.env.CYPRESS_baseUrl || "http://localhost",
};

// Load local configuration if available
if (isLower) {
try {
const lowerConfig = require("./cypress.lower.json");
Object.assign(defaultEnv, lowerConfig.env || {});
} catch (e) {
// Ignore error if the file doesn't exist
}
}

module.exports = defineConfig({
defaultCommandTimeout: 15000,
pageLoadTimeout: 120000,
responseTimeout: 120000,
requestTimeout: 120000,
e2e: {
specPattern: [
"./node_modules/@cypress-brightspot/cypress-brightspot/src/shared-tests/e2e/*.cy.js",
"cypress/e2e/brightspot-examples/*.cy.js",
"cypress/e2e/*.cy.js",
],
baseUrl: defaultEnv.host,
watchForFileChanges: false,
chromeWebSecurity: false,
waitForAnimations: true,
setupNodeEvents(on, config) {
on("file:preprocessor", webpackPreprocessor());
},
},
env: defaultEnv,
});
7 changes: 7 additions & 0 deletions e2e/cypress.lower.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"env": {
"debugUsername": "DEBUG",
"debugPassword": "DEBUG_PASSWORD",
"host": "https://cms.qa.brightspot.psdops.com"
}
}
60 changes: 60 additions & 0 deletions e2e/cypress/e2e/brightspot-examples/article-example-test.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Import the necessary cypress-brightspot page objects we will need for our test.
*
* The complete list of available page objects can be found in the module README here: https://www.npmjs.com/package/@cypress-brightspot/cypress-brightspot#page-objects
*/
import {
deleteArticleIfExist,
loginPage,
homePage,
articleEditPage,
} from "@cypress-brightspot/cypress-brightspot";

/**
* Import JSON objects containing mock test data.
*
* When developing out tests, we can create JSON files as needed to mock test data and reuse them across different tests.
* Some methods intake JSON object parameters, so you may need to inspect those methods to determine what attributes should be present in the JSON file.
*/
import user from "../../fixtures/user.json";
import site from "../../fixtures/site.json";
import article from "../../fixtures/article.json";

describe("Create Article Test", () => {
// Before we begin our test, we should reset the test data in our environment by deleting the Article if it already exists
beforeEach(() => {
deleteArticleIfExist(site, article, user);
});

it("Should publish an Article successfully", () => {
// As we complete different actions, we will use different page objects following the flow of our Test User.
// To start, we will use the loginPage object since that is the current page we will be manipulating.
loginPage.visit();
loginPage.loginUserViaUI(user);

// Now, on the CMS Homepage, we will use the homePage object to control our Test User's actions and open a new Article type.
homePage.switchSites(site.name);
homePage.createContentType("Article");

// On the Article Edit Page, we will use the articleEditPage object to fill in fields, publish, and verify success.
articleEditPage.getHeadlineField().type(article.headline);
articleEditPage.getSubHeadlineField().type(article.subHeadline);
articleEditPage.getBodyField().type(article.body);

articleEditPage.getPublishButton().click();
articleEditPage.getSuccessMessage().should("be.visible");
});

it("Should add a Section to an Article", () => {
/**
* All the necessary methods and page objects to do the below should already exist in cypress-brightspot.
*
* Complete the following steps:
* 1) Re-use the steps from the previous test to create an Article
* 2) Navigate to the Homepage
* 3) Search for the newly published Article
* 4) Set the 'Inspire Sports' Section on the Article
* 5) Publish the Article
*/
});
});
28 changes: 28 additions & 0 deletions e2e/cypress/e2e/brightspot-examples/author-example-test.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Import the necessary cypress-brightspot page objects we will need for our test.
*
* The complete list of available page objects can be found in the module README here: https://www.npmjs.com/package/@cypress-brightspot/cypress-brightspot#page-objects
*/
import { loginPage, homePage } from "@cypress-brightspot/cypress-brightspot";

// Import JSON objects containing mock test data.
import user from "../../fixtures/user.json";
import site from "../../fixtures/site.json";
import author from "../../fixtures/author.json";

// Importing page object form authorEditPage.js
import { authorEditPage } from "../../support/authorEditPage";

describe("Create Author Test", () => {
it("Should publish an Author successfully", () => {
/**
* Complete the following steps:
* 1) Create AuthorEditPage class in '/support/AuthorEditPage.js' to publish all necessary fields.
* AuthorEditPage should extend BaseContentTypePage class from cypress-brightspot.
*
* 2) Publish a Author with all fields using '/fixtures/author.json' with test data for each field.
*
* 3) Verify Author fields display correctly on the FE
*/
});
});
Loading
Loading