Screenshots of playwright failing to work on Github.''

Within my playwright.config.ts file, I have specified the following:

use: {
  ...
  screenshot: 'only-on-failure',
}

When running tests locally and they fail, screenshots are successfully saved in /test-results. However, the issue arises when the tests fail while running in Github Actions, as no screenshots are generated. This makes it challenging for me to identify the cause of the failures, especially since the tests pass without any issues locally.

The CI-specific sections of my configuration are as follows:

/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: process.env.CI ? 'github' : 'list',

Additionally, my action.yml file attempts to upload the /test-results folder, but it always appears to be empty since no screenshots were captured:

- uses: actions/upload-artifact@v2
  if: always()
  with:
    name: playwright-test-results
    path: test-results/

Answer №1

To include the test-results folder as a run artifact in GitHub, we can utilize the "upload-artifact" action after the suite execution is complete.

Another option is to incorporate a step in the workflow that specifically uploads the images to a specified location post test run.

Answer №2

// Configuration for Playwright tests
import { PlaywrightTestConfig, devices } from '@playwright/test';

const config: PlaywrightTestConfig = {
    forbidOnly: !!process.env.CI,
    retries: process.env.CI ? 2 : 1,
    use: {
        trace: 'on',
        screenshot: 'only-on-failure',
        video: 'retain-on-failure',
        headless: true,
        viewport: { width: 1280, height: 720 },
        baseURL: "https:xxxxx",
        launchOptions: {
            slowMo: 50,
            logger: {
                isEnabled: (name, severity) => name === 'browser',
                log: (name, severity, message, args) => console.log(`${name} ${message}`)
            }
        },
        actionTimeout: 10 * 1000,
        navigationTimeout: 30 * 1000
    },
    expect: {
        timeout: 10 * 1000
    },
    timeout: 90000,
    outputDir: `${__dirname}/build`,
    projects: [
        {
            name: 'chromium',
            use: { ...devices['Desktop Chrome'] }
        }
    ],
    reporter: [
        ['junit', { outputFile: 'build/results.xml' }],
        ['html', { outputFolder: 'build/html-report', open: 'never' }],
        ['list']
    ]
};
export default config;

// .gitlab-ci.yml

.e2e:
  stage: postdeploy
  image: xxxxx
  script:
    - pnpm xxx
    - pnpm nx test e2e
  after_script:
    - ls -l tests/e2e
    - cp -r tests/e2e/build ./results

  artifacts:
    when: always
    expire_in: never
    name: 'test-artifacts'
    paths:
      - results/html-report
    exclude:
      - results/results.xml
    reports:
      junit: results/results.xml

Answer №3

If you find that your uploads folder is empty, it is likely due to using a relative path. The upload-artifact plugin does not adhere to the working-directory setting, as discussed here: https://github.com/actions/upload-artifact/issues/232#issuecomment-964235360

Once this issue is resolved, you should be able to download the zip file and find the screenshots inside.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Updating during an ongoing state transition is not possible, especially within the `render` method. The `render` method should strictly be a pure function based on the props and state provided

