javascriptplaywrightplaywright-testplaywright-typescript

How to pass runtime test data to global.teardown.ts?


in fixtures.ts I perform some API calls that create objects in database and returns their ids.

After all tests are done, I need clean the created objects in database.

How do I pass the ids to global.teardown.ts?


What I have

I import fixtures module with a singleton array of guid in global.teardown.ts but the module is reinitialized and array is empty.

global.teardown.ts

import { entityGuidsToDelete, api } from './fixtures'

async function globalTeardown() {
    //not working yet, because the array is always empty
    for(const entityGuid of entityGuidsToDelete) { 
        await api.deleteEntity(entityGuid);
    }
}

export default globalTeardown;

playwright.config.ts

export default defineConfig({
  ...
  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],

  globalTeardown: require.resolve('./global-teardown')
});
type Fixtures = {
  userApi: Api;
  newEntity: LegalEntityModel;
};

export const entityGuidsToDelete = new Array<string>();

export const test = base.extend<Fixtures>({
 ...
 newEntity: async ({ userApi }, use) => {
    const newEntity = await createNewEntity()
    entityGuidsToDelete.push(newEntity.id); //this is being called
    await use(newEntity);
  }  
}

export { expect } from '@playwright/test';

Solution

  • I would use an scope worker fixture:

    import { test as base } from '@playwright/test';
    
    export const test = base.extend({
      entities: [async ({}, use) => {
        const array = [];
        await use(array);
      }, { scope: 'worker' }],
      forEachWorker: [async ({entities}, use) => {
        // This code runs before all the tests in the worker process.
        await use();
        // Do something with entities
      }, { scope: 'worker', auto: true }], 
    });
    
    export { expect } from '@playwright/test';
    

    In this example an entities array will be created per worker. Then, you can use that fixture in the forEachWork and do something with them after use.

    This is how you can use it on a test:

    import { test, expect } from './fixtures';
    
    test.describe('Example test suite', () => {
      test('first dummy test', async ({ page, entities }) => {
        // Empty test
        entities.push('entity1');
      });
    
      test('second dummy test', async ({ page, entities }) => {
        // Empty test
        entities.push('entity2');
      });
    
      test('third dummy test', async ({ page, entities }) => {
        // Empty test
        entities.push('entity3');
      });
    });