xiaohongshu
xiaohongshu
gate-4b-integration-tests
Gate 4b validation: Integration test creation and no-hardcoded-values enforcement
Full skill instructions
Purpose: Validate integration test quality, test data management, and credential handling
STOP AND CHECK:
# 1. Integration test files exist
if ! ls test/integration/*Test.ts 2>/dev/null | head -1 > /dev/null; then
echo "❌ Gate 4b FAILED: No integration test files found"
echo " Create test/integration/{Resource}ProducerTest.ts"
echo " See integration-test-patterns skill"
exit 1
fi
TEST_FILE_COUNT=$(ls test/integration/*Test.ts 2>/dev/null | wc -l)
echo "✅ Found $TEST_FILE_COUNT integration test file(s)"
# 2. Test suites exist with proper structure
DESCRIBE_COUNT=$(grep -h "^describe(" test/integration/*.ts 2>/dev/null | wc -l)
if [ "$DESCRIBE_COUNT" -lt 1 ]; then
echo "❌ Gate 4b FAILED: No describe blocks found"
echo " Integration tests must have describe blocks"
exit 1
fi
echo "✅ Found $DESCRIBE_COUNT describe block(s)"
# 3. Multiple test cases (3+ per operation)
IT_COUNT=$(grep -h "^\s*it(" test/integration/*.ts 2>/dev/null | wc -l)
if [ "$IT_COUNT" -lt 3 ]; then
echo "❌ Gate 4b FAILED: Insufficient test cases (found $IT_COUNT, need 3+)"
echo " Each operation needs multiple test cases"
exit 1
fi
echo "✅ Found $IT_COUNT test case(s)"
# 4. CRITICAL: NO hardcoded test values
echo "Checking for hardcoded test values..."
HARDCODED_IDS=$(grep -h -n -E "(const|let|var) [a-zA-Z_][a-zA-Z0-9_]*[Ii]d = ['\"][0-9a-zA-Z_-]+['\"]" test/integration/*.ts 2>/dev/null | grep -v "Common.ts" || true)
if [ -n "$HARDCODED_IDS" ]; then
echo "❌ Gate 4b FAILED: Hardcoded test values found"
echo " ALL test values must be in .env and imported from Common.ts"
echo ""
echo "Found hardcoded values:"
echo "$HARDCODED_IDS"
echo ""
echo "Fix:"
echo " 1. Add to .env file:"
echo " SERVICE_TEST_USER_ID=12345"
echo " SERVICE_TEST_ORGANIZATION_ID=1067"
echo ""
echo " 2. Export from test/integration/Common.ts:"
echo " export const SERVICE_TEST_USER_ID = process.env.SERVICE_TEST_USER_ID || '';"
echo ""
echo " 3. Import in test files:"
echo " import { SERVICE_TEST_USER_ID } from './Common';"
echo " const userId = SERVICE_TEST_USER_ID;"
echo ""
echo "See env-file-patterns skill Rule #3"
exit 1
fi
echo "✅ No hardcoded test values"
# 5. CRITICAL: Verify Common.ts exists and exports test data
if [ ! -f "test/integration/Common.ts" ]; then
echo "❌ Gate 4b FAILED: test/integration/Common.ts missing"
echo " Create Common.ts with:"
echo " - Credential loading from .env"
echo " - Test data exports (TEST_USER_ID, etc.)"
echo " - getConnectedInstance() helper"
echo " - hasCredentials() check"
echo ""
echo "See integration-test-patterns skill for template"
exit 1
fi
# Check Common.ts has test data exports
if ! grep -E "export const.*TEST.*=" test/integration/Common.ts > /dev/null 2>&1; then
echo "⚠️ WARNING: Common.ts should export test data constants"
echo " Example: export const TEST_USER_ID = process.env.TEST_USER_ID || '';"
echo " See env-file-patterns skill"
fi
# Check Common.ts loads credentials
if ! grep -q "process.env" test/integration/Common.ts; then
echo "⚠️ WARNING: Common.ts should load credentials from process.env"
fi
# Check Common.ts has getConnectedInstance
if ! grep -q "getConnectedInstance" test/integration/Common.ts; then
echo "❌ Gate 4b FAILED: Common.ts missing getConnectedInstance() helper"
echo " Add getConnectedInstance() function that:"
echo " - Connects using real credentials"
echo " - Caches connection instance"
echo " - Returns connected instance for tests"
exit 1
fi
# Check Common.ts has hasCredentials
if ! grep -q "hasCredentials" test/integration/Common.ts; then
echo "⚠️ WARNING: Common.ts should have hasCredentials() function"
echo " Used to skip tests when credentials unavailable"
fi
echo "✅ Common.ts properly structured"
# 6. Verify .env file exists
if [ ! -f ".env" ]; then
echo "⚠️ WARNING: .env file missing"
echo " Create .env with test credentials and data"
echo " See env-file-patterns skill"
echo ""
echo "Example .env:"
echo " SERVICE_API_KEY=your-api-key"
echo " SERVICE_TEST_USER_ID=12345"
echo " SERVICE_TEST_ORGANIZATION_ID=1067"
fi
# 7. Verify tests import from Common.ts
TEST_FILES_WITHOUT_COMMON=$(grep -L "from.*['\"]\.\/Common['\"]" test/integration/*Test.ts 2>/dev/null || true)
if [ -n "$TEST_FILES_WITHOUT_COMMON" ]; then
echo "⚠️ WARNING: Some test files don't import from Common.ts:"
echo "$TEST_FILES_WITHOUT_COMMON"
echo " Tests should import credentials and test data from Common.ts"
fi
# 8. Verify tests check hasCredentials
if ! grep -r "hasCredentials()" test/integration/*.ts > /dev/null 2>&1; then
echo "⚠️ WARNING: Tests should check hasCredentials() in before() hook"
echo " Add:"
echo " before(function () {"
echo " if (!hasCredentials()) {"
echo " this.skip();"
echo " }"
echo " });"
fi
# 9. Check for debug logging (MANDATORY)
LOGGER_IMPORTS=$(grep -h -c "getLogger" test/integration/*Test.ts 2>/dev/null | awk '{s+=$1} END {print s}')
if [ "$LOGGER_IMPORTS" -lt 1 ]; then
echo "❌ Gate 4b FAILED: No debug logging found in integration tests"
echo " Debug logging is MANDATORY for integration tests"
echo ""
echo "Add to each test file:"
echo " import { getLogger } from './Common';"
echo " const logger = getLogger('{Resource}ProducerTest');"
echo ""
echo "Log operations:"
echo " logger.debug('api.getUser(id)');"
echo " const user = await api.getUser(userId);"
echo " logger.debug('→', JSON.stringify(user, null, 2));"
echo ""
echo "See integration-test-patterns skill Rule #3"
exit 1
fi
DEBUG_LOGS=$(grep -h "logger\.debug" test/integration/*Test.ts 2>/dev/null | wc -l)
if [ "$DEBUG_LOGS" -lt 2 ]; then
echo "⚠️ WARNING: Insufficient debug logging (found $DEBUG_LOGS statements)"
echo " Log BEFORE and AFTER each API operation"
fi
echo "✅ Debug logging present ($DEBUG_LOGS statements)"
# 10. Verify NO nock in integration tests (should use real API)
if grep -h "from ['\"]nock['\"]" test/integration/*.ts 2>/dev/null | head -1 > /dev/null; then
echo "❌ Gate 4b FAILED: nock found in integration tests"
echo " Integration tests must use REAL API calls, not mocks"
echo ""
echo "Found nock imports:"
grep -n "from ['\"]nock['\"]" test/integration/*.ts
echo ""
echo "Fix: Remove nock - integration tests should call real API"
exit 1
fi
echo "✅ No nock (using real API calls)"
# 11. Check test file naming convention
for file in test/integration/*Test.ts; do
if [ -f "$file" ]; then
basename=$(basename "$file")
if [[ ! "$basename" =~ ^[A-Z][a-zA-Z]*Test\.ts$ ]] && [[ "$basename" != "Common.ts" ]]; then
echo "⚠️ WARNING: Incorrect test file naming: $basename"
echo " Should be: {Resource}ProducerTest.ts or ConnectionTest.ts"
fi
fi
done
# 12. Verify dotenv installed and configured
if [ -f "package.json" ]; then
if ! grep -q "\"dotenv\"" package.json; then
echo "⚠️ WARNING: dotenv not in package.json dependencies"
echo " Run: npm install --save-dev dotenv"
fi
fi
if [ -f ".mocharc.json" ]; then
if ! grep -q "dotenv/config" .mocharc.json; then
echo "⚠️ WARNING: dotenv not configured in .mocharc.json"
echo " Add to .mocharc.json:"
echo " \"require\": [\"ts-node/register\", \"dotenv/config\"]"
fi
fi
echo ""
echo "✅ Gate 4b: Integration Test Creation - PASSED"
PROCEED ONLY IF:
IF FAILED:
// ❌ WRONG - hardcoded IDs
describe('UserProducer Integration', function () {
it('should retrieve user', async () => {
const userId = '12345'; // HARDCODED - NO!
const groupId = 'abc-def-ghi'; // HARDCODED - NO!
const user = await userApi.getUser(userId);
expect(user.id).to.equal(userId);
});
});
// ✅ CORRECT - from .env via Common.ts
// .env file:
// SERVICE_TEST_USER_ID=12345
// SERVICE_TEST_GROUP_ID=abc-def-ghi
// test/integration/Common.ts:
export const TEST_USER_ID = process.env.SERVICE_TEST_USER_ID || '';
export const TEST_GROUP_ID = process.env.SERVICE_TEST_GROUP_ID || '';
// test/integration/UserProducerTest.ts:
import { TEST_USER_ID, TEST_GROUP_ID } from './Common';
describe('UserProducer Integration', function () {
it('should retrieve user', async () => {
const userId = TEST_USER_ID; // From .env
const groupId = TEST_GROUP_ID; // From .env
const user = await userApi.getUser(userId);
expect(user.id).to.equal(userId);
});
});
Why:
// ❌ WRONG - Common.ts missing test data exports
import { config } from 'dotenv';
import { Email } from '@zerobias-org/types-core-js';
import { newService } from '../../src';
config();
export const SERVICE_EMAIL = process.env.SERVICE_EMAIL || '';
export const SERVICE_PASSWORD = process.env.SERVICE_PASSWORD || '';
export function hasCredentials(): boolean {
return !!SERVICE_EMAIL && !!SERVICE_PASSWORD;
}
export async function getConnectedInstance() {
// ... connection logic
}
// ✅ CORRECT - Common.ts with test data exports
import { config } from 'dotenv';
import { Email } from '@zerobias-org/types-core-js';
import { LoggerEngine } from '@zerobias-org/logger';
import { newService } from '../../src';
import type { ServiceConnector } from '../../src';
config();
// Credentials
export const SERVICE_EMAIL = process.env.SERVICE_EMAIL || '';
export const SERVICE_PASSWORD = process.env.SERVICE_PASSWORD || '';
// Test data values - export ANY test IDs, names, or other values
export const TEST_USER_ID = process.env.SERVICE_TEST_USER_ID || '';
export const TEST_ORGANIZATION_ID = process.env.SERVICE_TEST_ORGANIZATION_ID || '';
export const TEST_RESOURCE_NAME = process.env.SERVICE_TEST_RESOURCE_NAME || '';
export function getLogger(name: string) {
return LoggerEngine.root().get(name);
}
if (process.env.LOG_LEVEL) {
switch (process.env.LOG_LEVEL) {
case 'trace': {
getLogger().setLevel(LogLevel.TRACE);
break;
}
case 'debug': {
getLogger().setLevel(LogLevel.DEBUG);
break;
}
case 'verbose': {
getLogger().setLevel(LogLevel.VERBOSE);
break;
}
case 'info': {
getLogger().setLevel(LogLevel.INFO);
break;
}
case 'warn': {
getLogger().setLevel(LogLevel.WARN);
break;
}
case 'error': {
getLogger().setLevel(LogLevel.ERROR);
break;
}
case 'crit': {
getLogger().setLevel(LogLevel.CRIT);
break;
}
default: {
getLogger().setLevel(LogLevel.INFO);
break;
}
}
}
export function hasCredentials(): boolean {
return !!SERVICE_EMAIL && !!SERVICE_PASSWORD;
}
let cachedConnector: ServiceConnector | null = null;
export async function getConnectedInstance(): Promise<ServiceConnector> {
if (cachedConnector) {
return cachedConnector;
}
const connector = newService();
await connector.connect({
email: new Email(SERVICE_EMAIL),
password: SERVICE_PASSWORD,
});
cachedConnector = connector;
return connector;
}
Why:
# ❌ WRONG - no .env file
# Tests try to run but have no credentials or test data
# ✅ CORRECT - .env file exists in module root
# .env
[email protected]
SERVICE_PASSWORD=test-password
SERVICE_API_KEY=your-api-key
# Test data values
SERVICE_TEST_USER_ID=12345
SERVICE_TEST_ORGANIZATION_ID=1067
SERVICE_TEST_RESOURCE_NAME=test-resource
SERVICE_TEST_WORKSPACE_ID=ws_abc123
# Optional: Debug logging
LOG_LEVEL=info # Set to 'debug' for verbose output
Usage:
# Run integration tests with debug logging
LOG_LEVEL=debug npm run test:integration
// ❌ WRONG - no logging
import { expect } from 'chai';
import { getConnectedInstance, hasCredentials, TEST_USER_ID } from './Common';
describe('UserProducer Integration', function () {
before(function () {
if (!hasCredentials()) {
this.skip();
}
});
it('should get user', async () => {
const connector = await getConnectedInstance();
const userApi = connector.getUserApi();
const user = await userApi.getUser(TEST_USER_ID);
expect(user).toBeDefined();
});
});
// ✅ CORRECT - debug logging before/after operations
import { expect } from 'chai';
import {
getConnectedInstance,
hasCredentials,
getLogger,
TEST_USER_ID
} from './Common';
const logger = getLogger('UserProducerTest');
describe('UserProducer Integration', function () {
this.timeout(30000);
before(function () {
if (!hasCredentials()) {
this.skip();
}
});
it('should get user', async () => {
logger.debug('getConnectedInstance()');
const connector = await getConnectedInstance();
const userApi = connector.getUserApi();
logger.debug('userApi.getUser(userId)', { userId: TEST_USER_ID });
const user = await userApi.getUser(TEST_USER_ID);
logger.debug('→', JSON.stringify(user, null, 2));
expect(user).toBeDefined();
expect(user.id).to.equal(TEST_USER_ID);
});
});
Run with debug output:
LOG_LEVEL=debug npm run test:integration
Why:
// ❌ WRONG - mocking in integration tests
import * as nock from 'nock';
import { expect } from 'chai';
describe('UserProducer Integration', function () {
it('should get user', async () => {
// NO! Integration tests should NOT mock
nock('https://api.service.com')
.get('/users/123')
.reply(200, { id: '123' });
const user = await userApi.getUser('123');
expect(user).toBeDefined();
});
});
// ✅ CORRECT - real API calls
import { expect } from 'chai';
import {
getConnectedInstance,
hasCredentials,
getLogger,
TEST_USER_ID
} from './Common';
const logger = getLogger('UserProducerTest');
describe('UserProducer Integration', function () {
this.timeout(30000);
before(function () {
if (!hasCredentials()) {
this.skip();
}
});
it('should get user', async () => {
logger.debug('getConnectedInstance()');
const connector = await getConnectedInstance();
const userApi = connector.getUserApi();
logger.debug('userApi.getUser(userId)', { userId: TEST_USER_ID });
const user = await userApi.getUser(TEST_USER_ID); // Real API call
logger.debug('→', JSON.stringify(user, null, 2));
expect(user).toBeDefined();
expect(user.id).to.equal(TEST_USER_ID);
});
});
Why:
// ❌ WRONG - no credential check
describe('UserProducer Integration', function () {
it('should get user', async () => {
// Fails if no .env file - no graceful skip
const connector = await getConnectedInstance();
const user = await userApi.getUser(TEST_USER_ID);
expect(user).toBeDefined();
});
});
// ✅ CORRECT - graceful skip when no credentials
import { hasCredentials, getConnectedInstance, getLogger } from './Common';
const logger = getLogger('UserProducerTest');
describe('UserProducer Integration', function () {
this.timeout(30000);
before(function () {
if (!hasCredentials()) {
logger.info('Skipping: no credentials in .env');
this.skip();
}
});
it('should get user', async () => {
logger.debug('getConnectedInstance()');
const connector = await getConnectedInstance();
const userApi = connector.getUserApi();
logger.debug('userApi.getUser(userId)');
const user = await userApi.getUser(TEST_USER_ID);
logger.debug('→', JSON.stringify(user, null, 2));
expect(user).toBeDefined();
});
});
Why:
# Verify integration tests exist
ls -lh test/integration/*Test.ts
# Count test suites and cases
echo "Describe blocks:"
grep -h "^describe(" test/integration/*.ts | wc -l
echo "Test cases:"
grep -h "^\s*it(" test/integration/*.ts | wc -l
echo "Debug logging statements:"
grep -h "logger.debug" test/integration/*.ts | wc -l
# Check for hardcoded test values (should find none)
echo "Checking for hardcoded test values:"
grep -n -E "(const|let|var) [a-zA-Z]*[Ii]d = ['\"][0-9a-zA-Z-]+['\"]" \
test/integration/*.ts | grep -v "Common.ts" && \
echo "❌ FAIL: Found hardcoded values" || \
echo "✅ PASS: No hardcoded values"
# Check Common.ts exports test data
echo "Checking Common.ts test data exports:"
grep -E "export const.*TEST.*=" test/integration/Common.ts && \
echo "✅ Test data exported" || \
echo "⚠️ WARNING: No test data exports"
# Check .env file exists
[ -f ".env" ] && \
echo "✅ .env file exists" || \
echo "⚠️ WARNING: .env file missing"
# Check Common.ts structure
echo "Checking test/integration/Common.ts:"
# Should load from process.env
grep -q "process.env" test/integration/Common.ts && \
echo "✅ Loads from process.env" || \
echo "❌ Should load from process.env"
# Should have getConnectedInstance
grep -q "getConnectedInstance" test/integration/Common.ts && \
echo "✅ Has getConnectedInstance" || \
echo "❌ Missing getConnectedInstance"
# Should have hasCredentials
grep -q "hasCredentials" test/integration/Common.ts && \
echo "✅ Has hasCredentials" || \
echo "❌ Missing hasCredentials"
# Should have getLogger
grep -q "getLogger" test/integration/Common.ts && \
echo "✅ Has getLogger" || \
echo "⚠️ WARNING: Should have getLogger"
# Check for nock (should not be in integration tests)
echo "Checking for nock in integration tests:"
grep -l "from ['\"]nock['\"]" test/integration/*.ts && \
echo "❌ FAIL: nock found (should use real API)" || \
echo "✅ PASS: No nock (using real API)"
# Run integration tests (requires .env)
npm run test:integration
# Run with debug logging
LOG_LEVEL=debug npm run test:integration
# Expected: Tests pass with real API or skip gracefully if no credentials
Integration test creation MUST meet ALL criteria:
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience