1"use strict";(self.webpackChunkplaywright_dev=self.webpackChunkplaywright_dev||[]).push([["3384"],{88461(e,t,n){n.r(t),n.d(t,{metadata:()=>s,default:()=>p,frontMatter:()=>o,contentTitle:()=>i,toc:()=>d,assets:()=>l});var s=JSON.parse('{"id":"test-global-setup-teardown","title":"Global setup and teardown","description":"Introduction","source":"@site/versioned_docs/version-stable/test-global-setup-teardown.mdx","sourceDirName":".","slug":"/test-global-setup-teardown","permalink":"/docs/test-global-setup-teardown","draft":false,"unlisted":false,"tags":[],"version":"stable","frontMatter":{"id":"test-global-setup-teardown","title":"Global setup and teardown"},"sidebar":"docs","previous":{"title":"Fixtures","permalink":"/docs/test-fixtures"},"next":{"title":"Parallelism","permalink":"/docs/test-parallel"}}'),a=n(74848),r=n(28453);n(13554),n(41647),n(83137);let o={id:"test-global-setup-teardown",title:"Global setup and teardown"},i,l={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Option 1: Project Dependencies",id:"option-1-project-dependencies",level:2},{value:"Setup",id:"setup",level:3},{value:"Teardown",id:"teardown",level:3},{value:"Test filtering",id:"test-filtering",level:3},{value:"More examples",id:"more-examples",level:3},{value:"Option 2: Configure globalSetup and globalTeardown",id:"option-2-configure-globalsetup-and-globalteardown",level:2},{value:"Example",id:"example",level:3},{value:"Capturing trace of failures during global setup",id:"capturing-trace-of-failures-during-global-setup",level:3}];function c(e){let t={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,a.jsxs)(t.p,{children:["There are two ways to configure global setup and teardown: using a global setup file and setting it in the config under ",(0,a.jsx)(t.a,{href:"#option-2-configure-globalsetup-and-globalteardown",children:(0,a.jsx)(t.code,{children:"globalSetup"})})," or using ",(0,a.jsx)(t.a,{href:"#option-1-project-dependencies",children:"project dependencies"}),". With project dependencies, you define a project that runs before all other projects. This is the recommended approach, as it integrates better with the Playwright test runner: your HTML report will include the global setup, traces will be recorded, and fixtures can be used. For a detailed comparison of the two approaches, see the table below."]}),"\n",(0,a.jsxs)(t.table,{children:[(0,a.jsx)(t.thead,{children:(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.th,{children:"Feature"}),(0,a.jsx)(t.th,{children:"Project Dependencies (recommended)"}),(0,a.jsxs)(t.th,{children:[(0,a.jsx)(t.code,{children:"globalSetup"})," (config option)"]})]})}),(0,a.jsxs)(t.tbody,{children:[(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Runs before all tests"}),(0,a.jsx)(t.td,{children:"\u2705 Yes"}),(0,a.jsx)(t.td,{children:"\u2705 Yes"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"HTML report visibility"}),(0,a.jsx)(t.td,{children:"\u2705 Shown as a separate project"}),(0,a.jsx)(t.td,{children:"\u274C Not shown"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Trace recording"}),(0,a.jsx)(t.td,{children:"\u2705 Full trace available"}),(0,a.jsx)(t.td,{children:"\u274C Not supported"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Playwright fixtures"}),(0,a.jsx)(t.td,{children:"\u2705 Fully supported"}),(0,a.jsx)(t.td,{children:"\u274C Not supported"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Browser management"}),(0,a.jsxs)(t.td,{children:["\u2705 Via ",(0,a.jsx)(t.code,{children:"browser"})," fixture"]}),(0,a.jsxs)(t.td,{children:["\u274C Fully manual via ",(0,a.jsx)(t.code,{children:"browserType.launch()"})]})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsx)(t.td,{children:"Parallelism and retries"}),(0,a.jsx)(t.td,{children:"\u2705 Supported via standard config"}),(0,a.jsx)(t.td,{children:"\u274C Not applicable"})]}),(0,a.jsxs)(t.tr,{children:[(0,a.jsxs)(t.td,{children:["Config options like ",(0,a.jsx)(t.code,{children:"headless"})," or ",(0,a.jsx)(t.code,{children:"testIdAttribute"})]}),(0,a.jsx)(t.td,{children:"\u2705 Automatically applied"}),(0,a.jsx)(t.td,{children:"\u274C Ignored"})]})]})]}),"\n",(0,a.jsx)(t.h2,{id:"option-1-project-dependencies",children:"Option 1: Project Dependencies"}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"./api/class-testproject#test-project-dependencies",children:"Project dependencies"})," are a list of projects that need to run before the tests in another project run. They can be useful for configuring the global setup actions so that one project depends on this running first. Using dependencies allows global setup to produce traces and other artifacts."]}),"\n",(0,a.jsx)(t.h3,{id:"setup",children:"Setup"}),"\n",(0,a.jsxs)(t.p,{children:["First we add a new project with the name 'setup db'. We then give it a ",(0,a.jsx)(t.a,{href:"/docs/api/class-testproject#test-project-test-match",children:"testProject.testMatch"})," property in order to match the file called ",(0,a.jsx)(t.code,{children:"global.setup.ts"}),":"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="playwright.config.ts"',children:"import { defineConfig } from '@playwright/test';
1\n\nexport default defineConfig({\n testDir: './tests',\n // ...\n projects: [\n {\n name: 'setup db',\n testMatch: /global\\.setup\\.ts/,\n },\n // {\n // other project\n // }\n ]\n});\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Then we add the ",(0,a.jsx)(t.a,{href:"/docs/api/class-testproject#test-project-dependencies",children:"testProject.dependencies"})," property to our projects that depend on the setup project and pass into the array the name of our dependency project, which we defined in the previous step:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="playwright.config.ts"',children:"import { defineConfig, devices } from '@playwright/test';\n\nexport default defineConfig({\n testDir: './tests',\n // ...\n projects: [\n {\n name: 'setup db',\n testMatch: /global\\.setup\\.ts/,\n },\n {\n name: 'chromium with db',\n use: { ...devices['Desktop Chrome'] },\n dependencies: ['setup db'],\n },\n ]\n});\n"})}),"\n",(0,a.jsxs)(t.p,{children:["In this example the 'chromium with db' project depends on the 'setup db' project. We then create a setup test, stored at root level of your project (note that setup and teardown code must be defined as regular tests by calling ",(0,a.jsx)(t.a,{href:"./api/class-test#test-call",children:"test()"})," function):"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="tests/global.setup.ts"',children:"import { test as setup } from '@playwright/test';\n\nsetup('create new database', async ({ }) => {\n console.log('creating new database...');\n // Initialize the database\n});\n"})}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="tests/menu.spec.ts"',children:"import { test, expect } from '@playwright/test';\n\ntest('menu', async ({ page }) => {\n // Your test that depends on the database\n});\n"})}),"\n",(0,a.jsx)(t.h3,{id:"teardown",children:"Teardown"}),"\n",(0,a.jsxs)(t.p,{children:["You can teardown your setup by adding a ",(0,a.jsx)(t.a,{href:"/docs/api/class-testproject#test-project-teardown",children:"testProject.teardown"})," property to your setup project. This will run after all dependent projects have run."]}),"\n",(0,a.jsxs)(t.p,{children:["First we add the ",(0,a.jsx)(t.a,{href:"/docs/api/class-testproject#test-project-teardown",children:"testProject.teardown"})," property to our setup project with the name 'cleanup db' which is the name we gave to our teardown project in the previous step:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="playwright.config.ts"',children:"import { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n testDir: './tests',\n // ...\n projects: [\n {\n name: 'setup db',\n testMatch: /global\\.setup\\.ts/,\n teardown: 'cleanup db',\n },\n {\n name: 'cleanup db',\n testMatch: /global\\.teardown\\.ts/,\n },\n {\n name: 'chromium',\n use: { ...devices['Desktop Chrome'] },\n dependencies: ['setup db'],\n },\n ]\n});\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Then we create a ",(0,a.jsx)(t.code,{children:"global.teardown.ts"})," file in the tests directory of your project. This will be used to delete the data from the database after all tests have run."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="tests/global.teardown.ts"',children:"import { test as teardown } from '@playwright/test';\n\nteardown('delete database', async ({ }) => {\n console.log('deleting test database...');\n // Delete the database\n});\n"})}),"\n",(0,a.jsx)(t.h3,{id:"test-filtering",children:"Test filtering"}),"\n",(0,a.jsxs)(t.p,{children:["All test filtering options, such as ",(0,a.jsx)(t.code,{children:"--grep"}),"/",(0,a.jsx)(t.code,{children:"--grep-invert"}),", ",(0,a.jsx)(t.code,{children:"--shard"}),", filtering directly by location in the command line, or using ",(0,a.jsx)(t.a,{href:"/docs/api/class-test#test-only",children:(0,a.jsx)(t.code,{children:"test.only()"})}),", directly select the primary tests to be run. If those tests belong to a project with dependencies, all tests from those dependencies will also run."]}),"\n",(0,a.jsxs)(t.p,{children:["You can pass ",(0,a.jsx)(t.code,{children:"--no-deps"})," command line option to ignore all dependencies and teardowns. Only your directly selected projects will run."]}),"\n",(0,a.jsx)(t.h3,{id:"more-examples",children:"More examples"}),"\n",(0,a.jsx)(t.p,{children:"For more detailed examples check out:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["our ",(0,a.jsx)(t.a,{href:"/docs/auth",children:"authentication"})," guide"]}),"\n",(0,a.jsxs)(t.li,{children:["our blog post ",(0,a.jsx)(t.a,{href:"https://dev.to/playwright/a-better-global-setup-in-playwright-reusing-login-with-project-dependencies-14",children:"A better global setup in Playwright reusing login
1with project dependencies"})]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.a,{href:"https://youtu.be/PI50YAPTAs4",children:"v1.31 release video"})," to see the demo"]}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"option-2-configure-globalsetup-and-globalteardown",children:"Option 2: Configure globalSetup and globalTeardown"}),"\n",(0,a.jsxs)(t.p,{children:["You can use the ",(0,a.jsx)(t.code,{children:"globalSetup"})," option in the ",(0,a.jsx)(t.a,{href:"/docs/test-configuration#advanced-configuration",children:"configuration file"})," to set something up once before running all tests. The global setup file must export a single function that takes a config object. This function will be run once before all the tests."]}),"\n",(0,a.jsxs)(t.p,{children:["Similarly, use ",(0,a.jsx)(t.code,{children:"globalTeardown"})," to run something once after all the tests. Alternatively, let ",(0,a.jsx)(t.code,{children:"globalSetup"})," return a function that will be used as a global teardown. You can pass data such as port number, authentication tokens, etc. from your global setup to your tests using environment variables."]}),"\n",(0,a.jsx)(t.admonition,{type:"note",children:(0,a.jsxs)(t.p,{children:["Beware that ",(0,a.jsx)(t.code,{children:"globalSetup"})," and ",(0,a.jsx)(t.code,{children:"globalTeardown"})," lack some features \u2014 see the ",(0,a.jsx)(t.a,{href:"#introduction",children:"intro"})," section for a detailed comparison. Consider using ",(0,a.jsx)(t.a,{href:"#option-1-project-dependencies",children:"project dependencies"})," instead to get full feature support."]})}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="playwright.config.ts"',children:"import { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n globalSetup: require.resolve('./global-setup'),\n globalTeardown: require.resolve('./global-teardown'),\n});\n"})}),"\n",(0,a.jsx)(t.h3,{id:"example",children:"Example"}),"\n",(0,a.jsxs)(t.p,{children:["Here is a global setup example that authenticates once and reuses authentication state in tests. It uses the ",(0,a.jsx)(t.code,{children:"baseURL"})," and ",(0,a.jsx)(t.code,{children:"storageState"})," options from the configuration file."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="global-setup.ts"',children:"import { chromium, type FullConfig } from '@playwright/test';\n\nasync function globalSetup(config: FullConfig) {\n const { baseURL, storageState } = config.projects[0].use;\n const browser = await chromium.launch();\n const page = await browser.newPage();\n await page.goto(baseURL!);\n await page.getByLabel('User Name').fill('user');\n await page.getByLabel('Password').fill('password');\n await page.getByText('Sign in').click();\n await page.context().storageState({ path: storageState as string });\n await browser.close();\n}\n\nexport default globalSetup;\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Specify ",(0,a.jsx)(t.code,{children:"globalSetup"}),", ",(0,a.jsx)(t.code,{children:"baseURL"})," and ",(0,a.jsx)(t.code,{children:"storageState"})," in the configuration file."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="playwright.config.ts"',children:"import { defineConfig } from '@playwright/test';\nexport default defineConfig({\n globalSetup: require.resolve('./global-setup'),\n use: {\n baseURL: 'http://localhost:3000/',\n storageState: 'state.json',\n },\n});\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Tests start already authenticated because we specify ",(0,a.jsx)(t.code,{children:"storageState"})," that was populated by global setup."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",children:"import { test } from '@playwright/test';\n\ntest('test', async ({ page }) => {\n await page.goto('/');\n // You are signed in!\n});\n"})}),"\n",(0,a.jsxs)(t.p,{children:["You can make arbitrary data available in your tests from your global setup file by setting them as environment variables via ",(0,a.jsx)(t.code,{children:"process.env"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="global-setup.ts"',children:"import type { FullConfig } from '@playwright/test';\n\nasync function globalSetup(config: FullConfig) {\n process.env.FOO = 'some data';\n // Or a more complicated data structure as JSON:\n process.env.BAR = JSON.stringify({ some: 'data' });\n}\n\nexport default globalSetup;\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Tests have access to the ",(0,a.jsx)(t.code,{children:"process.env"})," properties set in the global setup."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",children:"import { test } from '@playwright/test';\n\ntest('test', async ({ page }) =>
1 {\n // environment variables which are set in globalSetup are only available inside test().\n const { FOO, BAR } = process.env;\n\n // FOO and BAR properties are populated.\n expect(FOO).toEqual('some data');\n\n const complexData = JSON.parse(BAR);\n expect(BAR).toEqual({ some: 'data' });\n});\n"})}),"\n",(0,a.jsx)(t.h3,{id:"capturing-trace-of-failures-during-global-setup",children:"Capturing trace of failures during global setup"}),"\n",(0,a.jsxs)(t.p,{children:["In some instances, it may be useful to capture a trace of failures encountered during the global setup. In order to do this, you must ",(0,a.jsx)(t.a,{href:"/docs/api/class-tracing#tracing-start",children:"start tracing"})," in your setup, and you must ensure that you ",(0,a.jsx)(t.a,{href:"/docs/api/class-tracing#tracing-stop",children:"stop tracing"})," if an error occurs before that error is thrown. This can be achieved by wrapping your setup in a ",(0,a.jsx)(t.code,{children:"try...catch"})," block. Here is an example that expands the global setup example to capture a trace."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-js",metastring:'title="global-setup.ts"',children:"import { chromium, type FullConfig } from '@playwright/test';\n\nasync function globalSetup(config: FullConfig) {\n const { baseURL, storageState } = config.projects[0].use;\n const browser = await chromium.launch();\n const context = await browser.newContext();\n const page = await context.newPage();\n try {\n await context.tracing.start({ screenshots: true, snapshots: true });\n await page.goto(baseURL!);\n await page.getByLabel('User Name').fill('user');\n await page.getByLabel('Password').fill('password');\n await page.getByText('Sign in').click();\n await context.storageState({ path: storageState as string });\n await context.tracing.stop({\n path: './test-results/setup-trace.zip',\n });\n await browser.close();\n } catch (error) {\n await context.tracing.stop({\n path: './test-results/failed-setup-trace.zip',\n });\n await browser.close();\n throw error;\n }\n}\n\nexport default globalSetup;\n"})})]})}function p(e={}){let{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.