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

feat: soft assertion #4728

Merged
merged 4 commits into from
Jan 10, 2025
Merged

feat: soft assertion #4728

merged 4 commits into from
Jan 10, 2025

Conversation

kobenguyent
Copy link
Collaborator

@kobenguyent kobenguyent commented Jan 9, 2025

Motivation/Description of the PR


module hopeThat

hopeThat is a utility function for CodeceptJS tests that allows for soft assertions. It enables conditional assertions without terminating the test upon failure. This is particularly useful in scenarios like A/B testing, handling unexpected elements, or performing multiple assertions where you want to collect all results before deciding on the test outcome.

Use Cases

  • Multiple Conditional Assertions: Perform several assertions and evaluate all their outcomes together.
  • A/B Testing: Handle different variants in A/B tests without failing the entire test upon one variant's failure.
  • Unexpected Elements: Manage elements that may or may not appear, such as "Accept Cookie" banners.

Examples

Multiple Conditional Assertions

Add the assertion library:

const assert = require('assert');
const { hopeThat } = require('codeceptjs/effects');

Use hopeThat with assertions:

const result1 = await hopeThat(() => I.see('Hello, user'));
const result2 = await hopeThat(() => I.seeElement('.welcome'));
assert.ok(result1 && result2, 'Assertions were not successful');

Optional Click

const { hopeThat } = require('codeceptjs/effects');

I.amOnPage('/');
await hopeThat(() => I.click('Agree', '.cookies'));

Performs a soft assertion within CodeceptJS tests.

This function records the execution of a callback containing assertion logic. If the assertion fails, it logs the failure without stopping the test execution. It is useful for scenarios where multiple assertions are performed, and you want to evaluate all outcomes before deciding on the test result.

Usage

const result = await hopeThat(() => I.see('Welcome'));

// If the text "Welcome" is on the page, result => true
// If the text "Welcome" is not on the page, result => false

async
function hopeThat
@param {Function} callback - The callback function containing the soft assertion logic.
@returns {Promise<boolean | any>} - Resolves to true if the assertion is successful, or false if it fails.

Examples

Multiple Conditional Assertions:

const assert = require('assert');
const { hopeThat } = require('codeceptjs/effects');

const result1 = await hopeThat(() => I.see('Hello, user'));
const result2 = await hopeThat(() => I.seeElement('.welcome'));
assert.ok(result1 && result2, 'Assertions were not successful');

Optional Click:

const { hopeThat } = require('codeceptjs/effects');

I.amOnPage('/');
await hopeThat(() => I.click('Agree', '.cookies'));

Applicable helpers:

  • Playwright
  • Puppeteer
  • WebDriver
  • REST
  • FileHelper
  • Appium
  • TestCafe

Applicable plugins:

  • allure
  • autoDelay
  • autoLogin
  • customLocator
  • pauseOnFail
  • coverage
  • retryFailedStep
  • screenshotOnFail
  • selenoid
  • stepByStepReport
  • stepTimeout
  • wdio
  • subtitles

Type of change

  • 🔥 Breaking changes
  • 🚀 New functionality
  • 🐛 Bug fix
  • 🧹 Chore
  • 📋 Documentation changes/updates
  • ♨️ Hot fix
  • 🔨 Markdown files fix - not related to source code
  • 💅 Polish code

Checklist:

  • Tests have been added
  • Documentation has been added (Run npm run docs)
  • Lint checking (Run npm run lint)
  • Local tests are passed (Run npm test)

@kobenguyent kobenguyent requested a review from DavertMik January 9, 2025 09:56
@DavertMik
Copy link
Contributor

DavertMik commented Jan 9, 2025

@kobenguyent let's wait a bit with this one

I want to do some structural changes to improve the general logic:

  1. Use store instead of global or process.env to set global flags
  2. Instead of plugins expose functions from their own file. I already added this https://github.com/codeceptjs/CodeceptJS/blob/3.x/lib/els.js and here is the documentation https://github.com/codeceptjs/CodeceptJS/blob/3.x/docs/els.md

els replaced eachElement plugin
we can do similar for retryTo and hopeThat

We can group that 2 functions into its own module. How can we call it?

control

const { retryTo, hopeThat } = require('codeceptjs/control')

This like to general name...

steps

const { retryTo, hopeThat } = require('codeceptjs/step')
  • not actually about a single step, so not sure*

stepBlock / controlBlock

conditional

effect

const { retryTo, hopeThat } = require('codeceptjs/effect')

similar to React but quite hard to figure out naming

Maybe you have other ideas?

I want this module to be explicitly imported to test cases where it is used
To avoid more global vars

@kobenguyent
Copy link
Collaborator Author

@DavertMik how about stepEffect or just effect in general if we could add more thing not related to step only?

@DavertMik
Copy link
Contributor

Yes, I added effects into #4732
But still not sure of the naming

@DavertMik DavertMik merged commit c503ea2 into 3.x Jan 10, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants