create-qa-architect 5.0.0 โ†’ 5.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.github/RELEASE_CHECKLIST.md +2 -4
  2. package/.github/workflows/daily-deploy-check.yml +136 -0
  3. package/.github/workflows/nightly-gitleaks-verification.yml +1 -1
  4. package/.github/workflows/quality.yml +3 -0
  5. package/.github/workflows/release.yml +12 -10
  6. package/.github/workflows/weekly-audit.yml +173 -0
  7. package/LICENSE +66 -0
  8. package/README.md +44 -30
  9. package/config/defaults.js +22 -1
  10. package/config/quality-config.schema.json +1 -1
  11. package/create-saas-monetization.js +75 -27
  12. package/docs/ARCHITECTURE.md +53 -0
  13. package/docs/DEPLOYMENT.md +62 -0
  14. package/docs/PREFLIGHT_REPORT.md +108 -0
  15. package/docs/SLA_GATES.md +28 -0
  16. package/docs/TESTING.md +61 -0
  17. package/docs/security/SOC2_STARTER.md +29 -0
  18. package/lib/config-validator.js +8 -2
  19. package/lib/dependency-monitoring-basic.js +73 -26
  20. package/lib/dependency-monitoring-premium.js +21 -19
  21. package/lib/github-api.js +249 -0
  22. package/lib/interactive/questions.js +4 -0
  23. package/lib/license-validator.js +1 -1
  24. package/lib/licensing.js +11 -10
  25. package/lib/package-utils.js +224 -8
  26. package/lib/project-maturity.js +1 -1
  27. package/lib/setup-enhancements.js +33 -0
  28. package/lib/template-loader.js +2 -0
  29. package/lib/ui-helpers.js +2 -1
  30. package/lib/validation/base-validator.js +5 -1
  31. package/lib/validation/cache-manager.js +1 -0
  32. package/lib/validation/config-security.js +5 -4
  33. package/lib/validation/validation-factory.js +1 -1
  34. package/lib/yaml-utils.js +15 -10
  35. package/package.json +18 -13
  36. package/scripts/check-docs.sh +63 -0
  37. package/scripts/smart-test-strategy.sh +98 -0
  38. package/scripts/test-e2e-package.sh +283 -0
  39. package/scripts/validate-command-patterns.js +112 -0
  40. package/setup.js +161 -44
  41. package/templates/QUALITY_TROUBLESHOOTING.md +403 -0
  42. package/templates/ci/circleci-config.yml +35 -0
  43. package/templates/ci/gitlab-ci.yml +47 -0
  44. package/templates/integration-tests/api-service.test.js +244 -0
  45. package/templates/integration-tests/frontend-app.test.js +267 -0
  46. package/templates/scripts/smart-test-strategy.sh +109 -0
  47. package/templates/test-stubs/e2e.smoke.test.js +12 -0
  48. package/templates/test-stubs/unit.test.js +7 -0
  49. package/legal/README.md +0 -106
  50. package/legal/copyright.md +0 -76
  51. package/legal/disclaimer.md +0 -146
  52. package/legal/privacy-policy.html +0 -324
  53. package/legal/privacy-policy.md +0 -196
  54. package/legal/terms-of-service.md +0 -224
  55. package/marketing/beta-user-email-campaign.md +0 -372
  56. package/marketing/landing-page.html +0 -721
