reactjsautomated-testsplaywrightvitest

Snapshot for visual testing is not capturing entire component


I am using vitest with vitest-plugin-vis and playwright to perform visual testing in my Vite project. The issue I am facing is that the snapshots that are generated are only capturing part of my components.

Here is an example that tests my error component. As you can see, it is not very helpful as most of the error component is outside of the captured image. error boundary

Is there a way to make sure the entire component is captured and/or that you can set the width of the viewport?

Here is my vitest.config.js:

import defineConfig from "./vitest.base.config";
import { mergeConfig } from "vitest/config";
import { resolve } from "node:path";
import { vis } from 'vitest-plugin-vis/config';

const vitestBaseConfig = await defineConfig;

export default mergeConfig(vitestBaseConfig, {
    plugins: [vis(
        { preset: 'auto' }
    )],
    test: {
    exclude: [ "**/__tests__/*"],
        browser: {
            provider: 'playwright',
            enabled: true,
            headless: true,
            instances: [
                { browser: 'chromium' }
            ],
        },
        mockReset: true,
        setupFiles: ["./src/test-setup.ts"],
        alias: {}
    },
    resolve: {
        alias: {
            "@mendix/extensions-api": resolve(__dirname, "./__mocks__/@mendix/extensions-api.ts")
        }
    }
});

And here is my test:

import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { render } from "vitest-browser-react";
import ErrorBoundary from "../ErrorBoundary";
import { screen } from "@testing-library/react";
import { setAutoSnapshotOptions } from "vitest-plugin-vis";

describe("ErrorBoundary", () => {
    let consoleErrorSpy: ReturnType<typeof vi.spyOn>;

    beforeEach(() => {
        consoleErrorSpy = vi.spyOn(console, "trace").mockImplementation(() => {});
    });

    afterEach(() => {
        consoleErrorSpy.mockRestore();
    });
    
    test("renders outer error boundary", () => {
        setAutoSnapshotOptions({ enable: true });

        renderOuterErrorBoundary();

        const errorBoundary = screen.getByRole("alert");

        expect(errorBoundary).toMatchImageSnapshot();
    });
});

const renderOuterErrorBoundary = () =>
    render(
        <ErrorBoundary isOuterErrorBoundary={true}>
            <ErrorThrowingComponent />
        </ErrorBoundary>
    );

const ErrorThrowingComponent = () => {
    const error = new Error("Oops");
    error.stack = "Test stack"; // Stack can contain random ids. Therefore, we overwrite it with something constant, so it is constant during testing
    error.cause = "Test cause"; // Cause can contain random ids. Therefore, we overwrite it with something constant, so it is constant during testing

    throw error;
};

Solution

  • You can add a viewport definition to your configuration:

    test: {
            exclude: ["**/__tests__/*"],
            browser: {
                provider: "playwright",
                enabled: true,
                headless: true,
                instances: [{ browser: "chromium" }],
                viewport: { width: 1980, height: 1200 }
            },
            mockReset: true,
            setupFiles: ["./src/test-setup.ts"],
            alias: {}
        },