Skip to content

Commit ffbb3a0

Browse files
committed
test: add tests for GET /api/v1/auth/me
- Tests for 200 OK and 405 responses - Checks user data and metadata - Validates request_id presence
1 parent 258ed48 commit ffbb3a0

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

test/routes/api/v1/auth/me_test.dart

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import 'dart:convert';
2+
import 'dart:io';
3+
4+
import 'package:dart_frog/dart_frog.dart';
5+
import 'package:ht_shared/ht_shared.dart';
6+
import 'package:mocktail/mocktail.dart';
7+
import 'package:test/test.dart';
8+
9+
import '../../../../helpers/create_mock_request_context.dart';
10+
import '../../../../helpers/mock_classes.dart';
11+
// Import the actual route handler
12+
import '../../../../../routes/api/v1/auth/me.dart' as route;
13+
// Import RequestId definition from middleware file
14+
import '../../../../../routes/_middleware.dart' show RequestId;
15+
16+
17+
void main() {
18+
group('GET /api/v1/auth/me', () {
19+
late MockRequest mockRequest;
20+
21+
// Define a sample authenticated user
22+
final testUser = User(
23+
id: 'user-123',
24+
25+
isAnonymous: false,
26+
);
27+
const testRequestIdValue = 'req-abc-123';
28+
const testRequestId = RequestId(testRequestIdValue);
29+
30+
setUp(() {
31+
mockRequest = MockRequest();
32+
// Default stub for GET method
33+
when(() => mockRequest.method).thenReturn(HttpMethod.get);
34+
// Default stub for headers (authentication handled by middleware context)
35+
when(() => mockRequest.headers).thenReturn({});
36+
});
37+
38+
test('returns 200 OK with user data for authenticated user', () async {
39+
// Arrange
40+
// Expected success response payload (metadata timestamp will vary)
41+
final expectedPayload = SuccessApiResponse<User>(data: testUser);
42+
final expectedBody = jsonEncode(
43+
// We ignore metadata for direct comparison as timestamp varies
44+
expectedPayload.toJson((user) => user.toJson())
45+
..remove('metadata'),
46+
);
47+
48+
final context = createMockRequestContext(
49+
request: mockRequest,
50+
dependencies: {
51+
// Provide the authenticated user via context
52+
User: testUser,
53+
// Provide RequestId for metadata test
54+
RequestId: testRequestId,
55+
},
56+
);
57+
58+
// Act
59+
final response = await route.onRequest(context);
60+
final responseBody = await response.body();
61+
final decodedBody = jsonDecode(responseBody) as Map<String, dynamic>;
62+
63+
// Assert
64+
expect(response.statusCode, equals(HttpStatus.ok));
65+
// Compare data part only
66+
expect(decodedBody['data'], equals(jsonDecode(expectedBody)['data']));
67+
expect(
68+
response.headers[HttpHeaders.contentTypeHeader],
69+
equals('application/json'),
70+
);
71+
// Check metadata structure and requestId presence
72+
expect(decodedBody['metadata'], isA<Map<String, dynamic>>());
73+
expect(decodedBody['metadata']?['request_id'], equals(testRequestIdValue));
74+
expect(decodedBody['metadata']?['timestamp'], isNotNull);
75+
});
76+
77+
test('returns 200 OK with user data when RequestId is not in context', () async {
78+
// Arrange
79+
// Expected success response payload (metadata timestamp will vary)
80+
final expectedPayload = SuccessApiResponse<User>(data: testUser);
81+
final expectedBody = jsonEncode(
82+
// We ignore metadata for direct comparison as timestamp varies
83+
expectedPayload.toJson((user) => user.toJson())
84+
..remove('metadata'),
85+
);
86+
87+
final context = createMockRequestContext(
88+
request: mockRequest,
89+
dependencies: {
90+
// Provide the authenticated user via context
91+
User: testUser,
92+
// DO NOT provide RequestId
93+
},
94+
);
95+
96+
// Act
97+
final response = await route.onRequest(context);
98+
final responseBody = await response.body();
99+
final decodedBody = jsonDecode(responseBody) as Map<String, dynamic>;
100+
101+
// Assert
102+
expect(response.statusCode, equals(HttpStatus.ok));
103+
// Compare data part only
104+
expect(decodedBody['data'], equals(jsonDecode(expectedBody)['data']));
105+
expect(
106+
response.headers[HttpHeaders.contentTypeHeader],
107+
equals('application/json'),
108+
);
109+
// Check metadata structure and requestId absence/null
110+
expect(decodedBody['metadata'], isA<Map<String, dynamic>>());
111+
expect(decodedBody['metadata']?['request_id'], isNull); // Should be null
112+
expect(decodedBody['metadata']?['timestamp'], isNotNull);
113+
});
114+
115+
116+
test('returns 405 Method Not Allowed for non-GET requests', () async {
117+
// Arrange
118+
when(() => mockRequest.method).thenReturn(HttpMethod.post); // Test POST
119+
final context = createMockRequestContext(
120+
request: mockRequest,
121+
dependencies: {
122+
User: testUser, // User presence doesn't matter for method check
123+
},
124+
);
125+
126+
// Act
127+
final response = await route.onRequest(context);
128+
129+
// Assert
130+
expect(response.statusCode, equals(HttpStatus.methodNotAllowed));
131+
});
132+
133+
test('throws UnauthorizedException if user is null in context (safeguard)',
134+
() async {
135+
// Arrange
136+
// This scenario assumes the requireAuthentication middleware somehow failed
137+
// or wasn't applied, letting the request reach the handler without a user.
138+
final context = createMockRequestContext(
139+
request: mockRequest,
140+
dependencies: {
141+
// Explicitly provide null User
142+
User: null,
143+
},
144+
);
145+
146+
// Act & Assert
147+
// Expect the handler to throw the exception, letting middleware handle it
148+
expect(
149+
() => route.onRequest(context),
150+
throwsA(isA<UnauthorizedException>()),
151+
);
152+
// Note: The final 401 response format is tested in error handler tests.
153+
});
154+
});
155+
}

0 commit comments

Comments
 (0)