Handle Assertions
Fmstrat opened this issue · comments
Hi,
I think a nice feature of PR would be to include the ability to handle assertions. I.E:
"Confirm that a piece of content exists on a page after an action is taken."
I do this manually in Puppeteer with a variation of the below block of code (specifically the page.assert
function).
page = await browser.newPage()
page.announce = function(title) {
console.log(`Running test: ${title}`);
}
page.success = function(test) {
console.log(` Success: ${test}`);
}
page.fail = function(test) {
page.pass = false;
console.log(` -=- FAIL -=-: ${test}`);
}
page.assert = async function(test, location, value) {
res = await this.getPage();
switch (location) {
case "body":
if (res.body.includes(value)) {
this.success(test)
} else {
this.fail(test)
}
break;
case "title":
if (res.title.includes(value)) {
this.success(test)
} else {
this.fail(test)
}
break;
}
},
page.getPage = async function() {
await this.sleep(500);
return {
title: await this.title(),
body: await this.evaluate(() => document.body.innerHTML)
}
},
page.sleep = async function(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
page.pass = true;
// Announce the test is starting
page.announce("Sample Test");
// Set the view to a desktop/laptop window
await page.setViewport({ width: 1920, height: 980 })
// The navigationPromise means: "wait for the page to finish loading after a click"
const navigationPromise = page.waitForNavigation()
// Load a page and make sure "Moodle sandbox demo" is in the page title
await page.goto(env.url)
await page.assert("Initial load", "title", "Sandbox demo");
// Click on the login link in the upper right
await page.waitForSelector('.nav > .nav-item > .usermenu > .login > a')
await page.click('.nav > .nav-item > .usermenu > .login > a')
await navigationPromise
// Click on the username field
await page.waitForSelector('#username')
await page.click('#username')
// Type in username from our environments file
await page.type('#username', env.user)
// Type in password (tab got us here without clicking)
await page.type('#password', env.pass)
// Click the login button and make sure "Admin User" is in the page body afterwards
await page.waitForSelector('#loginbtn')
await page.click('#loginbtn')
await navigationPromise
await page.assert("Logged in", "body", "Admin User");
// Click on "My first course" and make sure "Topic 1" is in the page body afterwards
await page.waitForSelector('.courses > .even > .info > .coursename > a')
await page.click('.courses > .even > .info > .coursename > a')
await navigationPromise
await page.assert("First course", "body", "Topic 1");
// Click the dropdown menu in the upper right
await page.waitForSelector('#action-menu-toggle-1')
await page.click('#action-menu-toggle-1')
// Click on logout and make sure "You are not logged in." is in the body of the page
await page.waitForSelector('#action-menu-1-menu #actionmenuaction-6')
await page.click('#action-menu-1-menu #actionmenuaction-6')
await navigationPromise
await page.assert("Logout", "body", "You are not logged in.");
...
I think an amazing feature (that can be reused in your path forward even if it's not puppeteer as most apps, even playwrite, support this, would be to add a right click menu to include an assertion.
The process could work like this:
- User highlights a piece of text, we'll say "Text in selector"
- Right clicks
- Chooses
Add assertion
The code would then generate a shell with similar added page
functions to the above, along with:
await page.waitForSelector('#selector')
await page.assert("Found: Text in selector", "#selector", "Text in selector");
Where for assert
the first argument is what is being searched prefixed with "Found:", the second is the CSS selector of where that object is on the page, and the third is the actual text to search for.
Much of the assert function from above can be leveraged, you already have the code to grab the CSS selector, it just requires the right-click functionality to be added.
Thoughts?
@Fmstrat thanks for contributing, and this is absolutely something we want to add. First response after reading your proposal:
-
For assertions, we would 99% sure use an existing assertion library, i.e. chai.js, Node's own assert and/or the Jest
expect
function. -
A right-click, "add assertion" workflow is exactly what I was thinking. Maybe even a custom in page menu to provide some more options.