Testing Utilities
The @memberstack/dom/testing subpath provides mock factories, a mock SDK instance, and custom test matchers for unit testing your Memberstack integration. No API calls needed.
Works with Jest & Vitest
All testing utilities work with both Jest and Vitest. The custom matchers extend the expect API in both frameworks.
Import
Testing utilities are available from the @memberstack/dom/testing subpath. No additional packages to install.
import {
createMockMemberstack,
mockMember,
mockPlan,
mockPlanConnection,
mockCard,
mockPrice,
mockApp,
mockContentGroup,
memberstackMatchers
} from '@memberstack/dom/testing';Mock Factories
Mock factories create realistic test data with sensible defaults. Pass an overrides object to customize any fields.
mockMember(overrides?)
Creates a mock Member object with all fields populated.
import { mockMember } from '@memberstack/dom/testing';
// Default member
const member = mockMember();
// {
// id: "mem_abc123xyz",
// verified: true,
// profileImage: "",
// auth: { email: "test@example.com", hasPassword: true, providers: [] },
// loginRedirect: "/",
// stripeCustomerId: "",
// createdAt: "2025-01-01T00:00:00.000Z", // dynamic: new Date().toISOString()
// metaData: {},
// customFields: {},
// permissions: [],
// planConnections: []
// }
// With overrides
const verifiedMember = mockMember({
verified: true,
auth: { email: 'pro@example.com', hasPassword: true, providers: [] },
customFields: { 'first-name': 'Jane' }
});mockPlan(overrides?)
Creates a mock Plan object.
import { mockPlan } from '@memberstack/dom/testing';
const plan = mockPlan();
// { id: "pln_abc123", name: "Test Plan", description: "A test plan", status: "PUBLISHED",
// redirects: { afterLogin: "/", afterLogout: "/", afterSignup: "/" }, prices: [] }
const proPlan = mockPlan({
name: 'Pro',
prices: [mockPrice({ amount: 29, name: 'Monthly' })]
});mockPlanConnection(overrides?)
Creates a mock PlanConnection representing a member's subscription to a plan.
import { mockPlanConnection } from '@memberstack/dom/testing';
const connection = mockPlanConnection();
// {
// id: "conn_abc123",
// active: true,
// status: "ACTIVE",
// planId: "pln_abc123",
// type: "FREE",
// payment: null
// }
// Member with an active plan
const memberWithPlan = mockMember({
planConnections: [
mockPlanConnection({ planId: 'pln_pro-plan' })
]
});Other Factories
import { mockPrice, mockCard, mockApp, mockContentGroup } from '@memberstack/dom/testing';
// Mock a price tier
const price = mockPrice({ amount: 49, name: 'Annual', interval: { type: 'YEARLY', count: 1 } });
// Mock a saved card
const card = mockCard({ brand: 'visa', last4: '4242' });
// Mock app configuration
const app = mockApp({ name: 'My App', mode: 'sandbox' });
// Mock a content group (gated content)
const group = mockContentGroup({ name: 'Premium Content', key: 'premium' });createMockMemberstack(options?)
Creates a complete mock Memberstack SDK instance that behaves like the real thing but runs entirely in memory. All methods return promises and update internal state correctly.
import { createMockMemberstack, mockMember, mockPlan } from '@memberstack/dom/testing';
const mockMs = createMockMemberstack({
// Pre-set a logged-in member
member: mockMember({
auth: { email: 'test@example.com', hasPassword: true, providers: [] }
}),
// Available plans
plans: [
mockPlan({ id: 'pln_free', name: 'Free' }),
mockPlan({ id: 'pln_pro', name: 'Pro' })
]
});
// Use it like the real SDK
const { data } = await mockMs.getCurrentMember();
console.log(data.auth.email); // "test@example.com"
// Login/logout update internal state
await mockMs.logout();
const { data: afterLogout } = await mockMs.getCurrentMember();
console.log(afterLogout); // null
await mockMs.loginMemberEmailPassword({
email: 'test@example.com',
password: 'any-password'
});
const { data: afterLogin } = await mockMs.getCurrentMember();
console.log(afterLogin.auth.email); // "test@example.com"Available Mock Methods
The mock instance supports these methods:
| Method | Behavior |
|---|---|
getCurrentMember() | Returns the current mock member or null |
loginMemberEmailPassword() | Sets the mock member as logged in |
signupMemberEmailPassword() | Creates and sets a mock member |
logout() | Clears the current member |
updateMember() | Updates custom fields on the mock member |
getPlans() | Returns the configured mock plans |
getPlan() | Returns a specific plan by ID |
getApp() | Returns the mock app configuration |
getRestrictedUrlGroups() | Returns mock content groups |
onAuthChange(callback) | Subscribes to auth state changes |
Test Helpers
The mock instance also includes test-only helpers for manipulating state directly:
// Directly set the current member (without triggering login flow)
mockMs._setMember(mockMember({ verified: true }));
// Inspect the internal mock state
const state = mockMs._getMockState();
console.log(state.member); // Current member
console.log(state.plans); // Available plansCustom Test Matchers
Extend Jest or Vitest with Memberstack-specific assertions for cleaner, more readable tests.
import { memberstackMatchers, mockMember, mockPlanConnection } from '@memberstack/dom/testing';
// Register matchers (do this once, e.g., in a setup file)
expect.extend(memberstackMatchers);
// toBeLoggedIn() - asserts member is not null
const member = mockMember();
expect(member).toBeLoggedIn();
expect(null).not.toBeLoggedIn();
// toHavePlan(planId) - asserts member has a specific plan
const memberWithPlan = mockMember({
planConnections: [mockPlanConnection({ planId: 'pln_pro' })]
});
expect(memberWithPlan).toHavePlan('pln_pro');
expect(memberWithPlan).not.toHavePlan('pln_enterprise');
// toBeVerified() - asserts member's email is verified
const verifiedMember = mockMember({ verified: true });
expect(verifiedMember).toBeVerified();vitest.setup.ts or jest.setup.js) so they're available in all tests.Full Test Example
Here's a complete example testing a component that uses Memberstack for authentication and plan checking.
// auth.test.ts
import { describe, it, expect, beforeEach } from 'vitest';
import {
createMockMemberstack,
mockMember,
mockPlan,
mockPlanConnection,
memberstackMatchers
} from '@memberstack/dom/testing';
expect.extend(memberstackMatchers);
describe('Authentication Flow', () => {
let mockMs;
beforeEach(() => {
mockMs = createMockMemberstack({
plans: [
mockPlan({ id: 'pln_free', name: 'Free' }),
mockPlan({ id: 'pln_pro', name: 'Pro' })
]
});
});
it('should start logged out', async () => {
const { data } = await mockMs.getCurrentMember();
expect(data).not.toBeLoggedIn();
});
it('should login and return member', async () => {
mockMs._setMember(mockMember({
auth: { email: 'user@test.com', hasPassword: true, providers: [] }
}));
const { data } = await mockMs.getCurrentMember();
expect(data).toBeLoggedIn();
expect(data.auth.email).toBe('user@test.com');
});
it('should check plan access', async () => {
const member = mockMember({
planConnections: [
mockPlanConnection({ planId: 'pln_pro', status: 'ACTIVE' })
]
});
mockMs._setMember(member);
const { data } = await mockMs.getCurrentMember();
expect(data).toHavePlan('pln_pro');
expect(data).not.toHavePlan('pln_enterprise');
});
it('should logout and clear member', async () => {
mockMs._setMember(mockMember());
await mockMs.logout();
const { data } = await mockMs.getCurrentMember();
expect(data).not.toBeLoggedIn();
});
it('should list available plans', async () => {
const { data } = await mockMs.getPlans();
expect(data).toHaveLength(2);
expect(data[0].name).toBe('Free');
expect(data[1].name).toBe('Pro');
});
});Using with Dependency Injection
For the mock to work with your app code, pass the Memberstack instance as a dependency rather than importing it directly. Here's a pattern that works with most frameworks.
// memberstack.ts - your app's Memberstack wrapper
let instance = null;
export function setMemberstack(ms) {
instance = ms;
}
export function getMemberstack() {
return instance;
}
// main.ts - production code
import memberstack from '@memberstack/dom';
import { setMemberstack } from './memberstack';
const ms = await memberstack.init({ publicKey: 'pk_...' });
setMemberstack(ms);
// test.ts - test code
import { createMockMemberstack } from '@memberstack/dom/testing';
import { setMemberstack } from './memberstack';
beforeEach(() => {
setMemberstack(createMockMemberstack({ /* options */ }));
});