microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
66.2k stars 3.62k forks source link

[Feature] Allow to set test.use options per single test #27138

Open AdamOakman opened 1 year ago

AdamOakman commented 1 year ago

This issue was mentioned in a couple of places and seems like it is missing a good solution: https://github.com/microsoft/playwright/discussions/19893 https://github.com/microsoft/playwright/discussions/21341

Currently we have 2 ways of using fixture options - either by setting it in the config file per project inside use block or in test.use statement in a spec file. test.use statement seems to be not flexible enough because it allows to set whatever we want only for the whole file or per whole test.describe block and not for a single test.

Taking simple example from the official documentation https://playwright.dev/docs/test-fixtures#fixtures-options - having fixture option defined like below:

import { test as base } from '@playwright/test';
import { TodoPage } from './todo-page';

// Declare your options to type-check your configuration.
export type MyOptions = {
  defaultItem: string;
};
type MyFixtures = {
  todoPage: TodoPage;
};

// Specify both option and fixture types.
export const test = base.extend<MyOptions & MyFixtures>({
  // Define an option and provide a default value.
  // We can later override it in the config.
  defaultItem: ['Something nice', { option: true }],

  // Our "todoPage" fixture depends on the option.
  todoPage: async ({ page, defaultItem }, use) => {
    // ...
  },
});
export { expect } from '@playwright/test';

It would be convenient to be able to set use params per single test like that (or any other neat way that would do the trick):

test('example test #1', async ({ todoPage, page }) => {
  // ...
}).use({ defaultItem: 'Something cool' });

test('example test #2', async ({ todoPage, page }) => {
  // ...
}).use({ defaultItem: 'Something else' });
Terence625 commented 1 year ago

yes, I was trying to use multiple test.use() to switch authentications between tests in one test.describe block, but the last test.use() will just override the previous ones. And those tests are in one test.describe block for a reason as they are same tests with different authentications, I don't want to separate them into different files or different projects. It'll be nice to have test.use() more flexible

phil294 commented 12 months ago

but the last test.use() will just override the previous ones.

This is also my observation. I wonder what is the reasoning for the current behavior? We'd like to run a few small tests across different locales, nested under other conditionals. Apparently this is currently impossible? I tried

myLocales.forEach(locale => {
    const test = base.extend({})
    test.use({locale})
    test('...')
})

but apparently even like that, every test uses the same locale, namely the last one specified in myLocales. Don't really understand why though

kenanAlhindi97 commented 8 months ago

I don't know if I should make a separate issue for this but one of the behaviors that prevents from using fixtures is the fact that : test.use({parameter:parameterValue}); is not editable/update-able

say you have a this code :

let parameterValue=foo;
test.beforeEach(async () => {
    paremeterValue=bar;
});
test.use({parameter:parameterValue});

test('should log bar', async ({parameter}) => {
   console.log(parameter) // 'foo'
});

I just don't see any other way to implement parameterized fixtures with mutable parameters, and it would be a nice feature.

NagRock commented 2 months ago

It would be nice if test could override configured options with the one provided as last param:


   console.log(parameter) // 'foo'
}, () => ({parameter: parameterValue}));```

And the function with overrides will be called just before test function to override parent configuration