@@ -0,0 +1,244 @@
1
+ /**
2
+ * API Service Integration Test Template
3
+ * Real database and HTTP integration testing
4
+ */
5
+
6
+ import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest'
7
+ import request from 'supertest'
8
+
9
+ // Example: Adjust imports based on your API framework
10
+ // import app from '../src/app.js'
11
+ // import { setupTestDatabase, cleanupTestDatabase } from './helpers/database'
12
+
13
+ describe('API Service Integration Tests', () => {
14
+ let testApp
15
+ let _testDb
16
+
17
+ beforeAll(async () => {
18
+ // Setup test database with real connection
19
+ // testDb = await setupTestDatabase()
20
+ // testApp = createApp(testDb)
21
+
22
+ console.log('๐Ÿ”ง API Integration Test Setup:')
23
+ console.log(' 1. Initialize test database (PostgreSQL/MySQL/SQLite)')
24
+ console.log(' 2. Run migrations and seed test data')
25
+ console.log(' 3. Configure test environment variables')
26
+ console.log(' 4. Start test server on random port')
27
+ })
28
+
29
+ afterAll(async () => {
30
+ // Cleanup test database
31
+ // await cleanupTestDatabase(testDb)
32
+ console.log('๐Ÿงน Cleaned up test database and connections')
33
+ })
34
+
35
+ beforeEach(async () => {
36
+ // Reset test data before each test
37
+ // await testDb.truncate(['users', 'sessions'])
38
+ })
39
+
40
+ describe('Authentication Flow', () => {
41
+ it('should complete full authentication cycle', async () => {
42
+ // Register user
43
+ const registerResponse = await request(testApp)
44
+ .post('/api/auth/register')
45
+ .send({
46
+ email: 'test@example.com',
47
+ password: 'SecurePassword123!',
48
+ name: 'Test User',
49
+ })
50
+ .expect(201)
51
+
52
+ expect(registerResponse.body).toMatchObject({
53
+ user: { email: 'test@example.com' },
54
+ token: expect.any(String),
55
+ })
56
+
57
+ // Login with credentials
58
+ const loginResponse = await request(testApp)
59
+ .post('/api/auth/login')
60
+ .send({
61
+ email: 'test@example.com',
62
+ password: 'SecurePassword123!',
63
+ })
64
+ .expect(200)
65
+
66
+ const { token } = loginResponse.body
67
+
68
+ // Access protected resource
69
+ const protectedResponse = await request(testApp)
70
+ .get('/api/user/profile')
71
+ .set('Authorization', `Bearer ${token}`)
72
+ .expect(200)
73
+
74
+ expect(protectedResponse.body.email).toBe('test@example.com')
75
+ })
76
+
77
+ it('should handle invalid credentials properly', async () => {
78
+ await request(testApp)
79
+ .post('/api/auth/login')
80
+ .send({
81
+ email: 'nonexistent@example.com',
82
+ password: 'wrongpassword',
83
+ })
84
+ .expect(401)
85
+ })
86
+
87
+ it('should enforce rate limiting on login attempts', async () => {
88
+ const credentials = {
89
+ email: 'test@example.com',
90
+ password: 'wrongpassword',
91
+ }
92
+
93
+ // Make multiple failed attempts
94
+ for (let i = 0; i < 5; i++) {
95
+ await request(testApp)
96
+ .post('/api/auth/login')
97
+ .send(credentials)
98
+ .expect(401)
99
+ }
100
+
101
+ // 6th attempt should be rate limited
102
+ await request(testApp)
103
+ .post('/api/auth/login')
104
+ .send(credentials)
105
+ .expect(429)
106
+ })
107
+ })
108
+
109
+ describe('Database Operations', () => {
110
+ it('should handle concurrent user creation', async () => {
111
+ const users = [
112
+ { email: 'user1@test.com', password: 'Pass123!', name: 'User 1' },
113
+ { email: 'user2@test.com', password: 'Pass123!', name: 'User 2' },
114
+ { email: 'user3@test.com', password: 'Pass123!', name: 'User 3' },
115
+ ]
116
+
117
+ // Create users concurrently
118
+ const promises = users.map(user =>
119
+ request(testApp).post('/api/auth/register').send(user)
120
+ )
121
+
122
+ const responses = await Promise.all(promises)
123
+
124
+ // All should succeed
125
+ responses.forEach(response => {
126
+ expect(response.status).toBe(201)
127
+ expect(response.body.user).toBeDefined()
128
+ })
129
+
130
+ // Verify database consistency
131
+ const allUsers = await request(testApp)
132
+ .get('/api/admin/users')
133
+ .set('Authorization', 'Bearer admin_token')
134
+ .expect(200)
135
+
136
+ expect(allUsers.body.users).toHaveLength(3)
137
+ })
138
+
139
+ it('should maintain data integrity during transactions', async () => {
140
+ // Test database transactions and rollbacks
141
+ // Example: Transfer operation that must be atomic
142
+ const response = await request(testApp)
143
+ .post('/api/transfer')
144
+ .send({
145
+ fromAccount: 'account1',
146
+ toAccount: 'account2',
147
+ amount: 100.0,
148
+ })
149
+ .expect(200)
150
+
151
+ expect(response.body.transaction).toMatchObject({
152
+ status: 'completed',
153
+ fromAccount: 'account1',
154
+ toAccount: 'account2',
155
+ amount: 100.0,
156
+ })
157
+ })
158
+ })
159
+
160
+ describe('Error Handling', () => {
161
+ it('should handle database connection errors gracefully', async () => {
162
+ // Simulate database disconnection
163
+ // await testDb.disconnect()
164
+
165
+ const response = await request(testApp).get('/api/users').expect(503)
166
+
167
+ expect(response.body).toMatchObject({
168
+ error: 'Service temporarily unavailable',
169
+ code: 'DATABASE_UNAVAILABLE',
170
+ })
171
+
172
+ // Reconnect for cleanup
173
+ // await testDb.reconnect()
174
+ })
175
+
176
+ it('should validate request payloads properly', async () => {
177
+ await request(testApp)
178
+ .post('/api/auth/register')
179
+ .send({
180
+ // Missing required fields
181
+ email: 'invalid-email',
182
+ })
183
+ .expect(400)
184
+ .expect(res => {
185
+ expect(res.body.errors).toContain('Valid email required')
186
+ expect(res.body.errors).toContain('Password is required')
187
+ })
188
+ })
189
+ })
190
+
191
+ describe('Performance', () => {
192
+ it('should handle reasonable load', async () => {
193
+ const startTime = Date.now()
194
+
195
+ // Make 50 concurrent requests
196
+ const promises = Array.from({ length: 50 }, () =>
197
+ request(testApp).get('/api/health')
198
+ )
199
+
200
+ const responses = await Promise.all(promises)
201
+ const endTime = Date.now()
202
+
203
+ // All should succeed
204
+ responses.forEach(response => {
205
+ expect(response.status).toBe(200)
206
+ })
207
+
208
+ // Should complete within reasonable time (adjust threshold)
209
+ expect(endTime - startTime).toBeLessThan(5000)
210
+ })
211
+ })
212
+ })
213
+
214
+ // Example test helpers (create in tests/helpers/)
215
+ /*
216
+ // tests/helpers/database.js
217
+ export async function setupTestDatabase() {
218
+ // Create test database connection
219
+ // Run migrations
220
+ // Seed test data
221
+ }
222
+
223
+ export async function cleanupTestDatabase(db) {
224
+ // Clean up test data
225
+ // Close connections
226
+ }
227
+
228
+ // tests/helpers/auth.js
229
+ export async function createTestUser(app, userData) {
230
+ const response = await request(app)
231
+ .post('/api/auth/register')
232
+ .send(userData)
233
+
234
+ return response.body.user
235
+ }
236
+
237
+ export async function loginTestUser(app, credentials) {
238
+ const response = await request(app)
239
+ .post('/api/auth/login')
240
+ .send(credentials)
241
+
242
+ return response.body.token
243
+ }
244
+ */
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Frontend Application Integration Test Template
3
+ * Real browser testing with user interactions
4
+ */
5
+
6
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest'
7
+ import { test } from '@playwright/test'
8
+
9
+ // Example: Adjust imports based on your frontend framework
10
+ // React Testing Library example
11
+ // import { render, screen, fireEvent, waitFor } from '@testing-library/react'
12
+ // import userEvent from '@testing-library/user-event'
13
+ // import { BrowserRouter } from 'react-router-dom'
14
+
15
+ describe('Frontend Application Integration Tests', () => {
16
+ beforeAll(async () => {
17
+ console.log('๐Ÿ”ง Frontend Integration Test Setup:')
18
+ console.log(' 1. Start development server')
19
+ console.log(' 2. Setup test database/mock APIs')
20
+ console.log(' 3. Configure test environment')
21
+ console.log(' 4. Launch browser for E2E tests')
22
+ })
23
+
24
+ afterAll(async () => {
25
+ console.log('๐Ÿงน Cleaned up test environment')
26
+ })
27
+
28
+ describe('User Authentication Flow', () => {
29
+ it('should complete full authentication journey', async () => {
30
+ // Example using React Testing Library
31
+ /*
32
+ const user = userEvent.setup()
33
+
34
+ render(
35
+ <BrowserRouter>
36
+ <App />
37
+ </BrowserRouter>
38
+ )
39
+
40
+ // Navigate to login
41
+ const loginButton = screen.getByRole('button', { name: /sign in/i })
42
+ await user.click(loginButton)
43
+
44
+ // Fill login form
45
+ const emailInput = screen.getByLabelText(/email/i)
46
+ const passwordInput = screen.getByLabelText(/password/i)
47
+
48
+ await user.type(emailInput, 'test@example.com')
49
+ await user.type(passwordInput, 'SecurePassword123!')
50
+
51
+ const submitButton = screen.getByRole('button', { name: /log in/i })
52
+ await user.click(submitButton)
53
+
54
+ // Verify successful login
55
+ await waitFor(() => {
56
+ expect(screen.getByText(/welcome back/i)).toBeInTheDocument()
57
+ })
58
+
59
+ // Verify navigation to dashboard
60
+ expect(screen.getByRole('heading', { name: /dashboard/i })).toBeInTheDocument()
61
+ */
62
+
63
+ expect(true).toBe(true) // Replace with actual test
64
+ })
65
+
66
+ it('should handle login validation errors', async () => {
67
+ // Test form validation, API errors, network issues
68
+ expect(true).toBe(true) // Replace with actual test
69
+ })
70
+
71
+ it('should persist authentication across page refreshes', async () => {
72
+ // Test token persistence, automatic login restoration
73
+ expect(true).toBe(true) // Replace with actual test
74
+ })
75
+ })
76
+
77
+ describe('Component Integration', () => {
78
+ it('should handle complex form interactions', async () => {
79
+ // Example: Multi-step form with validation
80
+ /*
81
+ const user = userEvent.setup()
82
+
83
+ render(<UserRegistrationForm />)
84
+
85
+ // Step 1: Basic information
86
+ await user.type(screen.getByLabelText(/first name/i), 'John')
87
+ await user.type(screen.getByLabelText(/last name/i), 'Doe')
88
+ await user.type(screen.getByLabelText(/email/i), 'john@example.com')
89
+
90
+ await user.click(screen.getByRole('button', { name: /next/i }))
91
+
92
+ // Step 2: Additional details
93
+ await user.selectOptions(screen.getByLabelText(/country/i), 'US')
94
+ await user.type(screen.getByLabelText(/phone/i), '+1234567890')
95
+
96
+ await user.click(screen.getByRole('button', { name: /submit/i }))
97
+
98
+ // Verify submission
99
+ await waitFor(() => {
100
+ expect(screen.getByText(/registration successful/i)).toBeInTheDocument()
101
+ })
102
+ */
103
+
104
+ expect(true).toBe(true) // Replace with actual test
105
+ })
106
+
107
+ it('should handle API loading states properly', async () => {
108
+ // Test loading spinners, skeleton UI, error states
109
+ expect(true).toBe(true) // Replace with actual test
110
+ })
111
+
112
+ it('should update UI based on real-time data', async () => {
113
+ // Test WebSocket connections, polling, state updates
114
+ expect(true).toBe(true) // Replace with actual test
115
+ })
116
+ })
117
+
118
+ describe('Navigation and Routing', () => {
119
+ it('should handle complex navigation flows', async () => {
120
+ // Test protected routes, redirects, deep linking
121
+ expect(true).toBe(true) // Replace with actual test
122
+ })
123
+
124
+ it('should preserve state during navigation', async () => {
125
+ // Test form data persistence, scroll position, etc.
126
+ expect(true).toBe(true) // Replace with actual test
127
+ })
128
+ })
129
+
130
+ describe('Accessibility Integration', () => {
131
+ it('should support keyboard navigation', async () => {
132
+ // Test tab order, keyboard shortcuts, focus management
133
+ expect(true).toBe(true) // Replace with actual test
134
+ })
135
+
136
+ it('should work with screen readers', async () => {
137
+ // Test aria labels, semantic HTML, announcements
138
+ expect(true).toBe(true) // Replace with actual test
139
+ })
140
+
141
+ it('should handle color contrast and visual requirements', async () => {
142
+ // Test color contrast ratios, font sizes, visual indicators
143
+ expect(true).toBe(true) // Replace with actual test
144
+ })
145
+ })
146
+ })
147
+
148
+ // Playwright E2E Tests (real browser testing)
149
+ test.describe('Frontend E2E Tests', () => {
150
+ test.beforeEach(async ({ page }) => {
151
+ // Navigate to app
152
+ await page.goto('http://localhost:3000')
153
+ })
154
+
155
+ test('should complete user signup and onboarding', async ({ page }) => {
156
+ // Click signup button
157
+ await page.click('text=Sign Up')
158
+
159
+ // Fill registration form
160
+ await page.fill('[data-testid=email-input]', 'test@example.com')
161
+ await page.fill('[data-testid=password-input]', 'SecurePassword123!')
162
+ await page.fill(
163
+ '[data-testid=confirm-password-input]',
164
+ 'SecurePassword123!'
165
+ )
166
+
167
+ // Submit form
168
+ await page.click('[data-testid=signup-button]')
169
+
170
+ // Wait for redirect to onboarding
171
+ await page.waitForURL('**/onboarding')
172
+
173
+ // Complete onboarding steps
174
+ await page.fill('[data-testid=first-name]', 'Test')
175
+ await page.fill('[data-testid=last-name]', 'User')
176
+ await page.click('[data-testid=continue-button]')
177
+
178
+ // Verify dashboard access
179
+ await page.waitForURL('**/dashboard')
180
+ await expect(page.locator('h1')).toContainText('Welcome, Test!')
181
+ })
182
+
183
+ test('should handle responsive design across devices', async ({ page }) => {
184
+ // Test mobile viewport
185
+ await page.setViewportSize({ width: 375, height: 667 })
186
+
187
+ // Mobile navigation should be collapsed
188
+ await expect(page.locator('[data-testid=mobile-menu-button]')).toBeVisible()
189
+ await expect(page.locator('[data-testid=desktop-nav]')).not.toBeVisible()
190
+
191
+ // Test tablet viewport
192
+ await page.setViewportSize({ width: 768, height: 1024 })
193
+
194
+ // Test desktop viewport
195
+ await page.setViewportSize({ width: 1920, height: 1080 })
196
+
197
+ // Desktop navigation should be visible
198
+ await expect(page.locator('[data-testid=desktop-nav]')).toBeVisible()
199
+ })
200
+
201
+ test('should handle network failures gracefully', async ({ page }) => {
202
+ // Simulate offline mode
203
+ await page.context().setOffline(true)
204
+
205
+ // Try to navigate or perform action
206
+ await page.click('[data-testid=load-data-button]')
207
+
208
+ // Should show offline message
209
+ await expect(page.locator('[data-testid=offline-banner]')).toContainText(
210
+ 'You are offline'
211
+ )
212
+
213
+ // Restore connection
214
+ await page.context().setOffline(false)
215
+
216
+ // Should automatically retry and succeed
217
+ await expect(page.locator('[data-testid=data-loaded]')).toBeVisible()
218
+ })
219
+
220
+ test('should maintain performance under load', async ({ page }) => {
221
+ // Navigate to data-heavy page
222
+ await page.goto('http://localhost:3000/dashboard/analytics')
223
+
224
+ // Measure page load performance
225
+ const navigationPromise = page.waitForLoadState('networkidle')
226
+ await navigationPromise
227
+
228
+ // Check that page loaded within reasonable time
229
+ const metrics = await page.evaluate(() =>
230
+ JSON.stringify(window.performance.timing)
231
+ )
232
+ const timing = JSON.parse(metrics)
233
+
234
+ const loadTime = timing.loadEventEnd - timing.navigationStart
235
+ expect(loadTime).toBeLessThan(3000) // 3 seconds max
236
+ })
237
+ })
238
+
239
+ // Example test helpers (create in tests/helpers/)
240
+ /*
241
+ // tests/helpers/render.js
242
+ export function renderWithProviders(ui, options) {
243
+ // Wrap with providers (Router, Theme, Auth, etc.)
244
+ return render(
245
+ <BrowserRouter>
246
+ <ThemeProvider>
247
+ <AuthProvider>
248
+ {ui}
249
+ </AuthProvider>
250
+ </ThemeProvider>
251
+ </BrowserRouter>,
252
+ options
253
+ )
254
+ }
255
+
256
+ // tests/helpers/api.js
257
+ export function mockApiCalls() {
258
+ // Setup MSW or similar mocking
259
+ }
260
+
261
+ // tests/helpers/accessibility.js
262
+ export async function checkAccessibility(container) {
263
+ const { axe } = await import('axe-core')
264
+ const results = await axe(container)
265
+ expect(results.violations).toHaveLength(0)
266
+ }
267
+ */
@@ -0,0 +1,109 @@
1
+ #!/bin/bash
2
+ # Smart Test Strategy - {{PROJECT_NAME}}
3
+ # Generated by create-qa-architect (Pro/Team/Enterprise feature)
4
+ # https://vibebuildlab.com/tools/qa-architect
5
+ set -e
6
+
7
+ echo "๐Ÿง  Analyzing changes for optimal test strategy..."
8
+
9
+ # Environment variable overrides
10
+ if [[ "$SKIP_SMART" == "1" ]]; then
11
+ echo "โš ๏ธ SKIP_SMART=1 - Running comprehensive tests"
12
+ npm run test:comprehensive
13
+ exit 0
14
+ fi
15
+
16
+ if [[ "$FORCE_COMPREHENSIVE" == "1" ]]; then
17
+ echo "๐Ÿ”ด FORCE_COMPREHENSIVE=1 - Running all tests"
18
+ npm run test:comprehensive
19
+ exit 0
20
+ fi
21
+
22
+ if [[ "$FORCE_MINIMAL" == "1" ]]; then
23
+ echo "โšช FORCE_MINIMAL=1 - Running lint only"
24
+ npm run lint && npm run format:check
25
+ exit 0
26
+ fi
27
+
28
+ # Collect metrics
29
+ CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | wc -l | tr -d ' ')
30
+ CHANGED_LINES=$(git diff --stat HEAD~1..HEAD 2>/dev/null | tail -1 | grep -o '[0-9]* insertions' | grep -o '[0-9]*' || echo "0")
31
+ CURRENT_BRANCH=$(git branch --show-current)
32
+ HOUR=$(date +%H)
33
+ DAY_OF_WEEK=$(date +%u)
34
+
35
+ # Project-specific high-risk patterns (customized per project type)
36
+ # {{HIGH_RISK_PATTERN}}
37
+ HIGH_RISK_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "{{HIGH_RISK_REGEX}}" || true)
38
+ API_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "api/|routes/|endpoints/" || true)
39
+ CONFIG_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "(package\.json|\.env|config|tsconfig)" || true)
40
+ SECURITY_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "(auth|security|crypto|payment|billing)" || true)
41
+ TEST_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "test|spec|__tests__" || true)
42
+
43
+ # Calculate risk score (0-10)
44
+ RISK_SCORE=0
45
+
46
+ # File-based risk
47
+ [[ -n "$HIGH_RISK_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 4))
48
+ [[ -n "$SECURITY_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 3))
49
+ [[ -n "$API_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 2))
50
+ [[ -n "$CONFIG_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 2))
51
+
52
+ # Size-based risk
53
+ [[ $CHANGED_FILES -gt 10 ]] && RISK_SCORE=$((RISK_SCORE + 2))
54
+ [[ $CHANGED_FILES -gt 20 ]] && RISK_SCORE=$((RISK_SCORE + 3))
55
+ [[ $CHANGED_LINES -gt 200 ]] && RISK_SCORE=$((RISK_SCORE + 2))
56
+
57
+ # Branch-based risk
58
+ case $CURRENT_BRANCH in
59
+ main|master|production) RISK_SCORE=$((RISK_SCORE + 3)) ;;
60
+ hotfix/*) RISK_SCORE=$((RISK_SCORE + 4)) ;;
61
+ release/*) RISK_SCORE=$((RISK_SCORE + 2)) ;;
62
+ develop) RISK_SCORE=$((RISK_SCORE + 1)) ;;
63
+ esac
64
+
65
+ # Time pressure adjustment (strip leading zeros for arithmetic)
66
+ HOUR_NUM=$((10#$HOUR))
67
+ if [[ $HOUR_NUM -ge 9 && $HOUR_NUM -le 17 && $DAY_OF_WEEK -le 5 ]]; then
68
+ echo "โฐ Work hours - Optimizing for speed"
69
+ SPEED_BONUS=true
70
+ else
71
+ SPEED_BONUS=false
72
+ fi
73
+
74
+ # Display analysis
75
+ echo ""
76
+ echo "๐Ÿ“Š Analysis Results:"
77
+ echo " ๐Ÿ“ Files changed: $CHANGED_FILES"
78
+ echo " ๐Ÿ“ Lines changed: $CHANGED_LINES"
79
+ echo " ๐ŸŒฟ Branch: $CURRENT_BRANCH"
80
+ echo " ๐ŸŽฏ Risk Score: $RISK_SCORE/10"
81
+ echo " โšก Speed Bonus: $SPEED_BONUS"
82
+ echo ""
83
+
84
+ # Test tier selection based on risk score
85
+ if [[ $RISK_SCORE -ge 7 ]]; then
86
+ echo "๐Ÿ”ด HIGH RISK - Comprehensive validation"
87
+ echo " โ€ข All tests + security audit"
88
+ # {{COMPREHENSIVE_COMMAND}}
89
+ {{TEST_COMPREHENSIVE}}
90
+ elif [[ $RISK_SCORE -ge 4 ]]; then
91
+ echo "๐ŸŸก MEDIUM RISK - Standard validation"
92
+ echo " โ€ข Fast tests + integration (excludes slow tests)"
93
+ # {{MEDIUM_COMMAND}}
94
+ {{TEST_MEDIUM}}
95
+ elif [[ $RISK_SCORE -ge 2 || "$SPEED_BONUS" == "false" ]]; then
96
+ echo "๐ŸŸข LOW RISK - Fast validation"
97
+ echo " โ€ข Unit tests only"
98
+ # {{FAST_COMMAND}}
99
+ {{TEST_FAST}}
100
+ else
101
+ echo "โšช MINIMAL RISK - Quality checks only"
102
+ echo " โ€ข Lint + format check"
103
+ # {{MINIMAL_COMMAND}}
104
+ {{TEST_MINIMAL}}
105
+ fi
106
+
107
+ echo ""
108
+ echo "๐Ÿ’ก Tip: Run 'npm run test:comprehensive' locally for full validation"
109
+ echo "๐Ÿ’Ž Smart Test Strategy powered by QA Architect Pro"
@@ -0,0 +1,12 @@
1
+ import { describe, it } from 'vitest'
2
+
3
+ // Replace this stub with Playwright/Cypress flows for your app.
4
+ describe.skip('smoke: homepage renders', () => {
5
+ it('runs a placeholder e2e flow', async () => {
6
+ // TODO: add real browser automation (Playwright/Cypress/Webdriver)
7
+ // Example:
8
+ // const page = await chromium.launch().newPage()
9
+ // await page.goto('http://localhost:3000')
10
+ // await page.getByText('Welcome').isVisible()
11
+ })
12
+ })
@@ -0,0 +1,7 @@
1
+ import { describe, it, expect } from 'vitest'
2
+
3
+ describe('sample unit test', () => {
4
+ it('runs and asserts truthy values', () => {
5
+ expect(true).toBe(true)
6
+ })
7
+ })