Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/release-auth.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: release-auth

on:
push:
tags:
- "@playwright-kit/auth@*"

permissions:
contents: write

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
registry-url: "https://registry.npmjs.org"

- name: Install dependencies
run: npm ci

- name: Verify tag matches package version
shell: bash
run: |
TAG="${GITHUB_REF_NAME}"
VERSION="$(node -p "require('./packages/auth/package.json').version")"
EXPECTED="@playwright-kit/auth@${VERSION}"
if [ "${TAG}" != "${EXPECTED}" ]; then
echo "Tag mismatch: got '${TAG}', expected '${EXPECTED}'"
exit 1
fi

- name: Publish to npm
run: npm -w packages/auth publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true

7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ This repo is a small monorepo of production-ready utilities built on top of Play
- npm: `https://www.npmjs.com/package/@playwright-kit/auth`
- Examples: `examples/next-admin-auth`, `examples/vite-react-auth`

## Releasing

See `RELEASING.md`.

## Auth (@playwright-kit/auth)

Infrastructure utilities for managing Playwright `storageState` auth artifacts *before* running tests.
Expand Down Expand Up @@ -224,7 +228,8 @@ Or:
playwright-kit auth ensure --dotenv-path .env.ci
```

This requires `dotenv` to be installed in your project (`npm i -D dotenv`).
Notes:
- `.env` loading is provided via the `dotenv` package.

### Using in tests

Expand Down
36 changes: 36 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Releasing

This repo is a monorepo. The root package is private; only packages under `packages/*` are published.

### One-time GitHub setup

1) Create an npm automation token that can publish `@playwright-kit/*`.
2) Add it to the GitHub repo secrets as `NPM_TOKEN`.

### Release `@playwright-kit/auth`

1) Update `packages/auth/CHANGELOG.md` (optional but recommended).
2) Bump the version in `packages/auth/package.json` (and commit it):

```bash
cd packages/auth
npm version patch --no-git-tag-version
cd ../..
git add packages/auth/package.json packages/auth/CHANGELOG.md
git commit -m "release(auth): v$(node -p \"require('./packages/auth/package.json').version\")"
```

3) Create and push a tag in the format `@playwright-kit/auth@<version>`:

```bash
git tag "@playwright-kit/auth@$(node -p \"require('./packages/auth/package.json').version\")"
git push origin main
git push origin --tags
```

That tag triggers the GitHub Action that:
- runs `npm ci`
- verifies the tag matches `packages/auth/package.json#version`
- publishes `@playwright-kit/auth` to npm
- creates a GitHub Release for the tag

8 changes: 8 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
pre-commit:
parallel: true
commands:
lint:
run: npm run lint
typecheck:
run: npm run typecheck

pre-push:
commands:
check:
run: npm run check
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions packages/auth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 0.2.0

- Breaking: removed `baseTest` / `baseExpect` options from `authTest()` and `createAuthTest()` to keep types strictly aligned with Playwright’s default `test`.
- CLI: removed `--fail-fast` (undocumented) to keep `ensure` behavior consistent and deterministic across multiple profiles.

## 0.1.0

- CLI: `playwright-kit auth setup/ensure` with failure artifacts and optional `webServer` + `dotenv`.
Expand Down
3 changes: 2 additions & 1 deletion packages/auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ Or:
playwright-kit auth ensure --dotenv-path .env.ci
```

This requires `dotenv` to be installed in your project (`npm i -D dotenv`).
Notes:
- `.env` loading is provided via the `dotenv` package.

## Using in tests

Expand Down
2 changes: 1 addition & 1 deletion packages/auth/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@playwright-kit/auth",
"version": "0.1.2",
"version": "0.2.0",
"description": "Small, production-ready authentication utilities for Playwright.",
"license": "MIT",
"sideEffects": false,
Expand Down
1 change: 0 additions & 1 deletion packages/auth/src/__tests__/argParsing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ test("parseArgs: ensure supports repeated --profile", () => {
kind: "ensure",
profiles: ["a", "b"],
configPath: undefined,
failFast: false,
headed: false,
browser: undefined,
webServer: undefined,
Expand Down
7 changes: 0 additions & 7 deletions packages/auth/src/cli/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export type ParsedArgs =
kind: "ensure";
profiles?: string[];
configPath?: string;
failFast: boolean;
headed: boolean;
browser?: BrowserName;
webServer?: WebServerArgs;
Expand Down Expand Up @@ -290,7 +289,6 @@ export function parseArgs(argv: string[]): ParsedArgs {
if (command === "ensure") {
const profiles: string[] = [];
let configPath: string | undefined;
let failFast = false;
let headed = false;
let browser: BrowserName | undefined;
const webServer = parseWebServerArgs(rest);
Expand Down Expand Up @@ -322,10 +320,6 @@ export function parseArgs(argv: string[]): ParsedArgs {
i++;
continue;
}
if (arg === "--fail-fast") {
failFast = true;
continue;
}
if (arg === "--headed") {
headed = true;
continue;
Expand Down Expand Up @@ -377,7 +371,6 @@ export function parseArgs(argv: string[]): ParsedArgs {
kind: "ensure",
profiles: profiles.length > 0 ? profiles : undefined,
configPath,
failFast,
headed,
browser,
webServer,
Expand Down
2 changes: 0 additions & 2 deletions packages/auth/src/cli/commands/authEnsure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export async function authEnsure(options: {
loaded: AuthConfigLoadResult;
profileNames?: string[];
headed: boolean;
failFast: boolean;
browserName?: "chromium" | "firefox" | "webkit";
env: NodeJS.ProcessEnv;
onLog?: (line: string) => void;
Expand Down Expand Up @@ -80,7 +79,6 @@ export async function authEnsure(options: {
const message = error instanceof Error ? error.message : String(error);
log(`auth ensure: "${profileName}" failed: ${message}`);
failures.push({ profile: profileName, error });
if (options.failFast) break;
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/auth/src/cli/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ playwright-kit auth

Usage:
playwright-kit auth setup --profile <name> [--config <path>] [--headed] [--browser <chromium|firefox|webkit>]
playwright-kit auth ensure [--profile <name> ...] [--config <path>] [--fail-fast] [--headed] [--browser <chromium|firefox|webkit>]
playwright-kit auth ensure [--profile <name> ...] [--config <path>] [--headed] [--browser <chromium|firefox|webkit>]

Env (optional):
--dotenv Load .env from current working directory (requires "dotenv").
--dotenv-path <path> Load env from a specific file path (requires "dotenv").
--dotenv Load .env from current working directory.
--dotenv-path <path> Load env from a specific file path.

Web server (optional):
--web-server-command <cmd> Command to start your app/server (quote if it contains spaces).
Expand Down
1 change: 0 additions & 1 deletion packages/auth/src/cli/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ async function run(argv: string[]): Promise<number> {
loaded,
profileNames: parsed.profiles,
headed: parsed.headed,
failFast: parsed.failFast,
browserName: parsed.browser,
env: process.env,
}),
Expand Down
18 changes: 2 additions & 16 deletions packages/auth/src/fixtures/createAuthTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ type BaseTestArgs = PlaywrightTestArgs & PlaywrightTestOptions;
type BaseWorkerArgs = PlaywrightWorkerArgs & PlaywrightWorkerOptions;
type StorageStateOption = PlaywrightTestOptions["storageState"];

type DefaultBaseTest = typeof playwrightTest;
type DefaultExpect = typeof playwrightExpect;

type AuthFixtures = {
Expand Down Expand Up @@ -66,20 +65,15 @@ export interface AuthTestOptions {
/** Alias for statesDir (kept for ergonomics). */
stateDir?: string;
defaultProfile: string;
baseTest?: DefaultBaseTest;
baseExpect?: DefaultExpect;
}