Currently, I am utilizing react and react hooks for the front-end development of my project. Unfortunately, I have encountered an error message that states: index.js:1 Warning: Cannot update during an existing state transition (such as within `render` ...

Transmit the identification to angularjs for the genuine content to be displayed

I have a hidden field where I store an Id, which can also be 2, 3, 4, or 59. I need to send this Id from the hidden field to my opgaver.js file so it can download the content. However, I am facing difficulty in figuring out how to pass the Id to the opgav ...

Adjust the size of a Div/Element in real-time using a randomly calculated number

Currently, I am working on a script that is designed to change the dimensions of a div element when a button on the page is clicked. The JavaScript function connected to this button should generate a random number between 1 and 1000, setting it as both the ...

I'm attempting to create a button using html, but I'm puzzled as to why it's not functioning as expected

I've been working on creating a button that, when pressed, generates a new div string based on the node.innerHTML code. For some reason, my code doesn't seem to be functioning properly and I'm not sure why. Here's the HTML: <input ...

Having trouble with my TinyMCE Editor not loading content data in the Edit.vue component of my Vue 3 project with Vite

I am currently working on a Vue 3 project using Vite and incorporating Editor.vue components with TinyMCE. The code snippet for my Editor.vue component is shown below: My Editor.vue code: <template> <div class="mb-6"> < ...

When using Jest, it is not possible to match 'undefined' using 'expect.any(Object)' or 'expect.anything()'

Looking to test the following module. import * as apiUtils from './apiUtils'; export function awardPoints(pointsAwarding) { return apiUtils.callApiService("POST", "points", pointsAwarding); } This is the test in question. it("should call ap ...

Use two separate AJAX requests to open and close the modal dialog

I am experiencing an issue with my subscription form that uses modal windows. After closing the window and trying to subscribe again, the ajax calls are being duplicated, resulting in an error. $("#openModal").click(function() { if($("#wname").val() = ...

Maintaining the "Date" value in React Native DatePickerIOS when returning from other pages

In my scenario, I am using the DatePickerIOS component. The example in the documentation initializes a new Date() and uses state to store and update the Date value. However, when navigating to another page and returning, the time changes and I find myself ...

Accessing the current frame of a video in JavaScript or jQuery

Currently, I am experimenting with the HTML video tag to play a video. Instead of retrieving the "currentTime" of the video, I am interested in obtaining the current frame using either jQuery or JavaScript. Despite my efforts in calculating the frame rate ...

Problem concerning the window object in a React functional component

Hey there, I am currently facing a situation where I need to access the window object within my React component in order to retrieve some information from the query string. Here is an excerpt of what my component code looks like: export function MyCompone ...

What is the best way to iterate through an array of images and upload them individually, ensuring that they do not have duplicate names

In my current code snippet, I am working with an array of images called images and uploading each image within that array. Everything seems to be working correctly, but I am encountering a minor issue where all the uploaded images end up having the same na ...

The form will only display results after the "Submit" button is clicked twice

Recently, I built a flask website where the form and results are displayed on the same page. However, there seems to be an issue that arises upon clicking the 'submit' button for the first time after running 'flask run'. The error messa ...

Ways to substitute the $(document).ready function?

I'm facing a problem and struggling to find a solution. Here is the JavaScript script that's causing me trouble: $(function () { $.ajaxSetup({ cache: false }); var timer = window.setTimeout(function () { $(".alert").fadeTo(10 ...

What is the best way to showcase a collapsible tree using AngularJS and Bootstrap?

I'm currently working on a web application that requires the display of a tree structure using lists. Here is the basic outline: * Node 1 * Node 1.1 * Node 1.1.1 * Node 1.1.1.1 * Node 1.1.2 * Node 1.2 http://jsfid ...

Sending a value to a text box using json data transmission

I am having trouble accessing data from a js file and fetching the value to an html text box. Despite trying, I'm unable to get the desired result. Below are the contents of samle.js file and jsonhtml.html file: { "var1": "1", "var2": "2" } <scri ...

Obtain module-specific members through programmatic means

When working on a browser, the code may appear like this: //retrieve all enumerable properties of `this` function globalMems() { var g = this; var ret = {}; for (var prop in g) { ret[prop] = g[prop]; } return ret; } In Node.js, this does ...

"Transferring a variable from the parent Layout component to its children components in Next

I am trying to figure out how to effectively pass the variable 'country' from the Layout component to its children without using state management. Basically, I want to drill it down. import { useState, useEffect } from 'react' import La ...

What is the best way to retrieve a {collection object} from a JavaScript map?

My application utilizes a third-party library that returns the map in the following format: public sids: Map<SocketId, Set<Room>> = new Map(); When I try to access it using the code below: io.of("/").adapter.sids.forEach(function(va ...

Sending data from an external input field to a form using AngularJS programmatically with element name

I am facing a challenge where I need to include an Input element in a Form, even though the Input is located outside of the form. While I have managed to add the input using form.$addControl(outerInput), it is not producing the desired outcome as shown in ...

What is the most effective way to programmatically recreate scope in AngularJS?

Currently, I am working on implementing UI-router to handle state changes in my application. My initial belief was that switching states on a dynamic route would result in the current scope getting destroyed and a new scope being created for the template w ...