Migrating from Protractor to Playwright
Implementing the new framework in playwright will be easy things to do. But the challenges come to the picture when the outdated framework from Protractor need to be re-written or we can say need to be migrated to playwright.
There are two ways that we can migrate from existing protractor framework to playwright
1> We need to go through each page object and test file and need to re-write in playwright format.
2> The existing protractor script can be migrated to new the playwright framework.
Let’s start with 1st approach:-
1.1> Create class block under that create the variables for each locators.
1.2> Create constructor for the class and pass the page object into that.
1.3> Replace the locator (css , xpath etc ) to page.locator and pass the locator value within the double or single quotes.
1.4> Call the variable into the test file by creating the object reference of the page file.
Conclusion :- its very time taking job to convert each locator type playwright format as each and every lines need to be updated and on top of that need to create the constructor for each class in every page object files.
Start with 2nd Approach :-
Here we will be migrating the existing protractor script into Playwright script
Migration Principles :-
Cheat Sheet
Example
Protractor:
describe('angularjs homepage todo list', function()
it('should add a todo', function() {
browser.get('https://angularjs.org');
element(by.model('todoList.todoText')).sendKeys('first test');
element(by.css('[value="add"]')).click();
var todoList = element.all(by.repeater('todo in todoList.todos'));
expect(todoList.count()).toEqual(3);
expect(todoList.get(2).getText()).toEqual('first test');
// You wrote your first test, cross it off the list
todoList.get(2).element(by.css('input')).click();
var completedAmount = element.all(by.css('.done-true'));
expect(completedAmount.count()).toEqual(2);
});
});
Line-by-line migration to Playwright Test:
test.describe('angularjs homepage todo list', function()
test('should add a todo', async function({page}) { // 2, 3
await page.goto('https://angularjs.org'); // 4
await page.locator('[ng-model="todoList.todoText"]').fill('first test');
await page.locator('[value="add"]').click();
var todoList = page.locator('[ng-repeat="todo in todoList.todos"]'); // 5
await expect(todoList).toHaveCount(3);
await expect(todoList.nth(2)).toHaveText('first test', {
useInnerText: true,
});
// You wrote your first test, cross it off the list
await todoList.nth(2).getByRole('textbox').click();
var completedAmount = page.locator('.done-true');
await expect(completedAmount).toHaveCount(2);
});
}
Migration highlights (see inline comments in the Playwright Test code snippet):
Commands
The migration can be done directly by executing the following command in the e2e root folder:
Recommended by LinkedIn
npx @amadeus-it-group/protractor-to-playwright@latest --dst='relative/path/to/e2e-playwright-folder' --tsconfig='relative/path/to/tsconfig.conf.ts'
Basically, it takes these arguments:
You can get the help on the usage with npx @amadeus-it-group/protractor-to-playwright@latest –help
Architecture
A file 'playwright-utils' is added at the root of destination folder. It contains useful functions to help the conversion.
In protractor, there is a notion of current page from where you can do actions. In Playwright, this page is given in the callback function parameter of a test. In order to reproduce the Protractor behaviour, the setPage function (of playwright-utils) must be used at the start of each test to store the current page, which can be retrieved at any time with the getPage function. The test object of playwright-utils must be used as well, in order to clear the current page at the end of the test.
Migration strategy
You can adopt different migration strategies depending on your project. This is an example of how it can be done:
The new code will not work directly and will require manual changes. At this point, either you detect that something can be improved in the tool, so you can contact us or open a PR, or the migration can be finished on your side in a reasonable time. At any time, you can use the 'file' parameter to migrate only a set of files.
At this point you can either wait for a new release with fixes or finish the work on your side (and you will not need the migration tool anymore
Code that will need a review/refactor by the application team
For example, after the migration, you can have:
test('test 1', async({page}) =>
...
});
test('test 2', async({page}) => {
// Test 2 depends on the actions done in test 1
...
});
As test 2 depends on test 1, you will need to convert the code this way:
import { setPage } from "../../playwright-utils"; // Path to be adapte
...
test('Global description', async ({page}) => {
setPage(page);
await test.step('test 1', async () => {
...
});
await test.step('test 2', async () => {
// Test 2 depends on the actions done in test 1
...
});
});
For example, in the following code:
const button = this.page.locator('#buttonId');
await browser.wait(ExpectedConditions.presenceOf(button));
await button.click();
The line browser.wait is not needed at all, as Playwright provides all this waiting actions in the button.click.
Or:
await browser.wait(ExpectedConditions.titleIs('My title'));
Must be replaced by:
await expect(page).toHaveTitle('My title')
Do you working example for this? Mentioned utility is quite outdated & not working.