@bernierllc/content-management-tests 0.1.1
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.
- package/README.md +522 -0
- package/dist/index.js +1104 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1068 -0
- package/dist/index.mjs.map +1 -0
- package/jest.config.js +33 -0
- package/package.json +125 -0
- package/playwright.config.ts +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
# Content Management Tests
|
|
10
|
+
|
|
11
|
+
A comprehensive test suite for the content management system with Playwright, Jest, and integration tests.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **๐ญ Playwright E2E Tests**: Complete end-to-end testing with browser automation
|
|
16
|
+
- **๐งช Jest Unit Tests**: Unit testing with React Testing Library
|
|
17
|
+
- **๐ Integration Tests**: API and component integration testing
|
|
18
|
+
- **โก Performance Tests**: Load time and performance benchmarking
|
|
19
|
+
- **๐ฑ Responsive Tests**: Mobile, tablet, and desktop testing
|
|
20
|
+
- **โฟ Accessibility Tests**: WCAG compliance testing
|
|
21
|
+
- **๐ ๏ธ Test Utilities**: Reusable test helpers and fixtures
|
|
22
|
+
- **๐ Test Reports**: HTML, JSON, and JUnit test reports
|
|
23
|
+
- **๐ฏ Test Data**: Faker-based test data generation
|
|
24
|
+
- **๐ง Mocking**: Comprehensive mocking for external dependencies
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @bernierllc/content-management-tests
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { createTestUtils, contentFixtures } from '@bernierllc/content-management-tests';
|
|
36
|
+
|
|
37
|
+
// Create test utilities
|
|
38
|
+
const testUtils = createTestUtils(page, context);
|
|
39
|
+
|
|
40
|
+
// Use test fixtures
|
|
41
|
+
const contentData = contentFixtures.text;
|
|
42
|
+
|
|
43
|
+
// Run tests
|
|
44
|
+
await testUtils.createContent('text', contentData);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Test Types
|
|
48
|
+
|
|
49
|
+
### 1. End-to-End Tests
|
|
50
|
+
|
|
51
|
+
Comprehensive browser-based testing with Playwright:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { test, expect } from '@playwright/test';
|
|
55
|
+
import { createTestUtils } from '@bernierllc/content-management-tests';
|
|
56
|
+
|
|
57
|
+
test.describe('Content Management E2E', () => {
|
|
58
|
+
let testUtils: ReturnType<typeof createTestUtils>;
|
|
59
|
+
|
|
60
|
+
test.beforeEach(async ({ page, context }) => {
|
|
61
|
+
testUtils = createTestUtils(page, context);
|
|
62
|
+
await testUtils.navigateTo('/');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('should create and publish content', async () => {
|
|
66
|
+
await testUtils.login('admin@example.com', 'password');
|
|
67
|
+
await testUtils.createContent('text', {
|
|
68
|
+
title: 'Test Content',
|
|
69
|
+
slug: 'test-content',
|
|
70
|
+
body: 'Test body'
|
|
71
|
+
});
|
|
72
|
+
await testUtils.publishContent('test-content');
|
|
73
|
+
await testUtils.expectTextVisible('Content published successfully');
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Unit Tests
|
|
79
|
+
|
|
80
|
+
Component and function testing with Jest:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { render, screen } from '@testing-library/react';
|
|
84
|
+
import { ContentEditor } from '@bernierllc/content-management-suite';
|
|
85
|
+
|
|
86
|
+
describe('ContentEditor', () => {
|
|
87
|
+
test('should render editor component', () => {
|
|
88
|
+
render(<ContentEditor content={contentFixtures.text} />);
|
|
89
|
+
expect(screen.getByTestId('content-editor')).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 3. Integration Tests
|
|
95
|
+
|
|
96
|
+
API and service integration testing:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { test, expect } from '@playwright/test';
|
|
100
|
+
|
|
101
|
+
test.describe('API Integration', () => {
|
|
102
|
+
test('should handle content CRUD operations', async () => {
|
|
103
|
+
const response = await testUtils.apiRequest('POST', '/content', {
|
|
104
|
+
type: 'text',
|
|
105
|
+
data: contentFixtures.text
|
|
106
|
+
});
|
|
107
|
+
expect(response.status).toBe(201);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 4. Performance Tests
|
|
113
|
+
|
|
114
|
+
Load time and performance benchmarking:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { test, expect } from '@playwright/test';
|
|
118
|
+
|
|
119
|
+
test.describe('Performance', () => {
|
|
120
|
+
test('should load content list quickly', async () => {
|
|
121
|
+
const loadTime = await testUtils.measurePerformance('Content List Load', async () => {
|
|
122
|
+
await testUtils.navigateTo('/admin/content');
|
|
123
|
+
await testUtils.waitForElement('[data-testid="content-list"]');
|
|
124
|
+
});
|
|
125
|
+
expect(loadTime).toBeLessThan(2000);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Test Utilities
|
|
131
|
+
|
|
132
|
+
### TestUtils Class
|
|
133
|
+
|
|
134
|
+
Comprehensive test utilities for common operations:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { createTestUtils } from '@bernierllc/content-management-tests';
|
|
138
|
+
|
|
139
|
+
const testUtils = createTestUtils(page, context);
|
|
140
|
+
|
|
141
|
+
// Navigation
|
|
142
|
+
await testUtils.navigateTo('/admin/content');
|
|
143
|
+
await testUtils.waitForElement('[data-testid="content-list"]');
|
|
144
|
+
|
|
145
|
+
// Form operations
|
|
146
|
+
await testUtils.fillForm({
|
|
147
|
+
title: 'Test Title',
|
|
148
|
+
slug: 'test-slug',
|
|
149
|
+
body: 'Test body'
|
|
150
|
+
});
|
|
151
|
+
await testUtils.clickButton('Save as Draft');
|
|
152
|
+
|
|
153
|
+
// Content operations
|
|
154
|
+
await testUtils.createContent('text', contentData);
|
|
155
|
+
await testUtils.editContent(contentId, updates);
|
|
156
|
+
await testUtils.publishContent(contentId);
|
|
157
|
+
await testUtils.deleteContent(contentId, true);
|
|
158
|
+
|
|
159
|
+
// Workflow operations
|
|
160
|
+
await testUtils.createWorkflow(workflowData);
|
|
161
|
+
await testUtils.updateWorkflow(workflowId, updates);
|
|
162
|
+
await testUtils.deleteWorkflow(workflowId);
|
|
163
|
+
|
|
164
|
+
// User operations
|
|
165
|
+
await testUtils.createUser(userData);
|
|
166
|
+
await testUtils.updateUser(userId, updates);
|
|
167
|
+
await testUtils.deleteUser(userId);
|
|
168
|
+
|
|
169
|
+
// Authentication
|
|
170
|
+
await testUtils.login('admin@example.com', 'password');
|
|
171
|
+
await testUtils.logout();
|
|
172
|
+
|
|
173
|
+
// API operations
|
|
174
|
+
const response = await testUtils.apiRequest('GET', '/content');
|
|
175
|
+
const content = await testUtils.getContent(contentId);
|
|
176
|
+
const createdContent = await testUtils.createContentViaAPI('text', data);
|
|
177
|
+
|
|
178
|
+
// Assertions
|
|
179
|
+
await testUtils.expectElementVisible('[data-testid="content-list"]');
|
|
180
|
+
await testUtils.expectTextVisible('Content saved successfully');
|
|
181
|
+
await testUtils.expectElementCount('[data-testid="content-item"]', 5);
|
|
182
|
+
|
|
183
|
+
// Screenshots
|
|
184
|
+
await testUtils.takeScreenshot('content-list');
|
|
185
|
+
await testUtils.takeElementScreenshot('[data-testid="content-editor"]', 'editor');
|
|
186
|
+
|
|
187
|
+
// Performance
|
|
188
|
+
const loadTime = await testUtils.measurePerformance('Page Load', async () => {
|
|
189
|
+
await testUtils.navigateTo('/admin/content');
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Responsive
|
|
193
|
+
await testUtils.switchToMobile();
|
|
194
|
+
await testUtils.switchToTablet();
|
|
195
|
+
await testUtils.switchToDesktop();
|
|
196
|
+
|
|
197
|
+
// Cleanup
|
|
198
|
+
await testUtils.cleanup();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Test Fixtures
|
|
202
|
+
|
|
203
|
+
Pre-defined test data for consistent testing:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import { contentFixtures, workflowFixtures, userFixtures } from '@bernierllc/content-management-tests';
|
|
207
|
+
|
|
208
|
+
// Content fixtures
|
|
209
|
+
const textContent = contentFixtures.text;
|
|
210
|
+
const imageContent = contentFixtures.image;
|
|
211
|
+
const audioContent = contentFixtures.audio;
|
|
212
|
+
const videoContent = contentFixtures.video;
|
|
213
|
+
|
|
214
|
+
// Workflow fixtures
|
|
215
|
+
const simpleWorkflow = workflowFixtures.simple;
|
|
216
|
+
const editorialWorkflow = workflowFixtures.editorial;
|
|
217
|
+
|
|
218
|
+
// User fixtures
|
|
219
|
+
const adminUser = userFixtures.admin;
|
|
220
|
+
const editorUser = userFixtures.editor;
|
|
221
|
+
const authorUser = userFixtures.author;
|
|
222
|
+
const regularUser = userFixtures.user;
|
|
223
|
+
|
|
224
|
+
// Generate custom test data
|
|
225
|
+
const customContent = testDataGenerators.generateContent('text', {
|
|
226
|
+
title: 'Custom Title',
|
|
227
|
+
body: 'Custom body'
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Test Data Generators
|
|
232
|
+
|
|
233
|
+
Dynamic test data generation:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { TestDataGenerator } from '@bernierllc/content-management-tests';
|
|
237
|
+
|
|
238
|
+
// Generate content
|
|
239
|
+
const content = TestDataGenerator.generateContent('text', {
|
|
240
|
+
title: 'Generated Title',
|
|
241
|
+
body: 'Generated body'
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Generate workflow
|
|
245
|
+
const workflow = TestDataGenerator.generateWorkflow({
|
|
246
|
+
name: 'Generated Workflow',
|
|
247
|
+
stages: [...]
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Generate user
|
|
251
|
+
const user = TestDataGenerator.generateUser('admin', {
|
|
252
|
+
name: 'Generated User',
|
|
253
|
+
email: 'generated@example.com'
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Test Configuration
|
|
258
|
+
|
|
259
|
+
### Playwright Configuration
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
// playwright.config.ts
|
|
263
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
264
|
+
|
|
265
|
+
export default defineConfig({
|
|
266
|
+
testDir: './src/playwright',
|
|
267
|
+
fullyParallel: true,
|
|
268
|
+
retries: process.env.CI ? 2 : 0,
|
|
269
|
+
workers: process.env.CI ? 1 : undefined,
|
|
270
|
+
reporter: [
|
|
271
|
+
['html'],
|
|
272
|
+
['json', { outputFile: 'test-results/results.json' }],
|
|
273
|
+
['junit', { outputFile: 'test-results/results.xml' }]
|
|
274
|
+
],
|
|
275
|
+
use: {
|
|
276
|
+
baseURL: 'http://localhost:3000',
|
|
277
|
+
trace: 'on-first-retry',
|
|
278
|
+
screenshot: 'only-on-failure',
|
|
279
|
+
video: 'retain-on-failure'
|
|
280
|
+
},
|
|
281
|
+
projects: [
|
|
282
|
+
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
283
|
+
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
|
|
284
|
+
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
|
|
285
|
+
{ name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
|
|
286
|
+
{ name: 'Mobile Safari', use: { ...devices['iPhone 12'] } }
|
|
287
|
+
]
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Jest Configuration
|
|
292
|
+
|
|
293
|
+
```javascript
|
|
294
|
+
// jest.config.js
|
|
295
|
+
module.exports = {
|
|
296
|
+
testEnvironment: 'jsdom',
|
|
297
|
+
setupFilesAfterEnv: ['<rootDir>/src/setup/jest.setup.ts'],
|
|
298
|
+
testMatch: [
|
|
299
|
+
'<rootDir>/src/**/*.test.ts',
|
|
300
|
+
'<rootDir>/src/**/*.test.tsx'
|
|
301
|
+
],
|
|
302
|
+
collectCoverageFrom: [
|
|
303
|
+
'src/**/*.{ts,tsx}',
|
|
304
|
+
'!src/**/*.test.{ts,tsx}',
|
|
305
|
+
'!src/**/*.stories.{ts,tsx}'
|
|
306
|
+
],
|
|
307
|
+
coverageThreshold: {
|
|
308
|
+
global: {
|
|
309
|
+
branches: 80,
|
|
310
|
+
functions: 80,
|
|
311
|
+
lines: 80,
|
|
312
|
+
statements: 80
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Running Tests
|
|
319
|
+
|
|
320
|
+
### All Tests
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
# Run all tests
|
|
324
|
+
npm run test:all
|
|
325
|
+
|
|
326
|
+
# Run with coverage
|
|
327
|
+
npm run test:coverage
|
|
328
|
+
|
|
329
|
+
# Run in CI mode
|
|
330
|
+
npm run test:ci
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Playwright Tests
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Run Playwright tests
|
|
337
|
+
npm run test:playwright
|
|
338
|
+
|
|
339
|
+
# Run with UI
|
|
340
|
+
npm run test:playwright:ui
|
|
341
|
+
|
|
342
|
+
# Run in debug mode
|
|
343
|
+
npm run test:playwright:debug
|
|
344
|
+
|
|
345
|
+
# Run specific test
|
|
346
|
+
npx playwright test e2e-tests.spec.ts
|
|
347
|
+
|
|
348
|
+
# Run specific browser
|
|
349
|
+
npx playwright test --project=chromium
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Jest Tests
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
# Run Jest tests
|
|
356
|
+
npm run test
|
|
357
|
+
|
|
358
|
+
# Run in watch mode
|
|
359
|
+
npm run test:watch
|
|
360
|
+
|
|
361
|
+
# Run with coverage
|
|
362
|
+
npm run test:coverage
|
|
363
|
+
|
|
364
|
+
# Run specific test
|
|
365
|
+
npm run test -- --testNamePattern="ContentEditor"
|
|
366
|
+
|
|
367
|
+
# Run specific file
|
|
368
|
+
npm run test -- content-editor.test.tsx
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Integration Tests
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
# Run integration tests
|
|
375
|
+
npm run test:integration
|
|
376
|
+
|
|
377
|
+
# Run E2E tests
|
|
378
|
+
npm run test:e2e
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Test Scripts
|
|
382
|
+
|
|
383
|
+
### Package.json Scripts
|
|
384
|
+
|
|
385
|
+
```json
|
|
386
|
+
{
|
|
387
|
+
"scripts": {
|
|
388
|
+
"test": "jest",
|
|
389
|
+
"test:watch": "jest --watch",
|
|
390
|
+
"test:coverage": "jest --coverage",
|
|
391
|
+
"test:playwright": "playwright test",
|
|
392
|
+
"test:playwright:ui": "playwright test --ui",
|
|
393
|
+
"test:playwright:debug": "playwright test --debug",
|
|
394
|
+
"test:integration": "jest --testPathPattern=integration",
|
|
395
|
+
"test:e2e": "jest --testPathPattern=e2e",
|
|
396
|
+
"test:all": "npm run test && npm run test:playwright && npm run test:integration",
|
|
397
|
+
"test:ci": "npm run test:coverage && npm run test:playwright",
|
|
398
|
+
"setup": "playwright install"
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Test Reports
|
|
404
|
+
|
|
405
|
+
### HTML Reports
|
|
406
|
+
|
|
407
|
+
Playwright generates HTML reports with:
|
|
408
|
+
- Test results and status
|
|
409
|
+
- Screenshots and videos
|
|
410
|
+
- Performance metrics
|
|
411
|
+
- Error details and stack traces
|
|
412
|
+
|
|
413
|
+
### JSON Reports
|
|
414
|
+
|
|
415
|
+
Machine-readable JSON reports for CI/CD integration:
|
|
416
|
+
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"config": {
|
|
420
|
+
"projects": [...],
|
|
421
|
+
"webServer": {...}
|
|
422
|
+
},
|
|
423
|
+
"suites": [
|
|
424
|
+
{
|
|
425
|
+
"title": "Content Management E2E",
|
|
426
|
+
"file": "e2e-tests.spec.ts",
|
|
427
|
+
"specs": [...],
|
|
428
|
+
"tests": [...]
|
|
429
|
+
}
|
|
430
|
+
],
|
|
431
|
+
"errors": [...]
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### JUnit Reports
|
|
436
|
+
|
|
437
|
+
JUnit XML reports for CI/CD systems:
|
|
438
|
+
|
|
439
|
+
```xml
|
|
440
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
441
|
+
<testsuites>
|
|
442
|
+
<testsuite name="Content Management E2E" tests="10" failures="0" errors="0" skipped="0" time="45.2">
|
|
443
|
+
<testcase name="should create and publish content" time="3.2" />
|
|
444
|
+
<testcase name="should edit content" time="2.8" />
|
|
445
|
+
...
|
|
446
|
+
</testsuite>
|
|
447
|
+
</testsuites>
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Best Practices
|
|
451
|
+
|
|
452
|
+
### Test Organization
|
|
453
|
+
|
|
454
|
+
1. **Group related tests** in describe blocks
|
|
455
|
+
2. **Use descriptive test names** that explain what is being tested
|
|
456
|
+
3. **Keep tests independent** - each test should be able to run in isolation
|
|
457
|
+
4. **Use setup and teardown** for common test preparation
|
|
458
|
+
5. **Mock external dependencies** to ensure test reliability
|
|
459
|
+
|
|
460
|
+
### Test Data
|
|
461
|
+
|
|
462
|
+
1. **Use fixtures** for consistent test data
|
|
463
|
+
2. **Generate dynamic data** when needed
|
|
464
|
+
3. **Clean up test data** after each test
|
|
465
|
+
4. **Use realistic data** that matches production scenarios
|
|
466
|
+
5. **Avoid hardcoded values** in tests
|
|
467
|
+
|
|
468
|
+
### Assertions
|
|
469
|
+
|
|
470
|
+
1. **Use specific assertions** rather than generic ones
|
|
471
|
+
2. **Test both positive and negative cases**
|
|
472
|
+
3. **Verify error messages** and error handling
|
|
473
|
+
4. **Check accessibility** and responsive design
|
|
474
|
+
5. **Measure performance** for critical operations
|
|
475
|
+
|
|
476
|
+
### Maintenance
|
|
477
|
+
|
|
478
|
+
1. **Keep tests up to date** with code changes
|
|
479
|
+
2. **Refactor tests** when they become brittle
|
|
480
|
+
3. **Use page object model** for complex UI tests
|
|
481
|
+
4. **Document test scenarios** and expected behavior
|
|
482
|
+
5. **Monitor test performance** and optimize slow tests
|
|
483
|
+
|
|
484
|
+
## Troubleshooting
|
|
485
|
+
|
|
486
|
+
### Common Issues
|
|
487
|
+
|
|
488
|
+
1. **Tests timing out**: Increase timeout or optimize test performance
|
|
489
|
+
2. **Element not found**: Check selectors and wait conditions
|
|
490
|
+
3. **Flaky tests**: Add proper waits and retries
|
|
491
|
+
4. **Memory leaks**: Clean up resources and close browsers
|
|
492
|
+
5. **Network issues**: Mock external services and handle failures
|
|
493
|
+
|
|
494
|
+
### Debug Mode
|
|
495
|
+
|
|
496
|
+
```bash
|
|
497
|
+
# Run tests in debug mode
|
|
498
|
+
npx playwright test --debug
|
|
499
|
+
|
|
500
|
+
# Run specific test in debug mode
|
|
501
|
+
npx playwright test --debug --grep "should create content"
|
|
502
|
+
|
|
503
|
+
# Run with headed browser
|
|
504
|
+
npx playwright test --headed
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Test Environment
|
|
508
|
+
|
|
509
|
+
```bash
|
|
510
|
+
# Set test environment
|
|
511
|
+
NODE_ENV=test npm run test
|
|
512
|
+
|
|
513
|
+
# Set test database
|
|
514
|
+
TEST_DATABASE_URL=sqlite:test.db npm run test
|
|
515
|
+
|
|
516
|
+
# Set test port
|
|
517
|
+
TEST_PORT=3001 npm run test
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
## License
|
|
521
|
+
|
|
522
|
+
Copyright (c) 2025 Bernier LLC. Licensed under limited-use license.
|