Install
$ agentstack add skill-seed-forge-harness-ai-kit-devlab-integration-fullstack ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Full Stack Integration Testing Expert Skill
专注前后端混合架构的端到端业务流程验证能力。
覆盖微服务联动、消息队列集成、分布式事务补偿等复杂场景。
触发条件
当用户提到以下关键词时触发此 Skill:
- "全栈集成测试" / "full stack integration test"
- "微服务端到端流程" / "microservice end-to-end workflow"
- "跨服务数据流" / "cross-service data flow"
- "事件驱动架构测试" / "event-driven architecture testing"
- "分布式事务验证" / "distributed transaction validation"
技术栈依赖
核心 CLI
# E2E Testing
npm install -D @playwright/test
# Backend Testing
npm install -D jest supertest
# Infrastructure (Testcontainers)
npm install -D @testcontainers/postgresql @testcontainers/redis
AI Agent 初始化
npx playwright init-agents --loop=claude
功能范围
Phase 1: 跨服务业务流程映射
输入:
- 系统架构图(C4 模型或类似)
- API 契约文档
- 业务流程描述(User Journey)
输出:
specs/workflows/*.md— 业务流程规格specs/data-flow.md— 数据流图谱specs/error-handling.md— 异常处理场景
Step 1.1: 服务拓扑分析
// services/service-graph-analyzer.ts
interface Service {
id: string;
name: string;
type: 'api' | 'worker' | 'scheduler';
endpoints?: Endpoint[];
}
interface Dependency {
from: string;
to: string;
protocol: 'http' | 'grpc' | 'message';
pattern: 'sync' | 'async' | 'saga';
}
class ServiceGraphAnalyzer {
analyze(configs: any[]): { services: Service[], dependencies: Dependency[] } {
const services = config.map(c => ({
id: c.name,
name: c.displayName,
type: this.determineType(c),
endpoints: this.extractEndpoints(c)
}));
const dependencies = this.extractDependencies(services, configs);
return { services, dependencies };
}
extractDependencies(services: Service[], configs: any[]): Dependency[] {
const deps: Dependency[] = [];
configs.forEach(config => {
// HTTP dependencies
if (config.services?.forEach((target: string) => {
deps.push({
from: config.name,
to: target,
protocol: 'http',
pattern: 'sync'
});
}));
// Message queue dependencies
if (config.topics?.length > 0) {
config.topics.forEach(topic => {
deps.push({
from: config.name,
to: topic,
protocol: 'message',
pattern: 'async'
});
});
}
});
return deps;
}
}
Step 1.2: 业务流程规格生成
# specs/workflows/order-processing.md
## Feature: Order Processing Workflow
### User Story
As a customer, I want to place an order so that I can purchase products.
### System Components Involved
| Component | Role | Type |
|-----------|------|------|
| frontend-app | UI layer | api |
| auth-service | User authentication | api |
| cart-service | Shopping cart management | api |
| inventory-service | Stock verification & reservation | api |
| payment-service | Payment processing | api |
| order-service | Order creation & tracking | api |
| email-worker | Confirmation emails | worker |
| kafka-events | Event bus | message |
### Success Flow
1. **User adds item to cart**
```
frontend -> cart-service: POST /cart/items
cart-service -> auth-service: GET /users/{id}
cart-service returns: Cart with item
```
2. **Checkout initiation**
```
frontend -> cart-service: POST /cart/checkout
cart-service -> inventory-service: POST /verify-stock
inventory-service confirms: Stock available
```
3. **Payment processing**
```
frontend -> payment-service: POST /payments
payment-service -> order-service: POST /orders (create pending)
payment-service processes card: External gateway
payment-service -> order-service: PUT /orders/{id}/confirm
```
4. **Inventory reservation**
```
inventory-service -> kafka: PUBLISH "order.created"
email-worker consumes: "order.confirmed"
```
5. **Confirmation**
```
email-worker sends email
frontend shows success page
```
### Error Handling Scenarios
| Error | Source | Recovery | Expected Outcome |
|-------|--------|----------|------------------|
| Insufficient stock | inventory-service | Cancel order, refund deposit | Order cancelled |
| Payment failed | payment-service | Allow retry or cancel | Retry allowed |
| Auth token expired | auth-service | Force re-login | Session restored |
### Data Contracts
**Order Creation Request:**
```json
{
"cartId": "uuid",
"shippingAddress": {...},
"paymentMethod": {
"type": "card",
"token": "tok_xxx"
},
"promoCode": "SAVE10" // optional
}
Order Confirmation Response:
{
"orderId": "uuid",
"status": "confirmed",
"totalAmount": 129.99,
"estimatedDelivery": "2026-07-25T10:00:00Z",
"trackingNumber": "TRK123456789"
}
---
### Phase 2: 端到端测试代码生成
**输入**:
- `specs/workflows/*.md` 业务规格
- Seed 数据模板
**输出**:
- `tests/e2e/workflows/*.spec.ts`
- `tests/integration/cross-service/*.spec.ts`
- `tests/fixtures/setup.ts`
#### Step 2.1: 全局环境配置
```typescript
// tests/global-setup.ts
import { test as setup } from '@playwright/test';
import { TestContainers } from 'testcontainers';
setup('prepare global fixtures', async () => {
// Start containers once per suite
await TestContainers.start();
// Setup database schema
await setupDatabase();
// Seed initial data
await seedTestData();
});
setup.afterAll(async () => {
// Cleanup containers
await TestContainers.stop();
});
Step 2.2: Mock Server 配置
// tests/mocks/api-helpers.ts
import { setupServer } from 'msw/node';
import { rest } from 'msw';
export function createExternalAPIMocks() {
return setupServer(
// Mock payment gateway
rest.post('https://api.stripe.com/v1/charges', async (req, res, ctx) => {
const body = await req.json();
// Simulate random payment failures (5%)
if (Math.random() {
return res(
ctx.status(201),
ctx.json({ sid: 'SM' + Math.random().toString(36).substr(2, 9) })
);
})
);
}
// In test file
import { createExternalAPIMocks } from '../mocks/api-helpers';
const externalMocks = createExternalAPIMocks();
beforeAll(() => externalMocks.listen());
afterEach(() => externalMocks.resetHandlers());
afterAll(() => externalMocks.close());
Step 2.3: 跨服务工作流程测试
// tests/e2e/workflows/order-processing.spec.ts
import { test, expect } from '../../fixtures';
test.describe('Order Processing E2E', () => {
let userId: string;
let cartId: string;
let productId: string;
test.beforeEach(async ({ apiClient }) => {
// Pre-seed test data
userId = await apiClient.createUser();
productId = await apiClient.createProduct({ price: 29.99 });
await apiClient.addItemToCart(userId, productId, 2);
});
test('complete order checkout flow with all validations', async ({
page,
apiClient,
mockServer
}) => {
// === STEP 1: Navigate to checkout ===
await page.goto('/cart');
await expect(page.getByText('Your Cart')).toBeVisible();
// Verify cart total calculated correctly
const cartTotal = await page.getByTestId('cart-total').textContent();
expect(cartTotal).toBe('$59.98'); // 2 * $29.99
// Click checkout button
await page.getByRole('button', { name: /checkout/i }).click();
// === STEP 2: Shipping information ===
await expect(page.getByText('Shipping Information')).toBeVisible();
// Fill shipping form
await page.getByLabel('Email').fill('customer@example.com');
await page.getByLabel('Address').fill('123 Main St');
await page.getByLabel('City').fill('New York');
await page.getByLabel('Zip Code').fill('10001');
// Validate required fields
await page.getByRole('button', { name: /continue/i }).click();
await expect(page.getByText('Email is required')).not.toBeVisible();
// Continue to payment
await page.getByRole('button', { name: /continue to payment/i }).click();
// === STEP 3: Payment processing ===
await expect(page.getByText('Payment')).toBeVisible();
// Fill credit card info
await page.getByLabel('Card Number').fill('4111111111111111');
await page.getByLabel('Expiry Date').fill('12/25');
await page.getByLabel('CVV').fill('123');
// Apply promo code (if available)
const promoResponse = page.waitForResponse(resp =>
resp.url().includes('/api/promo') && resp.status() === 200
);
await page.getByLabel('Promo Code').fill('SAVE10');
await page.getByRole('button', { name: /apply/i }).click();
await promoResponse;
// Verify discount applied
const discountElement = await page.getByText(/10% off/i);
expect(discountElement).toBeVisible();
// Place order
await page.getByRole('button', { name: /place order/i }).click();
// === STEP 4: Confirm order ===
await page.waitForLoadState('networkidle');
// Wait for order confirmation modal
await expect(page.getByText('Order Confirmed')).toBeVisible();
// Capture order ID
const orderId = await page.getByTestId('order-id').textContent();
expect(orderId).toBeDefined();
// === VERIFICATIONS ===
// 1. Order created in database
const order = await apiClient.getOrder(orderId!);
expect(order.status).toBe('confirmed');
expect(order.total).toBeLessThan(100); // Discount applied
// 2. Inventory reserved
const inventory = await apiClient.getInventory(productId);
expect(inventory.reserved).toBeGreaterThanOrEqual(2);
// 3. Email sent
const emailEvents = await mockServer.captureEmails();
expect(emailEvents).toContainEqual(expect.objectContaining({
orderId: orderId!,
template: 'order-confirmation'
}));
// 4. SMS notification sent (optional)
const smsEvents = await mockServer.captureSMS();
// expect(smsEvents.length).toBeGreaterThan(0); // Can be disabled
// 5. Kafka events published
const kafkaEvents = await mockServer.consumeTopic('events.order-placed');
expect(kafkaEvents[0].value.orderId).toBe(orderId!);
// 6. Analytics event tracked
const analyticsEvents = await page.evaluate(() => window.__ANALYTICS__);
expect(analyticsEvents[0].eventName).toBe('order_completed');
});
test('handle insufficient stock gracefully', async ({ page, apiClient }) => {
// Create product with limited stock
const lowStockProduct = await apiClient.createProduct({
price: 99.99,
stock: 1 // Only 1 in stock
});
await apiClient.addItemToCart(userId, lowStockProduct.id, 2); // Try to buy 2
await page.goto('/cart');
// Should show warning about quantity limit
await expect(page.getByText(/only 1 available/i)).toBeVisible();
// Cannot proceed with checkout for 2 items
await expect(page.getByRole('button', { name: /checkout/i })).toBeDisabled();
});
test('handle payment failure and allow retry', async ({
page,
mockServer
}) => {
// Configure payment gateway to fail
mockServer.interceptPaymentFailure();
await page.goto('/cart');
await page.getByRole('button', { name: /checkout/i }).click();
// Fill payment details
await page.getByLabel('Card Number').fill('4111111111111111');
await page.getByLabel('Expiry Date').fill('12/25');
await page.getByLabel('CVV').fill('123');
// Place order (will fail)
await page.getByRole('button', { name: /place order/i }).click();
// Should show error message but not destroy order draft
await expect(page.getByText(/payment failed/i)).toBeVisible();
await expect(page.getByText(/try again/i)).toBeVisible();
// Update payment method
await page.getByLabel('Card Number').fill('4242424242424242');
await page.getByRole('button', { name: /retry payment/i }).click();
// Second attempt should succeed
await expect(page.getByText(/order confirmed/i)).toBeVisible();
});
test('rollback on inventory timeout', async ({ page, apiClient }) => {
// Simulate slow inventory service
mockServer.delayRequest('inventory-service', 10000);
await page.goto('/cart');
await page.getByRole('button', { name: /checkout/i }).click();
// Should show timeout error
await expect(page.getByText(/server unavailable/i)).toBeVisible();
// No partial orders should exist
const pendingOrders = await apiClient.getPendingOrders(userId);
expect(pendingOrders).toHaveLength(0);
// Cart should still be intact
await page.goto('/cart');
await expect(page.getByText('Your Cart')).toBeVisible();
});
});
Phase 3: 分布式事务验证
Step 3.1: Saga Pattern 测试
// tests/integration/distributed-transactions.spec.ts
import { test, expect } from '../fixtures';
test.describe('Saga Pattern Validation', () => {
test('compensating transaction when payment fails', async ({
apiClient,
eventStore
}) {
// Arrange: Initiate order
const order = await apiClient.createOrder({
items: [{ productId: 'SKU-123', quantity: 1 }],
status: 'pending_payment'
});
// Reserve inventory (committed)
const reservation = await apiClient.reserveInventory(
order.items[0].productId,
order.items[0].quantity
);
// Act: Payment fails, triggers compensation
await expect(apiClient.processPayment(order.id)).rejects.toThrow('PaymentDeclined');
// Assert: Compensation should release inventory
const newStock = await apiClient.getStock(order.items[0].productId);
expect(newStock.available).toBeGreaterThan(reservation.initialStock - reservation.quantity);
// Order status should be cancelled
const updatedOrder = await apiClient.getOrder(order.id);
expect(updatedOrder.status).toBe('cancelled');
// Events chain:
const events = await eventStore.getEventChain(order.id);
expect(events).toEqual([
{ type: 'ORDER_CREATED', payload: {...order} },
{ type: 'INVENTORY_RESERVED', payload: {...reservation} },
{ type: 'PAYMENT_FAILED', payload: {...error} },
{ type: 'INVENTORY_RELEASED', payload: {...compensation} } // Compensating transaction
]);
});
test('eventual consistency after eventual updates', async ({
apiClient,
waitForEvent
}) {
// Create order
const order = await apiClient.createOrder({ ... });
// Verify immediate consistency
expect(await apiClient.getOrder(order.id)).toBeDefined();
// Wait for eventual consistency (email notification)
await waitForEvent('ORDER_CONFIRMED', { timeout: 5000 });
// Email should be sent
const emails = await apiClient.getEmailsFor(order.userId);
expect(emails).toContainEqual(expect.objectContaining({
subject: expect.stringContaining('Order Confirmed')
}));
// Analytics should be updated
const analytics = await apiClient.getAnalytics('sales');
expect(analytics.recentOrders).toContain(order.id);
});
});
Step 3.2: Two-Phase Commit 模式测试
// tests/integration/two-phase-commit.spec.ts
test('two-phase commit with rollback on validation failure', async ({
dbTransaction
}) => {
// Begin transaction
const tx = await dbTransaction.begin();
try {
// Phase 1: Prepare
await tx.prepare('UPDATE accounts SET balance = balance - 100 WHERE id = ?');
await tx.prepare('UPDATE accounts SET balance = balance + 100 WHERE id = ?');
// All prepare statements succeed
const prepareStatus = await tx.commitPrepare();
expect(prepareStatus.allCommitted).toBe(true);
// Phase 2: Commit
await tx.commit();
// Verify final state
const account1 = await dbTransaction.getBalance('ACC-001');
const account2 = await dbTransaction.getBalance('ACC-002');
expect(account1.balance).toBe(originalBalance - 100);
expect(account2.balance).toBe(originalBalance + 100);
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [seed-forge](https://github.com/seed-forge)
- **Source:** [seed-forge/harness-ai-kit](https://github.com/seed-forge/harness-ai-kit)
- **License:** Apache-2.0
- **Homepage:** https://pypi.org/project/harness-ai-kit/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.