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

E2e protractor removal poc #740

Open
wants to merge 5 commits into
base: main
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 .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18.20.5
2 changes: 1 addition & 1 deletion docs/DEFINITION_OF_DONE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
- [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute)
- Security (where applicable)
- New behavior has been manually tested and verified
- Changes tested in all [supported browsers](./docs/FAQ.md#what-browsers-are-supported-by-nova-ui)
- Changes tested in all [supported browsers](./FAQ.md#what-browsers-are-supported-by-nova-ui)
- Automation tests (visual / unit / e2e / atoms) have been created and are passing
- Strongly favor unit tests over e2e/visual
- Business logic (e.g. controllers, services, filters, etc) should be unit tested - goal for coverage is at least 80%.
Expand Down
73 changes: 73 additions & 0 deletions docs/E2E_TEST_ATOMS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Atoms: Page Object Pattern for Component Harnesses

Atoms, based on the Page Object Pattern, are an abstraction layer designed to represent and interact with UI components in end-to-end testing frameworks. This approach provides a clean and reusable way to manage the complexity of user interfaces, ensuring that tests remain maintainable and robust.

## What are Atoms?
Atoms are essentially small, reusable units that encapsulate the logic for interacting with specific UI components. Each atom corresponds to a single component or element in the user interface, such as a button, input field, or dropdown menu. Atoms:

- Abstract away the underlying framework-specific details.
- Expose intuitive methods for interacting with the component.
- Make tests more readable and easier to maintain.

## Benefits of Using Atoms

1. **Reusability**: Atoms can be used across multiple test cases, reducing duplication.
2. **Encapsulation**: Encapsulating component interaction logic within atoms ensures that changes in the UI only require updates in one place.
3. **Readability**: Test scripts become more declarative and easier to understand.
4. **Framework Agnostic**: Atoms can be adapted to work with various testing frameworks, ensuring flexibility.
5. **Scalability**: Using atoms helps scale the test suite as the application grows, maintaining structure and clarity.

## Structure of an Atom

An atom typically consists of:

1. **Selectors**: Identify the element(s) on the page.
2. **Actions**: Define methods to interact with the element(s) (e.g., click, type).
3. **Assertions**: Provide helper methods to verify the state of the component.

### Example: Button Atom (Using Playwright)

```javascript
class ButtonAtom {
constructor(page, selector) {
this.page = page;
this.selector = selector;
}

async click() {
await this.page.click(this.selector);
}

async isVisible() {
return await this.page.isVisible(this.selector);
}

async getText() {
return await this.page.textContent(this.selector);
}
}

// Usage in a test
const button = new ButtonAtom(page, 'button.submit');
await button.click();
expect(await button.isVisible()).toBe(true);
```

## Atoms vs. Traditional Page Objects

| Aspect | Atoms | Traditional Page Objects |
|------------------------|---------------------------------------------|-------------------------------------|
| Scope | Focused on individual components | Represents entire pages |
| Reusability | High (can be shared across pages) | Moderate (specific to a page) |
| Granularity | Fine-grained (component-level abstraction) | Coarse-grained (page-level abstraction) |
| Maintenance | Easier (localized changes) | Harder (impacts multiple test cases) |

## Implementing Atoms in Your Test Suite

1. **Identify Components**: Break down your application into reusable UI components.
2. **Define Atoms**: Create atom classes for each component, encapsulating their interaction logic.
3. **Integrate into Tests**: Use atoms in your test scripts to interact with the application.
4. **Refactor Regularly**: Keep atoms up to date as the UI evolves.

## Conclusion
The atoms approach, inspired by the Page Object Pattern, provides a powerful abstraction for managing UI components in end-to-end tests. By leveraging atoms, teams can improve test maintainability, readability, and scalability, making their test suites more robust and easier to manage.
49 changes: 49 additions & 0 deletions docs/E2E_TEST_FRAMEWORK_CHOOSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Comparison of End-to-End Testing Frameworks as Protractor Replacements

Protractor has been deprecated, and developers are seeking alternative
end-to-end testing frameworks to ensure reliable testing of web applications.
Below is a comparison of popular e2e testing frameworks based on their pros and
cons.

## Comparison Table

| Framework | Pros | Cons |
|-----------------|----------------------------------------------------------------------|----------------------------------------------------------------|
| **Cypress** | - Easy setup and intuitive API | - Limited cross-browser support (no support for Safari or IE) |
| | - Excellent debugging tools with real-time reloading | - High memory consumption for large-scale tests |
| | - Built-in features for visual testing and inspecting test execution | - Limited scalability for complex, multi-browser environments |
| **Nightwatch** | - Full Selenium WebDriver support | - Outdated documentation and smaller community |
| | - Supports a11y testing with accessibility tools | - Slower updates compared to newer frameworks |
| | - Cross-browser testing capabilities | - Requires more configuration for advanced features |
| **WebdriverIO** | - Versatile with support for both Selenium and Chromium-based tools | - Steeper learning curve for beginners |
| | - Extensive plugin ecosystem for customization | - Slightly slower execution compared to lightweight frameworks |
| | - Built-in support for a11y and visual regression testing | - Debugging can be more complex |
| **Puppeteer** | - Headless browser testing with excellent performance | - Limited to Chromium-based browsers |
| | - Simple and fast setup | - Lacks built-in support for cross-browser testing |
| | - Great for visual regression testing | - Limited community compared to Selenium |
| **Playwright** | - Cross-browser support (Chromium, Firefox, WebKit) | - Steeper learning curve compared to simpler frameworks |
| | - Powerful API for modern testing needs | - Requires more boilerplate for simple tests |
| | - Supports a11y testing and robust visual testing features | - Comparatively newer, smaller community than Selenium |

## Summary

Each framework has its strengths and weaknesses, and the choice largely depends
on the specific requirements of your project. Additionally, Protractor users
should consider frameworks that support maintaining an abstraction level similar
to Protractor’s page objects or atoms. This abstraction helps in organizing test
code effectively and enhancing reusability.

- Cypress is ideal for developers looking for simplicity and an excellent user
experience but lacks comprehensive browser support.
- Nightwatch is a good option
for developers familiar with Selenium and needing cross-browser support.
- WebdriverIO offers versatility and extensibility with strong support for
accessibility and visual testing.
- Puppeteer is lightweight and
Chromium-specific, with great visual regression capabilities.
- Playwright is great for modern applications with a need for cross-browser, accessibility, and
visual testing.

### Note
To reduce amount of the code to rewrite we should also consider the [Atoms](./E2E_TEST_ATOMS.md)
which we do have implemented in bits/charts/dashboard and support for the jasmine
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,28 @@
"@angular/platform-browser-dynamic": "16.2.12",
"@angular/router": "16.2.12",
"@axe-core/webdriverjs": "4.10.1",
"@badisi/wdio-harness": "^4.1.0",
"@compodoc/compodoc": "1.1.23",
"@percy/cli": "1.30.2",
"@percy/protractor": "2.0.1",
"@schematics/angular": "16.2.16",
"@stackblitz/sdk": "1.11.0",
"@types/jasmine": "4.6.4",
"@swc/core": "^1.10.1",
"@types/jasmine": "^5.1.5",
"@types/jasminewd2": "2.0.13",
"@types/lodash": "4.17.13",
"@types/node": "18.19.64",
"@types/proxyquire": "1.3.31",
"@types/selenium-webdriver": "3.0.26",
"@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.62.0",
"@wdio/cli": "^9.4.5",
"@wdio/codemod": "^0.12.0",
"@wdio/dot-reporter": "^9.4.4",
"@wdio/jasmine-framework": "^9.4.5",
"@wdio/junit-reporter": "^9.4.4",
"@wdio/local-runner": "^9.4.5",
"@wdio/spec-reporter": "^9.4.4",
"copyfiles": "2.4.1",
"core-js": "3.39.0",
"eslint": "8.57.1",
Expand All @@ -49,6 +58,7 @@
"jasmine-core": "4.0.1",
"jasmine-reporters": "2.5.2",
"jasmine-spec-reporter": "7.0.0",
"jscodeshift": "^17.1.1",
"jsonc-parser": "3.3.1",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.1",
Expand All @@ -63,6 +73,7 @@
"moment": "2.29.4",
"moment-timezone": "0.5.46",
"ng-packagr": "16.2.3",
"nightwatch": "^3.9.0",
"npm-run-all": "4.1.5",
"prettier": "2.8.8",
"prettier-plugin-sort-json": "0.0.3",
Expand Down
86 changes: 86 additions & 0 deletions packages/bits/nightwatch.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Refer to the online docs for more details:
// https://nightwatchjs.org/gettingstarted/configuration/
//

// _ _ _ _ _ _ _
// | \ | |(_) | | | | | | | |
// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__
// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \
// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | |
// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_|
// __/ |
// |___/

module.exports = {
// An array of folders (excluding subfolders) where your tests are located;
// if this is not specified, the test source must be passed as the second argument to the test runner.
src_folders: ['nightwatch'],

// See https://nightwatchjs.org/guide/concepts/page-object-model.html
page_objects_path: [],

// See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html
custom_commands_path: [],

// See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html
custom_assertions_path: [],

// See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html
plugins: [],

// See https://nightwatchjs.org/guide/concepts/test-globals.html
globals_path: '',

webdriver: {},

test_workers: {
enabled: true
},
test_settings: {
default: {
disable_error_log: false,
launch_url: 'http://localhost:4200',

screenshots: {
enabled: true,
path: 'screens',
on_failure: true
},

desiredCapabilities: {
browserName: 'chrome'
},

webdriver: {
start_process: true,
server_path: ''
},

},

chrome: {
desiredCapabilities: {
browserName: 'chrome',
'goog:chromeOptions': {
// More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/
args: [
//'--no-sandbox',
//'--ignore-certificate-errors',
//'--allow-insecure-localhost',
//'--headless=new'
]
}
},

webdriver: {
start_process: true,
server_path: '',
cli_args: [
// --verbose
]
}
},

},

};
4 changes: 3 additions & 1 deletion packages/bits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@
"visual:watch": "npx watch \"yarn run visual:base\" src demo spec --watch=1",
"xliff": "run-s xliff:*",
"xliff:demo": "ng extract-i18n demo && ngx-extractor -i \"src/**/*.ts\" \"demo/src/**/*.ts\" -f xlf -o .tmp-i18n/messages.xlf && xliffmerge --profile xliffmerge-examples.json",
"xliff:lib": "ng extract-i18n lib && ngx-extractor -i \"src/**/*.ts\" -f xlf -o .tmp-i18n/messages.xlf && xliffmerge --profile xliffmerge.json"
"xliff:lib": "ng extract-i18n lib && ngx-extractor -i \"src/**/*.ts\" -f xlf -o .tmp-i18n/messages.xlf && xliffmerge --profile xliffmerge.json",
"wdio": "wdio wdio.conf.ts --suite e2e --spec ./tests/wdio/components/button/button.e2e.ts",
"nightwatch": "nightwatch ./tests/nightwatch/components"
},
"typings": "public_api.d.ts",
"version": "16.0.2-1",
Expand Down
Loading