thisdot / open-source

Repository for open source packages
MIT License
34 stars 11 forks source link

@this-dot/playwright-indexeddb #150

Open TapaiBalazs opened 1 year ago

TapaiBalazs commented 1 year ago

What do you want to build?

I'd like to propose building the @this-dot/playwright-indexeddb package.

Where did your idea come from?

The @this-dot/cypress-indexeddb library is getting more and more popular, creating a similar helper package for playwright seems reasonable. Before this proposal I have spent some time to investigate how it could be done, and if we could have shared methods between the two packages.

How long will it take to build?

POC findings

Playwright tests while structured similarly to cypress, communicating with the IDBFactory requires to be run inside a page.evaluate() callback. Playwright is more comfortable to use with the page-object model That also means that while in cypress we can access the indexeddb object before visiting the page, in playwright we must visit the page first to be able to interact with the IDBFactory Running everything inside an evaluate callback forces us to handle connecting to the database and selecting the store inside each and every function (set/get/update/delete items) We can only pass serialisable objects into the page.evaluate() method as parameters, therefore, the library will not be able to support every type of IDBValidKey, only the primitives (string and number)

Proposed shape of the helper

The helper should be a class, and it needs to be instantiated with a page object passed down in the constructor, with the database name. Initialising the database (if it does not exist) should happen after calling the page’s .goto() method. It is an async function. The method should return this Creating an object store should handle creating a version-update change if that’s needed Accessing the store should be a HOF, that returns an object with the “leaf” functions (set/get/update/delete)

A test would look something like the following:

import { expect, test } from '@playwright/test';
import { selectors } from 'playwright';

import type { Page } from 'playwright';
import { IdbHelper } from '@this-dot/playwright-indexeddb';

test.describe('@this-dot/route-config', () => {
  let page: Page;
  let playwrightIdb: IdbHelper;

  test.beforeAll(async ({ browser }) => {
    selectors.setTestIdAttribute('data-test-id');
    page = await browser.newPage();
  });

  test.beforeEach(async () => {
    playwrightIdb = new IdbHelper(page);

    await page.goto('/');

    await playwrightIdb.init('PLAYWRIGHT_DATABASE');
    await playwrightIdb.createObjectStore('PLAYWRIGHT_STORE');
  });

  test.describe('documentation section', () => {
    test.only('the documentation of the library is always visible', async () => {
      await playwrightIdb
        .store('PLAYWRIGHT_STORE')
        .createItem(`Key`, 'value');

      await page.goto('/')

      // ...
    });
  });

});

POC

See proof of concept PR at https://github.com/thisdot/open-source/pull/149 Additionally, I have attached a video of the POC demonstrating that we are able to set a value into the database.

Estimation

I’d estimate that roughly 30 hours would be enough for all the remaining sub-tasks (see below) for me, this is a pessimistic estimation because we can only reuse some logic from the cypress-indexeddb package.

What milestones exist?

Based on the above, I have the following milestones:

  1. Implement the remaining CRUD operators using a second StoreHelper class, that gets returned after the database store gets created. (5 hours of work)
  2. Write the existing cypress e2e tests as playwright tests to make sure the library works (5 hours of work)
  3. Write detailed TSDoc on methods, so library users will have proper documentation at hand while using the plug-in. Document limitations (e.g.: serialisable keys can be used with it because of playwright's limitations, etc), also write the proper readme for the package with examples, etc (5 hours)
  4. Write an introductory blog post that provides examples for writing tests using the package (5 hours)