Help us improve
Share bugs, ideas, or general feedback.
From shopify-commerce
Guides Shopify app testing: Vitest units, Playwright E2E/integration, Theme Check linting, Functions/webhooks/extensions, and CI/CD pipelines.
npx claudepluginhub orcaqubits/agentic-commerce-skills-plugins --plugin shopify-commerceHow this skill is triggered — by the user, by Claude, or both
Slash command
/shopify-commerce:shopify-testingThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Fetch live docs**:
Configures GitHub Actions CI/CD pipelines for Shopify apps with linting, tests, integration testing, API version checks, and Shopify CLI deployment.
Builds and debugs Shopify themes with Liquid, develops custom apps, and implements headless storefronts via Storefront API. Invoke for Shopify theme, app, or checkout customization.
Build Shopify apps, extensions, and themes using GraphQL Admin API, Shopify CLI, Polaris UI, and Liquid. Covers routing, CLI commands, access scopes, and GraphQL patterns.
Share bugs, ideas, or general feedback.
Fetch live docs:
site:shopify.dev testing apps for app testing patternssite:shopify.dev theme check for theme lintingsite:shopify.dev shopify functions testing for function testingThe Remix template uses Vitest:
// tests/routes/app._index.test.tsx
import { describe, it, expect, vi } from 'vitest';
import { loader } from '~/routes/app._index';
describe('App index loader', () => {
it('returns products', async () => {
const context = {
admin: {
graphql: vi.fn().mockResolvedValue({
json: () => ({ data: { products: { edges: [] } } }),
}),
},
};
const response = await loader({ context, request: new Request('http://test'), params: {} });
const data = await response.json();
expect(data.products).toBeDefined();
});
});
End-to-end testing with a development store:
import { test, expect } from '@playwright/test';
test('app loads in admin', async ({ page }) => {
await page.goto('https://dev-store.myshopify.com/admin/apps/my-app');
await expect(page.locator('[data-testid="app-page"]')).toBeVisible();
});
// Mock the admin GraphQL client
const mockAdmin = {
graphql: vi.fn().mockImplementation((query) => {
if (query.includes('products')) {
return Promise.resolve({
json: () => ({ data: { products: { edges: [] } } }),
});
}
}),
};
Static analysis for Liquid themes:
shopify theme check — run all checksshopify theme check --auto-correct — fix auto-fixable issuesshopify theme dev — live previewshopify app function run --input input.json
Create test input JSON files:
{
"cart": {
"lines": [
{
"id": "gid://shopify/CartLine/1",
"quantity": 2,
"merchandise": {
"__typename": "ProductVariant",
"id": "gid://shopify/ProductVariant/123"
}
}
]
}
}
import { describe, it, expect } from 'vitest';
import { run } from '../src/run';
describe('discount function', () => {
it('applies discount for VIP customers', () => {
const input = {
cart: { lines: [{ /* ... */ }] },
discountNode: { metafield: { value: '{"percentage": 10}' } },
};
const result = run(input);
expect(result.discounts).toHaveLength(1);
expect(result.discounts[0].value.percentage.value).toBe('10.0');
});
it('returns empty discounts for non-VIP', () => {
const input = { cart: { lines: [] }, discountNode: { metafield: null } };
const result = run(input);
expect(result.discounts).toHaveLength(0);
});
});
shopify app dev — sets up a tunnel and registers webhooks locallyimport { describe, it, expect } from 'vitest';
import crypto from 'crypto';
function createTestWebhook(body: object, secret: string) {
const bodyStr = JSON.stringify(body);
const hmac = crypto.createHmac('sha256', secret).update(bodyStr).digest('base64');
return { body: bodyStr, hmac };
}
describe('webhook verification', () => {
it('verifies valid HMAC', () => {
const { body, hmac } = createTestWebhook({ order: { id: 1 } }, 'test-secret');
expect(verifyWebhook(body, hmac, 'test-secret')).toBe(true);
});
it('rejects invalid HMAC', () => {
expect(verifyWebhook('{}', 'invalid', 'test-secret')).toBe(false);
});
});
name: Test Shopify App
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm run test
- run: shopify theme check (if theme)
tsc --noEmit) in CI pipelineFetch the Shopify testing documentation for exact test patterns, Theme Check configuration, and CI/CD examples before implementing.