agentsclimarketplace

Test ui qsf

Skill lgtm-hq/ai-skills/skills/test-ui-qsf

Canonical Agent Skills library for Claude Code, Cursor, Codex, and other agents.

Install
npx -y skills add lgtm-hq/ai-skills --skill test-ui-qsf

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

QSF project conventions for the Playwright E2E suite. Use when working in the QSF playwright-tests directory (authFixtures, ___ping-* handles, data-test-label test IDs, .auth storage states) — not for generic Playwright advice.

SKILL.md

6.4 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it

QSF Playwright E2E Conventions

Project-specific conventions for the QSF Playwright suite. For generic Playwright best practices (locators, auto-waiting, POM, anti-patterns), follow the test-ui skill — this skill only adds what is QSF-specific.

Commands

  • source ./bin/load_env.sh && bunx playwright test — run all tests headless
  • source ./bin/load_env.sh && bunx playwright test --project=regression-tests — skip auth-setup
  • bun run test / bunx playwright test --ui — interactive UI mode
  • bunx playwright test --reporter=list — verbose terminal output
  • bunx playwright test --grep '@smoke' — run tagged tests
  • bunx playwright show-trace <trace.zip> — inspect failure traces

Test IDs

getByTestId resolves to the data-test-label attribute (set via testIdAttribute in playwright.config.ts):

page.getByTestId("no-handles-available-indicator");
page.getByTestId("open-filter-section-button");

Fixtures (Auth Pattern)

The project extends Playwright's test with pre-authenticated user fixtures via storage state files in playwright-tests/.auth/.

// fixtures/authFixtures.ts
const authFiles = {
  guest: "guest_storage_state.json",
  testView: "test_view_storage_state.json",
  testNoRights: "test_no_rights_storage_state.json",
  // ... more users
};

const baseFixtures = Object.fromEntries(
  Object.entries(authFiles).map(([key, fileName]) => [
    key,
    async ({ browser }: { browser: Browser }, use: (page: Page) => Promise<void>) => {
      const storageState = path.join(__dirname, "../.auth", fileName);
      const context = await browser.newContext({ storageState });
      const page = await context.newPage();
      try {
        await use(page);
      } finally {
        await context.close();
      }
    },
  ]),
);

export const test = baseTest.extend(baseFixtures);
export const expect = test.expect;

Fixture Usage

// Tests import from authFixtures, NOT from @playwright/test
import { test, expect } from "../../fixtures/authFixtures";

test("user sees their handles", async ({ guest }) => {
  await guest.goto("/"); // `guest` is a pre-authenticated Page — no login needed
});

test("restricted user cannot access admin", async ({ testNoRights }) => {
  await testNoRights.goto("/admin");
});

File Organization

playwright-tests/
├── .auth/              # Storage state JSON files (gitignored in CI)
├── enums/              # Constants: handle names, error messages, labels
├── fixtures/           # authFixtures.ts — extended test/expect
├── pageObjects/        # POM classes (BasePage, LoginPage, ...)
│   └── components/     # Reusable: Navigation, FileUpload, FormElements
├── setup/              # auth.setup.ts, cleanup.ts
└── tests/              # Spec files grouped by feature (handle/, ping-files/, ...)

Page Objects

Pages extend BasePage (pageObjects/BasePage.ts), which composes Navigation, FilterSection, and IdleModal. Specialized pages (e.g. AppsDetailPage) add components like FileUpload and Iwa. Keep FormElements.ts under 300 lines — split by element type when it grows.

Enums & Constants

Store UI labels, error messages, and handle identifiers in playwright-tests/enums/. Never hard-code them in tests.

// enums/handles.ts
export const HandleNames = { PING_FILES: '___ping-files-en', ... };
export const HandleIds = { PING_FILES: 'qsf-handle-ping-files', ... };

// enums/errors.ts
export const Errors = { FILE_TOO_LARGE: 'produced an error while processing', ... };

// enums/elementLabels.ts
export const Buttons = { SUBMIT: 'Submit', UPLOAD: 'Upload files', ... };

Typical Test Pattern

import { test, expect } from "../../fixtures/authFixtures";
import { AppsDetailPage } from "../../pageObjects/AppsDetailPage";
import { MyAppsPage } from "../../pageObjects/MyAppsPage";
import { HandleNames } from "../../enums/handles";

test.describe("Feature Area", () => {
  test.beforeEach(async ({ guest }) => {
    const myAppsPage = new MyAppsPage(guest);
    await guest.goto("/");
    await myAppsPage.navigation.openHandle(HandleNames.PING_FILES);
  });

  test("describes expected behavior", async ({ guest }) => {
    const appsDetailPage = new AppsDetailPage(guest);
    await appsDetailPage.doSomething();
    await appsDetailPage.assertSomething(expected);
  });
});

When beforeEach navigation + upload + dashboard assertion is duplicated across describe blocks, extract a shared helper (e.g. setupDashboardForTestcase(guest, handleName, testcase)).

Environment-Aware Tests

import { isOpenAmEnv } from "../../src/utils/environment";

test.skip(isOpenAmEnv, "This test is only for Keycloak environments");

Env is loaded via source ./bin/load_env.sh; the ENVIRONMENT variable controls the target URL (default: test).

Configuration Highlights (playwright.config.ts)

export default defineConfig({
  testDir: "./playwright-tests",
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.TEST_HANDLE ? 0 : 1,
  workers: process.env.CI ? 1 : 5,
  globalTimeout: 30 * 60 * 1000,
  timeout: 60000,
  expect: { timeout: 10000 },
  use: {
    ignoreHTTPSErrors: true,
    testIdAttribute: "data-test-label",
    baseURL: envUrl,
    trace: "on-first-retry",
  },
  projects: [
    { name: "auth-setup", testMatch: "**/setup/auth.setup.ts" },
    {
      name: "regression-tests",
      testMatch: ["**/tests/*.spec.ts", "**/tests/**/*.spec.ts"],
      dependencies: process.env.CI ? ["auth-setup"] : [],
      use: { trace: "retain-on-failure", headless: true },
    },
  ],
});

QSF Checklist

  • test/expect imported from authFixtures, not @playwright/test
  • Named user fixtures (guest, testView, testNoRights) used for auth
  • Browser context closed after each fixture via context.close()
  • Handle names, errors, and labels imported from enums/
  • getByTestId values match data-test-label attributes
  • test.skip(isOpenAmEnv, ...) used for environment-specific tests
  • Env loaded via source ./bin/load_env.sh before running
  • Generic rules from the test-ui skill also satisfied

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.