Skip to main content
Logging in before every test is slow and fragile. A better approach: log in once, save the browser state, and reuse it across all your tests. Because Stably is 100% Playwright compatible, saving authenticated state works exactly like it does in Playwright — using storageState. No proprietary workarounds, no vendor lock-in, no jumping through hoops like you would with other no-code testing tools.
Why this is so easy with Stably: Unlike no-code testing platforms that require custom auth integrations or fragile cookie injection hacks, Stably uses standard Playwright under the hood. If it works in Playwright, it works in Stably — including storageState, setup projects, and everything else.

How It Works

Playwright’s storageState captures cookies and local storage from the browser after login. You save this to a JSON file, then tell your tests to load it — skipping the login UI entirely. The flow is simple:
  1. Run a setup step that logs in and saves the browser state to a file
  2. All other tests load that saved state and start already authenticated

In the Web Editor (Agent Sessions)

In Stably’s Web Editor, you don’t need to write any code. Just tell the AI what you want.

Save authenticated state after login

When creating or editing a test in the Web Editor, simply prompt the AI agent:
“Log in with the test account credentials, then save the authenticated state to playwright/.auth/user.json
The AI agent will generate the appropriate Playwright storageState call for you.

Reuse saved state in other tests

For subsequent tests that need to be authenticated, prompt the AI:
“Use the saved auth state from playwright/.auth/user.json so I don’t have to log in again”
The agent will add the correct test.use({ storageState: ... }) configuration.
This is just standard Playwright — the AI agent knows how to use storageState because Stably is fully Playwright compatible. No special Stably-specific auth setup required.

In the CLI

The same approach works in the Stably CLI. Just describe what you need in your prompt.

Interactive mode

stably
Then ask:
“Create an auth setup that logs into my app at https://myapp.com/login with the test credentials, and saves the storage state for reuse”
The agent will generate a Playwright setup project with storageState.

One-shot mode

stably create "Create an auth setup project that logs in and saves storageState to playwright/.auth/user.json, then create a test for the dashboard that reuses the saved auth"

What the Generated Code Looks Like

For reference, here’s what the AI agent generates under the hood. This is standard Playwright code — nothing proprietary.

Auth setup (runs once)

auth.setup.ts
import { test as setup, expect } from '@stablyai/playwright-test';

setup('authenticate', async ({ page }) => {
  // Go to login page
  await page.goto('https://myapp.com/login');

  // Fill in credentials
  await page.getByLabel('Email').fill(process.env.TEST_EMAIL!);
  await page.getByLabel('Password').fill(process.env.TEST_PASSWORD!);
  await page.getByRole('button', { name: 'Sign in' }).click();

  // Wait for login to complete
  await expect(page).toHaveURL('/dashboard');

  // Save the authenticated state
  await page.context().storageState({ path: 'playwright/.auth/user.json' });
});

Tests that reuse the state

dashboard.spec.ts
import { test, expect } from '@stablyai/playwright-test';

// Load the saved auth state — no login needed
test.use({ storageState: 'playwright/.auth/user.json' });

test('view dashboard', async ({ page }) => {
  await page.goto('https://myapp.com/dashboard');
  await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});

Playwright config with setup project

playwright.config.ts
import { defineConfig } from '@stablyai/playwright-test';

export default defineConfig({
  projects: [
    // Setup project runs first and saves auth state
    { name: 'setup', testMatch: /.*\.setup\.ts/ },

    // All tests depend on setup and use the saved state
    {
      name: 'tests',
      dependencies: ['setup'],
      use: {
        storageState: 'playwright/.auth/user.json',
      },
    },
  ],
});

Multiple Accounts

Need different roles (admin, regular user, viewer)? Save separate state files:
// admin.setup.ts
await page.context().storageState({ path: 'playwright/.auth/admin.json' });

// user.setup.ts
await page.context().storageState({ path: 'playwright/.auth/user.json' });
Then use the right state per test:
// Admin tests
test.describe('admin panel', () => {
  test.use({ storageState: 'playwright/.auth/admin.json' });

  test('manage users', async ({ page }) => {
    // Already logged in as admin
  });
});

// Regular user tests
test.describe('user dashboard', () => {
  test.use({ storageState: 'playwright/.auth/user.json' });

  test('view profile', async ({ page }) => {
    // Already logged in as regular user
  });
});
In the Web Editor or CLI, just tell the agent:
“Set up auth for two roles: an admin and a regular user. Save each to separate state files and create tests that use the correct role.”

Tips

The saved state files contain session tokens. Don’t commit them:
.gitignore
playwright/.auth/
Use Stably Environments to store test credentials as secret variables rather than hardcoding them. In the CLI, pass them via environment variables.
If your auth tokens expire quickly, the setup project runs fresh on each npx playwright test invocation — so state is always current. For long-lived CI runs, consider adding a TTL check or forcing a fresh login.
If your app uses Google login, combine storageState with Stably’s authWithGoogle helper to save authenticated Google sessions.

Why This Is Easier Than Other Tools

StablyTypical no-code tools
Auth mechanismStandard Playwright storageStateProprietary cookie injection or replay
SetupTell the AI agent in plain EnglishConfigure through vendor-specific UI
Multiple rolesSeparate state files, standard PlaywrightOften requires per-role configuration in dashboard
PortabilityPure Playwright — works anywhereLocked to the vendor’s runtime
DebuggingRead the generated .json state fileBlack box
Because Stably is built on Playwright, you get the full power of Playwright’s auth handling with none of the vendor lock-in. Your auth setup is just code — portable, version-controlled, and debuggable.