All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mark59.scripting.playwright.JmeterFunctionsForPlaywrightScripts Maven / Gradle / Ivy

/*
 *  Copyright 2019 Mark59.com
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License"); 
 *  you may not use this file except in compliance with the License. 
 *  You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *      
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mark59.scripting.playwright;

import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.mark59.core.JmeterFunctionsImpl;
import com.mark59.core.utils.Mark59LogLevels;
import com.mark59.scripting.AbstractJmeterFunctionsUiCommon;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Tracing;
import com.microsoft.playwright.Page.ScreenshotOptions;

/**
 * Playwright flavored extension of the Mark59 class {@link AbstractJmeterFunctionsUiCommon} ( whose primary purpose to to handle transaction
 *  results,implemented in Mark59 by the use of 'sub-results' within a {@link SampleResult} )    
 * 
 * 

This class is designed to additionally implement Playwright related functions within Mark59, in particular logging. * *

At instantiation, transaction level logging usage is set, based on the log4j level. This can be over-ridden via JMeter parameters * and/or directly calling the methods in this class from the script. * Please refer to {@link #overrideTxnLoggingBehaviourUsingJmeterParameters(Map)}

* *

From JMeter, Playwright scripts (that extend {@link PlaywrightAbstractJavaSamplerClient}) have been provisioned to have transaction-level * 'logging settings' available.
* *

Current default outputs setting are : * *

Trace Level: *

    *
  • write Screenshots At Start and End OfTransactions *
  • write Page Source At Start and End OfTransactions *
*

Debug Level: *

    *
  • write Screenshots End Of Transactions *
  • write Page Source End Of Transactions *
*

No screenshot/log transaction level at Info or above, except for exception handling, which occurs regardless of log4j level * *

For debugging a troublesome script during execution, note that 'buffered' logs can be set in script * (For example see {@link #logAllLogsAtEndOfTransactions(Mark59LogLevels)} ) * *

Finer grained control within a script can be achieved using methods to setting the individual logging flags. * *

An example of transaction-level logging in use: *


 * if (LOG.isInfoEnabled()) jm.logScreenshotsAtStartOfTransactions(Mark59LogLevels.WRITE);
 * jm.startTransaction("Some-transaction-whose-screenshot-i-want-to-see-at-the-start-when-at-log4j-INFO-level");
 *       :
 * //OK, now just go back to the default behavior for the current Log4j level..  	 
 * if (LOG.isInfoEnabled()) jm.logScreenshotsAtStartOfTransactions(Mark59LogLevels.DEFAULT);
 * 
* * @see Mark59LogLevels * @see JmeterFunctionsImpl * @see PlaywrightAbstractJavaSamplerClient#scriptExceptionHandling(JavaSamplerContext, Map, Throwable) * * @author Philip Webb * Written: Australian Summer 2023/24 */ public class JmeterFunctionsForPlaywrightScripts extends AbstractJmeterFunctionsUiCommon { /** log4J class logger */ public static final Logger LOG = LogManager.getLogger(JmeterFunctionsForPlaywrightScripts.class); private Page page; /** * @param context the JMeter JavaSamplerContext * @param jmeterRuntimeArgumentsMap used to override default state of Mark59 log output */ public JmeterFunctionsForPlaywrightScripts(JavaSamplerContext context, Map jmeterRuntimeArgumentsMap) { super(context, jmeterRuntimeArgumentsMap); } /** * @return page a playwright page */ public Page getPage() { return page; } /** * @param page a playwright page */ public void setPage(Page page) { this.page = page; } /** * (Playwright Only) As per {@link #writeScreenshot(String)}, but allows user to pass any desired * Playwright Page and optionally ScreenshotOptions. * * @param page a Playwright Page object * @param imageName last part of the log filename (but excluding extension - which is set as '.jpg') * @param options Playwright ScreenshotOptions */ public void writePageScreenshot(Page page, String imageName, ScreenshotOptions options) { writeLog(imageName,"jpg", page.screenshot(options)); } /** * (Playwright Only) As perAs per {@link #bufferScreenshot(String)}, but allows user to pass any desired * Playwright Page and optionally set ScreenshotOptions. *

If you want to immediately write a screenshot to file, use {@link #writeScreenshot(String)} instead. * * @param page a Playwright Page object * @param imageName last part of the log filename (but excluding extension - which is set as '.jpg') * @param options Playwright ScreenshotOptions * * @see JmeterFunctionsImpl#writeBufferedArtifacts() * @see PlaywrightAbstractJavaSamplerClient#UiScriptExecutionAndExceptionsHandling(JavaSamplerContext, Map, String) */ public void bufferScreenshot(Page page, String imageName, ScreenshotOptions options) { bufferLog(imageName,"jpg", page.screenshot(options)); } /** * Capture and immediately output one or more screenshot (.jpg) logs. Use with caution in a Performance * and Volume test as misuse of this method may produce many more screenshots than intended. *

Instead, you could use {@link #bufferScreenshot(String)} and {@link #writeBufferedArtifacts()}. *

All pages associated with the {@link PlaywrightAbstractJavaSamplerClient#browser}, are screenshot, so * more than one file can potentially be written when invoking this method. * * @param imageName last part of the log filename (but excluding extension - which is set as '.jpg') */ @Override public void writeScreenshot(String imageName) { List ctxPages = listBrowerCtxPages(); for (int i = 0; i < ctxPages.size(); i++) { writeLog(unique(imageName,ctxPages,i), "jpg", ctxPages.get(i).screenshot()); } } /** * Stores one or more screenshot (.jpg) logs in memory, ready to be written to file later. * If you want to immediately write a screenshot to file, use {@link #writeScreenshot(String)} instead. *

All pages associated with the {@link PlaywrightAbstractJavaSamplerClient#browser} are screenshot, so * more than one file can potentially be buffered when invoking this method. * * @param imageName last part of the log filename (but excluding extension - which is set as '.jpg') * * @see JmeterFunctionsImpl#writeBufferedArtifacts() * @see PlaywrightAbstractJavaSamplerClient#UiScriptExecutionAndExceptionsHandling(JavaSamplerContext, Map, String) */ @Override public void bufferScreenshot(String imageName) { List ctxPages = listBrowerCtxPages(); for (int i = 0; i < ctxPages.size(); i++) { bufferLog(unique(imageName,ctxPages,i), "jpg", ctxPages.get(i).screenshot()); } } /** * Capture and immediately output a page source (.html) log. Use with caution in a Performance and Volume * test as misuse of this method may produce many more screenshots than intended. *

Instead, you could use {@link #bufferPageSource(String)} and {@link #writeBufferedArtifacts()}. *

All pages associated with the {@link PlaywrightAbstractJavaSamplerClient#browser}, are have their * page source taken, so more than one file can potentially be written when invoking this method. * * @param imageName last part of the log filename (but excluding extension - which is set as '.html') */ public void writePageSource(String imageName) { List ctxPages = listBrowerCtxPages(); for (int i = 0; i < ctxPages.size(); i++) { writeLog(unique(imageName,ctxPages,i), "html", captureCurrentUrlAndtHtmlPageSource(ctxPages.get(i)).getBytes()); } } /** * Stores a page source (.html) log in memory, ready to be written to file later. * If you want to immediately write a screenshot to file, use {@link #writePageSource(String)} instead. *

All pages associated with the {@link PlaywrightAbstractJavaSamplerClient#browser}, are have their * page source taken, so more than one file can potentially be buffered when invoking this method. * * @param imageName last part of the log filename (but excluding extension - which is set as '.html') */ public void bufferPageSource(String imageName) { List ctxPages = listBrowerCtxPages(); for (int i = 0; i < ctxPages.size(); i++) { bufferLog(imageName, "html", captureCurrentUrlAndtHtmlPageSource(ctxPages.get(i)).getBytes()); } } /** * Note Performance logging is only implemented for selenium scripts * @param textFileName last part of the log filename (excluding extension) */ public void writeDriverPerfLogs(String textFileName) { // no-op } /** * Note Performance logging is only implemented for selenium scripts * @param textFileName last part of the log filename (excluding extension) */ public void bufferDriverPerfLogs(String textFileName) { // no-op } /** * Convenience method to start a Playwright trace, with StartOptions set to true. *
Only intended to be used when debugging a script. Use with extreme care in a performance test! *

* page.context().tracing().start(new Tracing.StartOptions().setScreenshots(true).setSnapshots(true).setSources(true)); * * @see #stopPlayWrightTrace(String) */ public void startPlayWrightTrace() { page.context().tracing() .start(new Tracing.StartOptions().setScreenshots(true).setSnapshots(true).setSources(true)); } /** * Convenience method to stop a Playwright trace, and set location of the trace zip file. *

Sample Usage:
* jm.stopPlayWrightTrace("C:/Test/trace.zip"); *

This would put the trace.zip file in you project root when running from Eclipse:
* jm.stopPlayWrightTrace("trace.zip"); * @param tracePath location of the trace zip file * @see #startPlayWrightTrace() */ public void stopPlayWrightTrace(String tracePath) { page.context().tracing().stop(new Tracing.StopOptions().setPath(Paths.get(tracePath))); } /** * @return returns a string describing the url and full contents of the current page */ private String captureCurrentUrlAndtHtmlPageSource(Page ctxPage) { String currentURL = ctxPage.url(); String pageSource = ctxPage.content(); return " \n" + pageSource; } private List listBrowerCtxPages() { List ctxPages = new ArrayList(); List browserContexts = new ArrayList(); try { browserContexts = page.context().browser().contexts(); } catch (Exception e) { // just return the original page object ctxPages.add(page); return ctxPages; } for (BrowserContext browserContext : browserContexts){ for (Page cxtPage: browserContext.pages()) { ctxPages.add(cxtPage); } } return ctxPages; } /** * @param imageName imageName * @param ctxPages list of pages * @param ctxPageIx current index on ctxPages * @return a unique image name, using a counter and the page title (first 20 chars) */ private String unique(String imageName, List ctxPages, int ctxPageIx) { String uniqueImageName = imageName; if (ctxPages.size()>1) { uniqueImageName += "_" + (ctxPageIx+1) + "_" + StringUtils.left(Objects.toString(ctxPages.get(ctxPageIx).title(),"noTitle").replaceAll("[^a-zA-Z0-9]",""), 20); } return uniqueImageName; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy