In this tutorial, you will use the Playwright automation framework to write end-to-end tests for your Freshworks Apps. We will learn to authenticate, configure and write our first test with Playwright.
Playwright is the perfect tool for testing Freshworks apps. It provides powerful APIs to control web browsers, automate user interactions, and test web applications across browsers and operating systems.
You can use the Codegen tool of Playwright to capture the tests automatically by manually going through the app's functionality and running the tests automatically.
Additionally, running the automation test suite once will generate the code coverage for your app for the covered functionalities.
Follow these steps to set up the local environment for Playwright Framework.
We will use the Say Hello sample app from Freshworks Developer sample app repositories for this exercise. You can use either Freshdesk or Freshservice to run the app. But, in this tutorial, we will use the Freshdesk version of the app. Freshservice should be similar as well, apart from the URLs used.
git clone https://github.com/freshworks-developers/say-hello.git
.npm init playwright@latest
. You can also find alternative methods from the official documentation. This step will add some required files for the app testing framework and install the necessary browsers.Once installed, you can start using the Playwright test automation framework and Codegen that comes with it. We will use Codegen to write a test script for our Say Hello app.
Follow these steps to generate the test script.
Note: If you want to write the test script manually, skip this section and refer to the official documentation for the syntax.
npx playwright codegen
command to generate the test script. It will open a browser window and another window to capture the generated test scripts.subdomain.freshdesk.com/a/tickets/111?dev=true
URL. It will open the login page as each test will run on an incognito window.Ensure that the generated test script looks similar to the following snippet.
const { test, expect } = require('@playwright/test');
test.describe('Sample app testing using local FDk', () =>{
test('Validate app flow ', async ({ browser }) => {
const context = await browser.newContext({
storageState: `${__dirname}/../auth.json`
});
const page = await context.newPage();
let testApp;
await test.step("Navigating to freshdesk account", async() =>{
await page.goto('/a/tickets/5?dev=true');
await page.getByText('[In-Dev] Freshdesk').click();
});
await test.step("Check availability of app in ticket sidebar and open", async() =>{
testApp = await page.frameLocator('[data-test-id="app_123456789_content"] iframe');
await testApp.locator('fw-button[id="btnSayHello"]>button').click();
});
await test.step("Validate new ticket is created in freshdesk", async() =>{
await page.waitForTimeout(2000);
const text = await testApp.locator('fw-label[id="newTicketBanner"]>span').textContent();
expect(text).toContain('Freshdesk talks in tickets, check for new ticket.');
});
});
});
Refer to the Test Generation steps in the Playwright's official documentation. You can also write the test scripts manually.
Multiple steps are required to clean up the test and organise it for better troubleshooting.
You can try all these steps by checking out the Playwright documentation and referring to the completed Say-Hello app test project. You can replace your test script in the example.spec.js file with the following script.
const { test, expect } = require('@playwright/test');
const CONSTANTS = {
config_url: 'http://localhost:10001/custom_configs',
Subdomain: '<YOUR_FRESHDESK_SUBDOMAIN>',
api_key: '<YOUR_FRESHDESK_API_KEY>',
ticket_id: 111,
app_name: 'say-hello'
}
test.describe('Sample app testing using local FDk', () => {
test('Validating the custom config page and installing the app', async ({ page }) => {
await test.step("Navigating to custom config page", async () => {
await page.goto(CONSTANTS.config_url);
});
await test.step("Fill up the basic details", async () => {
await page.frameLocator('#iparams-form iframe').getByLabel('Freshdesk subdomain').fill(CONSTANTS.subdomain);
await page.frameLocator('#iparams-form iframe').getByLabel('Freshdesk API key').fill(CONSTANTS.api_key);
});
await test.step("Check app is installed", async () => {
await page.getByRole('button', { name: 'INSTALL' }).click();
await expect(page.locator('#snackbar')).toHaveText('App installation parameters have been successfully stored. You can now proceed to test the app.');
});
});
test('Validate app flow ', async ({ browser }) => {
const context = await browser.newContext({
storageState: `${__dirname}/../auth.json`
});
const page = await context.newPage();
let testApp;
await test.step("Navigating to freshdesk account", async () => {
await page.goto(`/a/tickets/${CONSTANTS.ticket_id}?dev=true`);
await page.getByText(`[IN-DEV] ${CONSTANTS.app_name.toUpperCase()}`).click();
});
await test.step("Check availability of app in ticket sidebar and open", async () => {
testApp = await page.frameLocator('[data-test-id="app_123456789_content"] iframe');
await testApp.locator('fw-button[id="btnSayHello"]>button').click();
});
await test.step("Validate new ticket is created in freshdesk", async () => {
await page.waitForTimeout(2000);
const text = await testApp.locator('fw-label[id="newTicketBanner"]>span').textContent();
expect(text).toContain('Freshdesk talks in tickets, check for new ticket.');
});
});
});
To do meta steps, let's add a global setup to test our project. Name the setup file "global_setup.js" under the "tests" directory of the project.
const { chromium } = require('@playwright/test');
module.exports = async config => {
const { baseURL, storageState } = config.projects[0].use;
const browser = await chromium.launch({ headless: false});
const page = await browser.newPage();
await page.goto(`${baseURL}/a/admin/marketplace/gallery`);
await page.getByRole('link', { name: 'Login here' }).click();
await page.getByTestId('username').fill('<YOUR_FRESHDESK_USERNAME');
await page.getByTestId('password').fill('<YOUR_FRESHDESK_PASSWORD>');
await page.getByTestId('login-button').click();
await page.frameLocator('#gallery-frame').getByRole('button', { name: 'Manage Apps' }).waitFor();
await page.context().storageState({ path: storageState });
await browser.close();
};
Note: For the sake of this tutorial, we only use the username and password combination for authentication. If you use Google or another SSO, the logic will differ. You can use "Forgot Password" to set a password if you have never set one before.
Open the playwright.config.js file and add the global config to the config object.
module.exports = defineConfig({
globalSetup: require.resolve('./tests/global_setup'),
...
});
The browser state must be stored in a file to reuse the sessions across the tests.
module.exports = defineConfig({
...
use: {
...
storageState: 'auth.json',
...
}
...
});
https://your-subdomain.freshdesk.com
URL to use it in our tests.fullyParallel
from true to false.Execute the npx playwright test --headed
command to run the tests. It will run all the tests and open the browser while executing the test.
The Playwright will then execute the script's instructions and show its results in the terminal.
The Playwright test report provides detailed information about the results of your tests. It will appear in the terminal after each test run. The report contains information such as the test name, duration of the steps, and whether the test result was a success or failed during the test.
Execute the playwright show-report
command to view the results in the browser. Find more information on the documentation.
The test execution by the Playwright framework helps you generate the code coverage for your app. The Freshworks CLI (fdk) generates the code coverage automatically when the tests are executed on your local environment.
Alternatively, you can test the app manually to generate the code coverage for any missed functionality or wherever required.