🩰 Schedule automated tests; become premier ballet artiste
Tags: playwright, yaml, tests
Published: 2023-09-01 08:52:08

---
title: 🩰 Schedule automated tests; become premier ballet artiste
published: true
description: Making a notification system with Playwright and GitHub Actions. How I made sure to never miss a beat 💃
tags: playwright, yaml, tests
# published_at: 2023-09-01 07:39 +0000
---

I've been checking this page of the Royal Opera House website everyday lately:
![Events page on the Royal Ballet's website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/svf4wwgvhh01t3y4blwf.png)
<figcaption><sup>The website shows three sold-out workshops with The Royal Ballet.</sup></figcaption>

There's three sold out events and I want to go to any one of them, so I am keeping an eye out for return tickets going on resale. But wait! Computers can help automate this...

## 1. Write a test to check the page automatically

I am not sure how the page will look when a ticket goes back on sale, but I am confident that the page will change so that the header with the words "Sold out" do not appear 3 times. (I expect this will also decrease by 1 after any of the dates have passed - but I haven't written this into my test yet).

I created an empty [Vue.js](https://vuejs.org/) project - I don't need a UI, I just want to use tests, so Vue will create a dummy project for me.

### Playwright

I am going to use a browser based testing tool called [Playwright](https://playwright.dev/) (But you could use [Capybara](https://teamcapybara.github.io/capybara/), or [Selenium WebDriver](https://www.selenium.dev/documentation/webdriver/) etc.).

First I'm going to write a 'Hello World' style test to make sure I am on the correct page.  When I navigate to the url, do I see the title I expect?

```JavaScript
test('a hello world check that we have the right page', async ({ page }) => {
  await page.goto('https://www.roh.org.uk/tickets-and-events/dance-with-the-royal-ballet-dates');
  await expect(page).toHaveTitle(/Dance with The Royal Ballet/);
});
```

Then, I'll write my useful test. I want the headless browser to go to the webpage at the given URL. I'm using JavaScript, so I am going to make my test method `async` and use `await` for actions that will create a `Promise` which needs to be fulfilled.

I used the [Chrome DevTools](https://developer.chrome.com/docs/devtools/open/) to investigate what elements are used for the "Sold out" text. The Inspect tool tells me this is a `h4` and therefore it has the `heading` Role.

![Use the inspect tool to find out a page elements role](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3gejrwkt161da8wqa840.png)
<figcaption><sup>The element has a 'heading' Role.</sup></figcaption>

I use Playwright's `getByRole` method with arguments describing that the role I want is a heading, with the exact text "Sold out".
Then I can add an assertion that I expect there to be three sold out items on the page - I made sure to break my assertion to check that the test can fail, before using the correct assertion.

```JavaScript
test('check for sold out items', async ({ page }) => {
  await page.goto('https://www.roh.org.uk/tickets-and-events/dance-with-the-royal-ballet-dates');
  const soldOutItems = await page.getByRole('heading', { name: 'Sold out' });

  // Expects page to have three Sold out items.
  // If there are not 3 sold out items, there may be returns for sale!
  await expect(soldOutItems).toHaveCount(3);
});
```

[The test file on GitHub](https://github.com/ruthmoog/ballert/blob/main/tests/example.spec.js)

## 2. Trigger the test workflows on automated schedule

I've pushed my changes to my GitHub repo, and use [Actions](https://docs.github.com/en/actions/using-workflows/about-workflows) to set up an automatic test run.

The `playwright.yml` file is automatically configured to run when code is pushed or a pull-request is merged, and it will run the browser tests:

```YAML
name: Playwright Tests
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
    ...
    - name: Run Playwright tests
      run: npx playwright test
```

To run these tests on a schedule, I need to add another item within the on section:

```YAML
  schedule:
    - cron:  '1 1,10,15 * * *'
```

This uses the [POSIX cron syntax](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html#tag_20_25_07) to add a schedule event. The example above will schedule the tests to run at 1 minute past 2am, 11am and 4pm local time (or, 01:01, 10:01, 15:01 UTC).

The GitHub Actions docs explain [how to use schedule events to trigger workflows](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule), including how the cron syntax works.

For the time being, I have guessed which intervals to use - but I have contacted the box office about when tickets are released on the website, so that I can run the tests as few times as possible.

[Workflow configuration YAML on GitHub](https://github.com/ruthmoog/ballert/blob/main/.github/workflows/playwright.yml)

And with that, my alerts (_ballerts_...) are done. GitHub will run my tests at the given times (deferring for heavy usage times) and their email notifications will let me know if there is a test failure and therefore that I should jump over to the website to try and buy a ticket (or update my test!).

![*curtsy*](https://ic.pics.livejournal.com/unbelievableme/20692558/1192847/1192847_original.gif)
<figcaption><sup>｡･:*:･ﾟ☆Graceful curtsy☆･ﾟ:*:･｡</sup></figcaption>