Skip to main content

2 posts tagged with "playwright"

View All Tags

Open Letter to Jan Molak

· 4 min read

Jan,

Your recent updates to serenity-js.org are a significant improvement, and they highlight something I believe is increasingly important for our industry: testing strategy matters more than tooling.

We've exchanged a few DMs about the accessibility of Serenity/JS, particularly how difficult it can be for newcomers to understand where it fits into their testing journey. When you asked me to review the latest changes to the website, I realised my feedback was about more than the site itself, so I thought I'd share it in the form of an open letter.

Meeting People Where They Are

What stands out most about the updated site is how effectively it meets people where they are. Instead of assuming visitors already understand the Screenplay Pattern, it starts with the problems teams are trying to solve and then shows different paths into Serenity/JS.

Whether someone is looking for better reporting, more maintainable tests, or a full Screenplay-based architecture, they can quickly understand where Serenity/JS fits and how it might help.

That matters because most teams don't wake up looking for a new framework. They are looking for solutions to real problems. By focusing on those problems first, the site makes Serenity/JS far more approachable and relevant.

A Shift in the Industry

Reviewing the site also reminded me of a broader shift happening across our industry.

For years, conversations about test automation have centred on tools. Playwright versus Cypress. Selenium versus WebdriverIO. Page Objects versus Screenplay.

Today, AI has become part of that conversation as well.

And honestly, that's a good thing.

AI is already helping teams write tests faster, understand systems more quickly, improve documentation, and eliminate repetitive work. Used well, it can make automation engineers dramatically more productive.

Yet the rise of AI also reinforces an important truth: the value of testing has never been in writing code.

The real value lies in understanding risk, identifying meaningful behaviours, and deciding what is worth testing in the first place.

Those are fundamentally human skills.

The Impact of AI on Testing

An AI can generate a Playwright test in seconds. It can even generate hundreds of them. But someone still needs to decide which behaviours matter, what level of confidence is required, and how testing supports the goals of the business.

As AI lowers the barrier to creating automation code, the differentiator will not be who can generate the most tests. It will be who can design the most effective testing strategy and communicate it clearly.

This is why I believe test strategy should always come before tooling.

Not because tools don't matter - they absolutely do.

But the best tools amplify a good strategy rather than compensate for the lack of one.

Why Serenity/JS Matters

This is where I think Serenity/JS becomes particularly relevant.

Its value isn't that it can automate a browser. Playwright already does that brilliantly.

Its value is that it encourages teams to think about behaviour, intent, and outcomes. It helps automation express what users are trying to achieve rather than simply documenting which buttons were clicked.

In an AI-assisted world, that emphasis on intent becomes even more important. When generating automation becomes easier, the quality of the thinking behind that automation becomes the real advantage.

What I appreciate about the updated Serenity/JS website is that it moves the conversation in exactly that direction. It explains not only what Serenity/JS is, but also the problems it helps teams solve and the thinking behind it.

The result is a much clearer path for newcomers and a stronger message for experienced practitioners.

Conclusion

In a world where AI is making test automation more accessible than ever, helping people think more clearly about testing may be one of the most valuable things a framework can do.

Congratulations on the work.

Best, Jan

Serenity/JS and Actor Notepads for Injecting User Credentials

· 5 min read
Jan Graefe
Maintainer

Are your test scripts drowning in test data chaos? Say goodbye to clutter and hello to clarity with Serenity/JS's Actor Notepads! Learn how to inject user credentials seamlessly for cleaner, more maintainable tests. Ready to dive in?

Actors in Serenity/JS

Serenity/JS is a testing framework that promotes collaboration, clarity, and maintainability in automated testing. At its core, Serenity/JS introduces the concept of actors, which represent the different users or personas interacting with a web application. Actors are equipped with capabilities and context, allowing them to perform actions and interact with the application under test.

Serenity/JS

Introducing Actor Notepads

A key feature of Serenity/JS is the concept of actor notepads. Notepads serve as containers for actor-specific data, such as credentials, expected outcomes, and any other contextual information relevant to the test scenario. Instead of cluttering test scripts with data setup details, actor notepads encapsulate this information within the actor itself.

Example

