CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-storybook--vue3

Storybook Vue 3 renderer for developing, documenting, and testing UI components in isolation

Pending
Overview
Eval results
Files

component-testing.mddocs/

Component Testing with Playwright

Integration with Playwright for component testing, providing utilities to create test functions for Vue components within the Storybook environment. This enables automated browser-based testing of individual components and stories.

Capabilities

Create Test Function

Creates a Playwright test function specifically designed for component testing with Storybook Vue 3 components.

/**
 * Creates Playwright test function for component testing.
 * Provides a test runner that can render and interact with Vue components
 * in a browser environment using Playwright.
 * 
 * @param options - Configuration options for the test runner
 */
function createTest(options?: any): any;

Usage Example:

import { createTest } from "@storybook/vue3/experimental-playwright";
import { test, expect } from "@playwright/experimental-ct-vue";

const storybookTest = createTest();

storybookTest("Button renders correctly", async ({ mount }) => {
  const component = await mount(MyButton, {
    props: {
      label: "Click me",
      primary: true,
    },
  });

  await expect(component).toContainText("Click me");
  await expect(component).toHaveClass(/btn-primary/);
});

Advanced Testing Patterns

Testing with Stories

import { createTest } from "@storybook/vue3/experimental-playwright";
import { composeStory } from "@storybook/vue3";
import Meta, { Primary } from "./Button.stories";

const test = createTest();
const PrimaryStory = composeStory(Primary, Meta);

test("Primary story renders correctly", async ({ mount }) => {
  const component = await mount(PrimaryStory);
  
  await expect(component).toBeVisible();
  await expect(component.getByRole("button")).toHaveText("Button");
});

Interactive Testing

import { createTest } from "@storybook/vue3/experimental-playwright";

const test = createTest();

test("Button interaction", async ({ mount }) => {
  let clicked = false;
  
  const component = await mount(MyButton, {
    props: {
      label: "Click me",
      onClick: () => { clicked = true; },
    },
  });

  await component.getByRole("button").click();
  expect(clicked).toBe(true);
});

Form Testing

import { createTest } from "@storybook/vue3/experimental-playwright";

const test = createTest();

test("Form submission", async ({ mount }) => {
  const component = await mount(ContactForm, {
    props: {
      onSubmit: (data) => console.log("Form submitted:", data),
    },
  });

  await component.getByLabel("Name").fill("John Doe");
  await component.getByLabel("Email").fill("john@example.com");
  await component.getByRole("button", { name: "Submit" }).click();

  await expect(component.getByText("Form submitted successfully")).toBeVisible();
});

Component Testing Configuration

Playwright Config Setup

// playwright-ct.config.ts
import { defineConfig, devices } from "@playwright/experimental-ct-vue";
import { resolve } from "path";

export default defineConfig({
  testDir: "./src/components",
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: "html",
  use: {
    trace: "on-first-retry",
    ctViteConfig: {
      resolve: {
        alias: {
          "@": resolve(__dirname, "./src"),
        },
      },
    },
  },
  projects: [
    {
      name: "chromium",
      use: { ...devices["Desktop Chrome"] },
    },
    {
      name: "firefox",
      use: { ...devices["Desktop Firefox"] },
    },
    {
      name: "webkit",
      use: { ...devices["Desktop Safari"] },
    },
  ],
});

Test Setup File

// test-setup.ts
import { beforeMount } from "@playwright/experimental-ct-vue";
import { setup } from "@storybook/vue3";
import { createPinia } from "pinia";

// Setup global plugins for component tests
setup(() => createPinia());

beforeMount(async ({ app }) => {
  // Additional test-specific setup
  app.config.globalProperties.$testMode = true;
});

Testing Best Practices

Component Isolation

import { createTest } from "@storybook/vue3/experimental-playwright";

const test = createTest();

test.describe("Button Component", () => {
  test("renders with default props", async ({ mount }) => {
    const component = await mount(MyButton);
    await expect(component).toBeVisible();
  });

  test("applies custom styling", async ({ mount }) => {
    const component = await mount(MyButton, {
      props: { variant: "danger", size: "large" },
    });
    
    await expect(component).toHaveClass(/btn-danger/);
    await expect(component).toHaveClass(/btn-lg/);
  });
});

Accessibility Testing

import { createTest } from "@storybook/vue3/experimental-playwright";
import AxeBuilder from "@axe-core/playwright";

const test = createTest();

test("Button is accessible", async ({ mount, page }) => {
  await mount(MyButton, {
    props: { label: "Accessible Button" },
  });

  const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
  expect(accessibilityScanResults.violations).toEqual([]);
});

Visual Regression Testing

import { createTest } from "@storybook/vue3/experimental-playwright";

const test = createTest();

test("Button visual regression", async ({ mount }) => {
  const component = await mount(MyButton, {
    props: { 
      label: "Visual Test Button",
      primary: true,
    },
  });

  await expect(component).toHaveScreenshot("primary-button.png");
});

Integration with CI/CD

# .github/workflows/component-tests.yml
name: Component Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      
      - name: Install dependencies
        run: npm install
      
      - name: Install Playwright
        run: npx playwright install --with-deps
        
      - name: Run component tests
        run: npx playwright test -c playwright-ct.config.ts
        
      - name: Upload test results
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: playwright-report
          path: playwright-report/

Install with Tessl CLI

npx tessl i tessl/npm-storybook--vue3

docs

app-setup.md

component-testing.md

index.md

portable-stories.md

story-types.md

tile.json