Skip to content

Commit

Permalink
Merge pull request #1417 from aravindb24/development
Browse files Browse the repository at this point in the history
UI-Testing
  • Loading branch information
huss authored Jan 23, 2025
2 parents 355bbb7 + e345a24 commit d125ad7
Show file tree
Hide file tree
Showing 13 changed files with 448 additions and 6 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,7 @@ nohup.out
.vscode/settings.json

# tmp file
src/server/tmp/*
src/server/tmp/*

#ui-testing screenshots
src/cypress/screenshots/*
16 changes: 16 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { defineConfig } from 'cypress';

export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
specPattern: 'src/cypress/e2e/*.cy.ts',
supportFile: 'src/cypress/support/e2e.ts',
screenshotsFolder: 'src/cypress/screenshots/e2e'
}
});
38 changes: 34 additions & 4 deletions docker-compose.yml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ services:
- POSTGRES_PASSWORD=pleaseChange # default postgres password that should be changed for security.
volumes:
- ./postgres-data:/var/lib/postgresql/data/pgdata
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 10s
retries: 3
# ports:
# - "5432:5432"
# Uncomment the above lines to enable access to the PostgreSQL server
Expand Down Expand Up @@ -68,10 +73,15 @@ services:
# and comment out the debug port and 3000:3000 line above
# Don't bring this up without the DB
depends_on:
- database
# database:
# - database
database:
# We need the database and it has to be ready for work (see healthcheck above).
# condition: service_healthy
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000"]
interval: 10s
timeout: 5s
retries: 5
# Lets docker compose up work right
# If environment variable install_args is not set then it becomes blank without warning user.
command:
Expand All @@ -81,4 +91,24 @@ services:
"${install_args:-}"
]
# Use this if you are using a docker-compose that is earlier than version 2 and comment out the one above.
# command: ["bash", "./src/scripts/installOED.sh"]
# command: ["bash", "./src/scripts/installOED.sh"]

# Cypress testing service
cypress:
image: cypress/included
profiles:
- ui-testing
environment:
- CYPRESS_BASE_URL=http://web:3000
- DISPLAY=:99
working_dir: /usr/src/app
depends_on:
web:
condition: service_healthy
volumes:
- ./:/usr/src/app
entrypoint: >
/bin/sh -c "
rm -f /tmp/.X99-lock &&
Xvfb :99 -screen 0 1024x768x16"
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 98 additions & 0 deletions src/cypress/e2e/general_ui.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// TODO: The commented out tests were attempts to test the UI that are
// not yet working. They need to be fixed.

describe('UI Functionality Tests for Open Energy Dashboard', () => {
beforeEach(() => {
// Visit the page before each test
cy.visit('/');
});

// it('Tests all buttons functionality', () => {
// // Ensure buttons are visible and clickable
// cy.get('button').should('have.length.greaterThan', 0); // Ensure buttons exist
// cy.get('button').each((button) => {
// cy.wrap(button).should('be.visible'); // Check visibility
// cy.wrap(button).click({ force: true }); // Test click
// });
// });

// it('Tests all form inputs', () => {
// // Test text and email inputs
// cy.get('input[type="text"], input[type="email"]').each((input) => {
// cy.wrap(input).should('be.visible').type("Sample Text"); // Check visibility and type
// });

// // Test password inputs
// cy.get('input[type="password"]').each((input) => {
// cy.wrap(input).should('be.visible').type('password');
// });

// // Test textareas
// cy.get('textarea').each((textarea) => {
// cy.wrap(textarea).should('be.visible').type('Sample description text');
// });

// // Submit forms
// cy.get('form').each((form) => {
// cy.wrap(form).within(() => {
// cy.get('button[type="submit"], input[type="submit"]').click({ force: true });
// });
// });
// });

// it('Tests dropdown menus', () => {
// // Ensure dropdowns are visible and options are selectable
// cy.get('select').should('have.length.greaterThan', 0); // Ensure dropdowns exist
// cy.get('select').each((dropdown) => {
// cy.wrap(dropdown)
// .should('be.visible') // Check visibility
// .find('option')
// .should('have.length.greaterThan', 1); // Ensure options exist

// // Select the first option (change index as needed)
// cy.wrap(dropdown).select(0);
// });
// });

it('Tests links for navigation', () => {
// Ensure links have valid href attributes
cy.get('a[href]').each((link) => {
cy.wrap(link).should('have.attr', 'href').and('not.be.empty'); // Check href exists
});
});

// it('Tests modals for correct behavior', () => {
// // Ensure modals can be triggered and closed
// cy.get('[data-bs-toggle="modal"]').each((modalTrigger) => {
// cy.wrap(modalTrigger).should('be.visible').click(); // Trigger modal
// cy.get('.modal').should('be.visible'); // Check modal is visible
// cy.get('.modal .close').click(); // Close modal
// cy.get('.modal').should('not.be.visible'); // Check modal is closed
// });
// });
// it('Tests tables for data population', () => {
// // Ensure tables are populated with rows
// cy.get('table').should('have.length.greaterThan', 0); // Ensure tables exist
// cy.get('table').each((table) => {
// cy.wrap(table).find('tr').should('have.length.greaterThan', 1); // At least one row
// });
// });
// it('Tests interactive inputs (checkboxes and radio)', () => {
// // Check and uncheck checkboxes
// cy.get('input[type="checkbox"]').each((checkbox) => {
// cy.wrap(checkbox).check({ force: true }).should('be.checked'); // Check it
// cy.wrap(checkbox).uncheck({ force: true }).should('not.be.checked'); // Uncheck it
// });
// cy.get('input[type="radio"]').each((radio) => {
// cy.wrap(radio).check({ force: true }).should('be.checked'); // Check radio
// });
// });
// it('Tests for dynamic elements', () => {
// // Ensure dynamically loaded elements exist and are visible
// cy.get('[data-dynamic]').should('exist').and('be.visible');
// });
});
38 changes: 38 additions & 0 deletions src/cypress/e2e/hideOptions.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

describe("Options Menu Tests", () => {
beforeEach(() => {
// Visit the OED application
cy.visit("/");
});

it("should toggle the visibility of graph configuration options when 'Hide options' is clicked", () => {
// Open the Options dropdown
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li:nth-child(3) > a").click();

// Click "Hide options"
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li.dropdown.show.nav-item > div > button:nth-child(2)").click();

// Verify that graph configuration options are hidden
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li:nth-child(2) > a").should("not.exist"); // pages
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li:nth-child(3) > a").should("not.exist"); // options
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > a:nth-child(4)").should("not.exist"); // help



// Click "Menu" again to toggle visibility back
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > button").click();
cy.get("body > div:nth-child(4) > div > div.modal.fade.show > div > div > div.modal-header > div > h6 > div > nav > div > ul > li:nth-child(3) > a").click();
cy.get("body > div:nth-child(4) > div > div.modal.fade.show > div > div > div.modal-header > div > h6 > div > nav > div > ul > li.dropdown.show.nav-item > div > button:nth-child(2)").click();



cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li:nth-child(2) > a").should("be.visible"); // pages
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li:nth-child(3) > a").should("be.visible"); // options
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > a:nth-child(4)").should("be.visible"); // help


});
});
25 changes: 25 additions & 0 deletions src/cypress/e2e/initLangTest.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

describe("Language Selector Tests", () => {
beforeEach(() => {
// Visit the OED application
cy.visit("/");
});

it("should update the UI and React state when the language is changed", () => {
// Open the language selection dropdown

cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li:nth-child(3) > a").click();
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li.dropdown.show.nav-item > div > div.dropdown.dropstart > a").click();


// Select a specific language (e.g., Spanish)
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li.dropdown.show.nav-item > div > div.dropdown.dropstart.show > div").contains("Español").click();

// Verify that UI elements are updated to the selected language
cy.get("body").should("contain", "Tipo de gráfico"); // Example text in Spanish for "Graph Type"

});
});
92 changes: 92 additions & 0 deletions src/cypress/e2e/line.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// TODO These tests assume a clean setup/test data. In the future we should wipe the database
// and load the needed data (maybe without the actual meter data until needed) in a similar way
// to how the Chai/Mocha tests work.

// This test is a great template to start with for understanding testing using cypress.
describe('testing line graph selecting groups and meters and test for plotly line graph ', () => {
beforeEach(() => {
// Visit the OED application
cy.visit('/');
});

// Graph Type is Line.
// TODO This is the default line type when OED is created but can be changed by the admin. It might be good
// to first set it to this value at some point (but it does make another possible failure).
it('should display a line graph type automatically', () => {
// Find the line chart
cy.get('#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-2.d-none.d-lg-block > div > div.dropdown > button').should('have.text', 'Line');
cy.screenshot('ShowLineTypeOption')

});
// Checking all group options
it('groups should be clickable and display 10 options and 1 incompatible option', () => {
// Find and click the group
cy.get('#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-2.d-none.d-lg-block > div > div:nth-child(4) > div:nth-child(2) > div > div.css-1fdsijx-ValueContainer').click().should('be.visible');
// Check if the 10 options are there
cy.get('#react-select-2-listbox > div:nth-child(1) > div:nth-child(2)').children().should('have.length', 10);
cy.get('#react-select-2-group-0-heading > div > span.badge.bg-primary.rounded-pill').should('have.text', '10');
// check if the incompatible option is visible and not clickable
cy.get('#react-select-2-option-1-0').should('exist')
.should('have.attr', 'aria-disabled', 'true') // Check the aria-disabled attribute
.should('have.attr', 'tabindex', '-1') // Validate tabindex to confirm it’s not focusable
});
// Checking all meter options
it('selecting menu option should display 25 options and plotly graph', () => {
// open menu option
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-2.d-none.d-lg-block > div > div:nth-child(4) > div:nth-child(4) > div > div.css-1fdsijx-ValueContainer").click().should('be.visible');
// Verify all options
cy.get("#react-select-3-listbox > div > div:nth-child(2)").children().should('have.length', 25);
// click on Cos 23 Min KWH
cy.get("#react-select-3-option-0-0").should('exist').click();

// plotly element show be dynamically created: check for plotly display
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div")
.should('exist');

//meter name should be displayed
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(3) > g.infolayer > g.legend > g > g > g > text").should('have.text', 'Cos 23 Min kWh');

// checking x-axis labels
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.xaxislayer-above > g:nth-child(1) > text").should('have.text', 'Mar 2020');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.xaxislayer-above > g:nth-child(2) > text").should('have.text', 'May 2020');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.xaxislayer-above > g:nth-child(3) > text").should('have.text', 'Jul 2020');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.xaxislayer-above > g:nth-child(4) > text").should('have.text', 'Sep 2020');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.xaxislayer-above > g:nth-child(5) > text").should('have.text', 'Nov 2020');

// checking y-axis labels
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.yaxislayer-above > g:nth-child(1) > text").should('have.text', '0');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.yaxislayer-above > g:nth-child(2) > text").should('have.text', '0.5');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.yaxislayer-above > g:nth-child(3) > text").should('have.text', '1');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.yaxislayer-above > g:nth-child(4) > text").should('have.text', '1.5');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.yaxislayer-above > g:nth-child(5) > text").should('have.text', '2');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.yaxislayer-above > g:nth-child(6) > text").should('have.text', '2.5');
cy.get("#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.yaxislayer-above > g:nth-child(7) > text").should('have.text', '3');


/*
TODO: We want to check if the graph displays correct information.
After a meter or group is selected a get request is made to the server to get the data for the graph to the following endpoint:
http://localhost:3000/api/unitReadings/line/meters/21?timeInterval=all&graphicUnitId=1
The response is a json object with the data that is used to plot the graph.
It might be possible to check the json object to see if the data is correct.
Testing methods to
The line in the graph is rendered as path class ="js-line"
Main Graph:
#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(1) > g.cartesianlayer > g > g.plot > g > g > g.lines > path
Drag Bar:
#root > div:nth-child(2) > div.container-fluid.flexGrowOne > div > div.col-12.col-lg-10.align-self-auto.text-center > div > div.js-plotly-plot > div > div > svg:nth-child(3) > g.infolayer > g.rangeslider-container > g.rangeslider-rangeplot.xy > g.plot > g > g > g.lines > path
We could possibly simulate moving a mouse over the graph to check if the data is correct.
Clicking and dragging the bottom drag bar then refreshing the page
And checking the time interval in which the data is displayed. (From seconds to day...)
*/
});
});
25 changes: 25 additions & 0 deletions src/cypress/e2e/pagesGroups.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

describe("Navigation to Groups Page", () => {
beforeEach(() => {
// Visit the application home page
cy.visit("/");
});

it("should navigate to the Groups page when 'Groups' is clicked from the Pages dropdown", () => {
// Open the Pages dropdown
cy.get("#header > div > div.col-4.justify-content-end.d-lg-flex.d-none > div > nav > div > ul > li:nth-child(2) > a").click();

// Click the 'Groups' option in the dropdown
cy.contains("Groups").click();

// Verify that the Groups page has the correct title
cy.get("h2").should("have.text", "Groups");

// Verify the tooltip icon is present in the title
cy.get("h2 > div > i").should("have.attr", "data-for", "groups");
cy.get("h2 > div > i").should("have.attr", "data-tip", "help.groups.groupview");
});
});
Loading

0 comments on commit d125ad7

Please sign in to comment.