You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
5.8 KiB
246 lines
5.8 KiB
# Time Safari Architecture — Examples and Testing
|
|
|
|
> **Agent role**: Reference this file for architectural examples and
|
|
testing patterns when working with TimeSafari architecture.
|
|
|
|
## Error Handling Patterns
|
|
|
|
### Global Error Handler
|
|
|
|
```typescript
|
|
|
|
// main.ts
|
|
app.config.errorHandler = (err, instance, info) => {
|
|
const componentName = instance?.$options?.name || 'Unknown';
|
|
logger.error(`[${componentName}] Vue error`, err, info);
|
|
};
|
|
|
|
window.addEventListener('unhandledrejection', (event) => {
|
|
logger.error('[Global] Unhandled promise rejection', event.reason);
|
|
});
|
|
|
|
```
|
|
|
|
### Platform-Specific Error Wrapping
|
|
|
|
```typescript
|
|
|
|
// services/platforms/CapacitorPlatformService.ts
|
|
export class CapacitorPlatformService {
|
|
async getFileContents(path: string): Promise<string> {
|
|
try {
|
|
const result = await Filesystem.readFile({
|
|
path: path,
|
|
encoding: 'utf8'
|
|
});
|
|
return result.data;
|
|
} catch (error) {
|
|
logger.error('[Capacitor API Error] Failed to read file', error, path);
|
|
throw new Error(`Failed to read file: ${path}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
## Testing Patterns
|
|
|
|
### Platform-Specific Test Skipping
|
|
|
|
```typescript
|
|
|
|
// tests/QRScanner.test.ts
|
|
describe('QRScanner Service', () => {
|
|
test('should start scanning on web', async () => {
|
|
test.skip(process.env.VITE_PLATFORM !== 'web', 'Web-only test');
|
|
|
|
const scanner = new WebInlineQRScanner();
|
|
await scanner.startScanning();
|
|
// Assert scanning started
|
|
});
|
|
|
|
test('should start scanning on mobile', async () => {
|
|
test.skip(process.env.VITE_PLATFORM !== 'capacitor', 'Mobile-only test');
|
|
|
|
const scanner = new CapacitorQRScanner();
|
|
await scanner.startScanning();
|
|
// Assert scanning started
|
|
});
|
|
});
|
|
|
|
```
|
|
|
|
### Mock Service Testing
|
|
|
|
```typescript
|
|
|
|
// tests/mocks/QRScannerMock.ts
|
|
export class QRScannerMock implements QRScannerService {
|
|
private isScanning = false;
|
|
private listeners: Map<string, Function[]> = new Map();
|
|
|
|
async startScanning(): Promise<void> {
|
|
this.isScanning = true;
|
|
this.emit('scanningStarted');
|
|
}
|
|
|
|
async stopScanning(): Promise<void> {
|
|
this.isScanning = false;
|
|
this.emit('scanningStopped');
|
|
}
|
|
|
|
addListener(event: string, callback: Function): void {
|
|
if (!this.listeners.has(event)) {
|
|
this.listeners.set(event, []);
|
|
}
|
|
this.listeners.get(event)!.push(callback);
|
|
}
|
|
|
|
removeListener(event: string, callback: Function): void {
|
|
const callbacks = this.listeners.get(event);
|
|
if (callbacks) {
|
|
const index = callbacks.indexOf(callback);
|
|
if (index > -1) {
|
|
callbacks.splice(index, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
private emit(event: string, ...args: any[]): void {
|
|
const callbacks = this.listeners.get(event);
|
|
if (callbacks) {
|
|
callbacks.forEach(callback => callback(...args));
|
|
}
|
|
}
|
|
|
|
getScanningState(): boolean {
|
|
return this.isScanning;
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
## Integration Examples
|
|
|
|
### Service Composition
|
|
|
|
```typescript
|
|
|
|
// services/QRScannerService.ts
|
|
export class QRScannerService {
|
|
constructor(
|
|
private platformService: PlatformService,
|
|
private notificationService: NotificationService
|
|
) {}
|
|
|
|
async startScanning(): Promise<void> {
|
|
try {
|
|
await this.platformService.startCamera();
|
|
this.notificationService.show('Camera started');
|
|
} catch (error) {
|
|
this.notificationService.showError('Failed to start camera');
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
### Component Integration
|
|
|
|
```typescript
|
|
|
|
// components/QRScannerDialog.vue
|
|
export default class QRScannerDialog extends Vue {
|
|
@Inject() private qrScannerService!: QRScannerService;
|
|
|
|
async mounted() {
|
|
try {
|
|
await this.qrScannerService.startScanning();
|
|
} catch (error) {
|
|
this.$notify.error('Failed to start scanner');
|
|
}
|
|
}
|
|
|
|
beforeDestroy() {
|
|
this.qrScannerService.stopScanning();
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### Service Design
|
|
|
|
- Keep services focused and single-purpose
|
|
|
|
- Use dependency injection for service composition
|
|
|
|
- Implement proper error handling and logging
|
|
|
|
- Provide clear interfaces and contracts
|
|
|
|
### Testing Strategy
|
|
|
|
- Test platform-specific behavior separately
|
|
|
|
- Use mocks for external dependencies
|
|
|
|
- Test error conditions and edge cases
|
|
|
|
- Validate service contracts and interfaces
|
|
|
|
### Error Handling
|
|
|
|
- Log errors with appropriate context
|
|
|
|
- Provide user-friendly error messages
|
|
|
|
- Implement graceful degradation
|
|
|
|
- Handle platform-specific error scenarios
|
|
|
|
---
|
|
|
|
**See also**:
|
|
|
|
- `.cursor/rules/app/architectural_decision_record.mdc` for
|
|
|
|
core architecture principles
|
|
|
|
- `.cursor/rules/app/architectural_implementation.mdc` for
|
|
|
|
implementation details
|
|
|
|
- `.cursor/rules/app/architectural_patterns.mdc` for core patterns
|
|
|
|
**Status**: Active examples and testing guide
|
|
**Priority**: Medium
|
|
**Estimated Effort**: Ongoing reference
|
|
**Dependencies**: architectural_patterns.mdc
|
|
**Stakeholders**: Development team, Testing team
|
|
|
|
## Model Implementation Checklist
|
|
|
|
### Before Architectural Examples
|
|
|
|
- [ ] **Pattern Selection**: Choose appropriate architectural pattern for the use
|
|
case
|
|
- [ ] **Service Design**: Plan service structure and dependencies
|
|
- [ ] **Testing Strategy**: Plan testing approach for the example
|
|
- [ ] **Error Handling**: Plan error handling and logging strategy
|
|
|
|
### During Architectural Examples
|
|
|
|
- [ ] **Service Implementation**: Implement focused, single-purpose services
|
|
- [ ] **Dependency Injection**: Use proper dependency injection patterns
|
|
- [ ] **Error Handling**: Implement proper error handling and logging
|
|
- [ ] **Interface Design**: Provide clear interfaces and contracts
|
|
|
|
### After Architectural Examples
|
|
|
|
- [ ] **Testing Execution**: Test platform-specific behavior separately
|
|
- [ ] **Service Validation**: Validate service contracts and interfaces
|
|
- [ ] **Error Testing**: Test error conditions and edge cases
|
|
- [ ] **Documentation**: Update architectural examples documentation
|
|
|