1616
1717package com .microsoft .playwright .impl .junit ;
1818
19- import com .microsoft .playwright .Browser ;
20- import com .microsoft .playwright .BrowserContext ;
21- import com .microsoft .playwright .Playwright ;
22- import com .microsoft .playwright .PlaywrightException ;
19+ import com .microsoft .playwright .*;
2320import com .microsoft .playwright .impl .Utils ;
2421import com .microsoft .playwright .junit .Options ;
2522import org .junit .jupiter .api .extension .*;
2623
24+ import java .io .IOException ;
25+ import java .nio .file .Files ;
26+ import java .nio .file .Path ;
27+ import java .nio .file .Paths ;
28+
2729import static com .microsoft .playwright .impl .junit .ExtensionUtils .*;
30+ import static com .microsoft .playwright .impl .junit .PageExtension .cleanUpPage ;
2831
29- public class BrowserContextExtension implements ParameterResolver , AfterEachCallback {
32+ public class BrowserContextExtension implements ParameterResolver , TestWatcher {
3033 private static final ThreadLocal <BrowserContext > threadLocalBrowserContext = new ThreadLocal <>();
3134
32- @ Override
33- public void afterEach (ExtensionContext extensionContext ) {
34- BrowserContext browserContext = threadLocalBrowserContext .get ();
35- threadLocalBrowserContext .remove ();
36- if (browserContext != null ) {
37- browserContext .close ();
38- }
39- }
40-
4135 @ Override
4236 public boolean supportsParameter (ParameterContext parameterContext , ExtensionContext extensionContext ) throws ParameterResolutionException {
4337 return !isClassHook (extensionContext ) && isParameterSupported (parameterContext , extensionContext , BrowserContext .class );
@@ -51,6 +45,7 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
5145 /**
5246 * Returns the BrowserContext that belongs to the current test. Will be created if it doesn't already exist.
5347 * <strong>NOTE:</strong> this method is subject to change.
48+ *
5449 * @param extensionContext the context in which the current test or container is being executed.
5550 * @return The BrowserContext that belongs to the current test.
5651 */
@@ -66,10 +61,97 @@ public static BrowserContext getOrCreateBrowserContext(ExtensionContext extensio
6661 Browser browser = BrowserExtension .getOrCreateBrowser (extensionContext );
6762 Browser .NewContextOptions contextOptions = getContextOptions (playwright , options );
6863 browserContext = browser .newContext (contextOptions );
64+ if (shouldRecordTrace (options )) {
65+ Tracing .StartOptions startOptions = new Tracing .StartOptions ().setSnapshots (true ).setScreenshots (true ).setTitle (extensionContext .getDisplayName ());
66+ if (System .getenv ("PLAYWRIGHT_JAVA_SRC" ) != null ) {
67+ startOptions .setSources (true );
68+ }
69+ browserContext .tracing ().start (startOptions );
70+ }
6971 threadLocalBrowserContext .set (browserContext );
7072 return browserContext ;
7173 }
7274
75+ @ Override
76+ public void testSuccessful (ExtensionContext extensionContext ) {
77+ saveTraceWhenOn (extensionContext );
78+ closeBrowserContext ();
79+ }
80+
81+ @ Override
82+ public void testAborted (ExtensionContext extensionContext , Throwable cause ) {
83+ saveTraceWhenOn (extensionContext );
84+ closeBrowserContext ();
85+ }
86+
87+ @ Override
88+ public void testFailed (ExtensionContext extensionContext , Throwable cause ) {
89+ Options options = OptionsExtension .getOptions (extensionContext );
90+ if (shouldRecordTrace (options )) {
91+ saveTrace (extensionContext );
92+ }
93+ closeBrowserContext ();
94+ }
95+
96+ private static void saveTraceWhenOn (ExtensionContext extensionContext ) {
97+ Options options = OptionsExtension .getOptions (extensionContext );
98+ if (options .trace .equals (Options .Trace .ON )) {
99+ saveTrace (extensionContext );
100+ }
101+ }
102+
103+ private static void saveTrace (ExtensionContext extensionContext ) {
104+ BrowserContext browserContext = threadLocalBrowserContext .get ();
105+ if (browserContext == null ) {
106+ return ;
107+ }
108+ Path outputPath = getOutputPath (extensionContext );
109+ createOutputPath (outputPath );
110+ Tracing .StopOptions stopOptions = new Tracing .StopOptions ().setPath (outputPath .resolve ("trace.zip" ));
111+ browserContext .tracing ().stop (stopOptions );
112+ }
113+
114+ private static void createOutputPath (Path outputPath ) {
115+ if (!Files .exists (outputPath )) {
116+ try {
117+ Files .createDirectories (outputPath );
118+ } catch (IOException e ) {
119+ throw new RuntimeException (e );
120+ }
121+ }
122+ }
123+
124+ private static Path getOutputPath (ExtensionContext extensionContext ) {
125+ BrowserType browserType = BrowserExtension .getBrowser ().browserType ();
126+ Path defaultOutputPath = getDefaultOutputPath (extensionContext );
127+ String outputDirName = extensionContext .getRequiredTestClass ().getName () + "." +
128+ extensionContext .getRequiredTestMethod ().getName () + "-" +
129+ browserType .name ();
130+ return defaultOutputPath .resolve (outputDirName );
131+ }
132+
133+ private static Path getDefaultOutputPath (ExtensionContext extensionContext ) {
134+ Options options = OptionsExtension .getOptions (extensionContext );
135+ Path outputPath = options .outputDir ;
136+ if (outputPath == null ) {
137+ outputPath = Paths .get (System .getProperty ("user.dir" )).resolve ("test-results" );
138+ }
139+ return outputPath ;
140+ }
141+
142+ private void closeBrowserContext () {
143+ cleanUpPage ();
144+ BrowserContext browserContext = threadLocalBrowserContext .get ();
145+ threadLocalBrowserContext .remove ();
146+ if (browserContext != null ) {
147+ browserContext .close ();
148+ }
149+ }
150+
151+ private static boolean shouldRecordTrace (Options options ) {
152+ return options .trace .equals (Options .Trace .ON ) || options .trace .equals (Options .Trace .RETAIN_ON_FAILURE );
153+ }
154+
73155 private static Browser .NewContextOptions getContextOptions (Playwright playwright , Options options ) {
74156 Browser .NewContextOptions contextOptions = Utils .clone (options .contextOptions );
75157 if (contextOptions == null ) {
@@ -94,7 +176,7 @@ private static Browser.NewContextOptions getContextOptions(Playwright playwright
94176 contextOptions .hasTouch = deviceDescriptor .hasTouch ;
95177 }
96178
97- if (options .ignoreHTTPSErrors != null ) {
179+ if (options .ignoreHTTPSErrors != null ) {
98180 contextOptions .setIgnoreHTTPSErrors (options .ignoreHTTPSErrors );
99181 }
100182
0 commit comments