Let's assume a small test where an actor:

  • Navigates to the login page of the application (https://the-internet.herokuapp.com/login).
  • Enters the username retrieved from the actor's notepad into the username input field on the login page.
  • Enters the password retrieved from the actor's notepad into the password input field on the login page.
  • Clicks on the login button to submit the credentials.
  • Waits until a flash message appears on the page, indicating a successful login, with the expected result retrieved from the actor's notepad.

First, we prepare two actors called Tom Smith, who is allowed to login and Jan Doe, who is not allowed to login. We put their login credentials and expected result into their notepads, using the ability to TakeNotes.

// To avoid typos and repetition when instantiating and retrieving actors,
// we use string enums to store actor names:
enum ActorNames {
Tom = 'Tom Smith, who is allowed to use our system,',
Jane = 'Jane Doe, who is not allowed to use our system,'
}

// We are using a model for our actors notepad
type FormAuthenticationModel = {
Username: string,
Password: string,
ExpectedResult: string
}

class AuthenticationActors implements Cast {
constructor(private readonly browser: Browser) {
}

// Prepare method to configure actors with specific capabilities and data
prepare(actor: Actor): Actor {
// Initialize the actor with the capability to browse the web using Playwright
let preparedActor = actor.whoCan(BrowseTheWebWithPlaywright.using(this.browser));

// Switch statement to customize actor based on their name
switch (actor.name) {
// Configuration for actor named Tom
case ActorNames.Tom: {
// Configure actor to take notes using a notepad with specific authentication data
preparedActor = preparedActor.whoCan(
TakeNotes.using(Notepad.with<FormAuthenticationModel>({
Username: 'tomsmith',
Password: 'SuperSecretPassword!',
ExpectedResult: 'You logged into a secure area!'
}))
);
break;
}
// Configuration for actor named Jane
case ActorNames.Jane: {
// Configure actor to take notes using a notepad with specific authentication data
preparedActor = preparedActor.whoCan(
TakeNotes.using(Notepad.with<FormAuthenticationModel>({
Username: 'janedoe',
Password: 'WrongPassword!',
ExpectedResult: 'Your username is invalid!'
}))
);
break;
}
}
// Return the prepared actor with customized capabilities and data
return preparedActor;
}
}

For our test we have to prepare the PageElements and a Task:

class FormAuthenticationPage {
static UserNameInputField = PageElement.located(By.css('#username')).describedAs('field to input the username')
static PasswordInputField = PageElement.located(By.css('#password')).describedAs('field to input the password')
static LoginButton = PageElement.located(By.css('[type="submit"]')).describedAs('button to login')
static FlashMessage = PageElement.located(By.css('#flash')).describedAs('result message')
}

const LoginToAppUsingActorsNotepad = () =>
Task.where(`#actor logs in using username and password from their notepad`,
Navigate.to('https://the-internet.herokuapp.com/login'),
Enter.theValue(notes<FormAuthenticationModel>().get('Username')).into(FormAuthenticationPage.UserNameInputField),
Enter.theValue(notes<FormAuthenticationModel>().get('Password')).into(FormAuthenticationPage.PasswordInputField),
Click.on(FormAuthenticationPage.LoginButton),
Wait.until(Text.of(FormAuthenticationPage.FlashMessage), includes(notes<FormAuthenticationModel>().get('ExpectedResult')))
)

Finally, when using Serenity/JS with Playwright Test our spec looks like:

//make sure to import { describe, it, test } from '@serenity-js/playwright-test'

describe('form authentication notepad', () => {
test.use({

/*
* Override the default cast of actors,
* so that each actor receives their own,
* independent browser window.
*/
actors: async ({ browser }, use) => {
use(new AuthenticationActors(browser));
},
});
describe('login page', () => {
it('should log in with correct username and password', async ({ actorCalled }) => {
await actorCalled(ActorNames.Tom).attemptsTo(
LoginToAppUsingActorsNotepad(),
)
})

it('should deny login with incorrect username and password', async ({ actorCalled }) => {
await actorCalled(ActorNames.Jane).attemptsTo(
LoginToAppUsingActorsNotepad(),
)
})

})
})

To start right away with Serenity/JS using Playwright test I recommend to use a Serenity/JS template.

Advantages of Using Actor Notepads

  • Separation of Concerns: By delegating data setup to actor notepads, test scripts focus solely on orchestrating actor actions, leading to cleaner and more readable code.

  • Encapsulation: Actor notepads encapsulate actor-specific data, promoting better organization and reducing the likelihood of data misuse or modification.

  • Reusability: Actor notepads facilitate the reuse of actors across multiple tests without duplicating data setup logic, improving test maintainability and reducing code duplication.

  • Scalability: As test suites grow, managing data setup through actor notepads proves more scalable and manageable than injecting data through parameters.

  • Enhanced Reporting: Serenity/JS emphasizes descriptive and readable test reports. Actor notepads enable better reporting by associating test steps with relevant actor context, enhancing test comprehensibility.

  • Flexibility for Extension: Actor notepads provide a flexible mechanism to extend actor capabilities or introduce additional data for testing purposes, without significantly modifying test script structure.

Conclusion

In conclusion, leveraging actor notepads within Serenity/JS tranforms automated testing, offering a streamlined approach to managing test data. By encapsulating test data within actors, test scripts become clearer, more maintainable, and less prone to errors. With the separation of concerns afforded by actor notepads, the focus shifts from data setup to orchestrating meaningful test actions, resulting in enhanced readability and scalability.