export function authTest(options: AuthTestOptions): AuthTestWithExpect {
const baseTest = options.baseTest ?? playwrightTest;
const expect = options.baseExpect ?? playwrightExpect;

const statesDir = options.statesDir ?? options.stateDir ?? ".auth";
const defaultProfile = options.defaultProfile;

const authOption: [string, { option: true }] = [defaultProfile, { option: true }];

const testBase = baseTest.extend<AuthFixtures>({
const testBase = playwrightTest.extend<AuthFixtures>({
auth: authOption,
_authStatePath: async ({ auth }, use) => {
if (!auth) {
Expand Down Expand Up @@ -123,23 +117,18 @@ export function authTest(options: AuthTestOptions): AuthTestWithExpect {
derived(title, fn);
};

return Object.assign(testBase, { withAuth, auth, expect });
return Object.assign(testBase, { withAuth, auth, expect: playwrightExpect });
}

export interface CreateAuthTestOptions {
statesDir?: string;
defaultProfile?: string;
baseTest?: DefaultBaseTest;
baseExpect?: DefaultExpect;
}

export function createAuthTest(options: CreateAuthTestOptions = {}): {
test: AuthTest;
expect: DefaultExpect;
} {
const baseTest = options.baseTest ?? playwrightTest;
const baseExpect = options.baseExpect ?? playwrightExpect;

const defaultProfile = options.defaultProfile;
if (!defaultProfile) {
throw new Error(
Expand All @@ -150,10 +139,7 @@ export function createAuthTest(options: CreateAuthTestOptions = {}): {
const test = authTest({
defaultProfile,
statesDir: options.statesDir,
baseTest,
baseExpect,
});

return { test, expect: test.expect };
}

20 changes: 20 additions & 0 deletions packages/auth/type-tests/authTest-use-options-type.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { PlaywrightTestOptions } from "@playwright/test";

import { authTest } from "../src/fixtures/createAuthTest";

const test = authTest({ defaultProfile: "user" });

test.use({ auth: "admin" });

const storageState: PlaywrightTestOptions["storageState"] = {
cookies: [],
origins: [],
};
test.use({ storageState });

test("options keep Playwright types", async ({ page, baseURL, storageState: state }) => {
void page;
void baseURL;
void state;
});

Loading