/** * Property-based tests for authentication handling * **Feature: miniapp-frontend, Property 2: Auth Redirect on Invalid Token** * **Validates: Requirements 1.4** */ import { describe, it, expect, beforeEach } from 'vitest' import * as fc from 'fast-check' // Import mock before other modules import '../mocks/uni.js' import { setToken, getToken } from '../../utils/storage.js' import { handleUnauthorized } from '../../api/request.js' describe('Auth Property Tests', () => { beforeEach(() => { // Clear storage and reset redirect state before each test uni._clearStorage() uni._resetRedirectState() }) /** * Property 2: Auth Redirect on Invalid Token * *For any* API response with 401 status code, the application SHALL * clear the stored token. * Note: Redirect is handled by the caller, not handleUnauthorized itself * **Validates: Requirements 1.4** */ it('Property 2: Auth Redirect on Invalid Token - 401 should clear token', () => { fc.assert( fc.property( // Generate any token that might be stored fc.string({ minLength: 1 }).filter(s => s.trim().length > 0), (token) => { // Setup: Store a token (simulating logged-in state) setToken(token) // Verify token is stored const storedToken = getToken() if (storedToken !== token) return false // Action: Handle unauthorized (simulating 401 response) handleUnauthorized() // Verify: Token should be cleared const tokenAfterUnauth = getToken() const tokenCleared = tokenAfterUnauth === '' // Reset for next iteration uni._clearStorage() return tokenCleared } ), { numRuns: 100 } ) }) /** * Property: handleUnauthorized should be idempotent * Calling it multiple times should have the same effect as calling once */ it('handleUnauthorized should be idempotent', () => { fc.assert( fc.property( fc.string({ minLength: 1 }).filter(s => s.trim().length > 0), fc.integer({ min: 1, max: 5 }), (token, callCount) => { // Setup setToken(token) // Call handleUnauthorized multiple times for (let i = 0; i < callCount; i++) { handleUnauthorized() } // Token should still be cleared const tokenAfter = getToken() const tokenCleared = tokenAfter === '' // Cleanup uni._clearStorage() return tokenCleared } ), { numRuns: 100 } ) }) })