Initialized Claude COde and let it fix some test stuff
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:ac_web/Api/Api.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
|
||||
const ApiConfig testConfig = ApiConfig(host: 'api.local', port: 5000, basePath: 'api');
|
||||
|
||||
AcApi apiReturning(String body, {int statusCode = 200, void Function(Uri uri)? onRequest}) {
|
||||
final client = MockClient((request) async {
|
||||
onRequest?.call(request.url);
|
||||
return http.Response(body, statusCode, headers: {'content-type': 'application/json'});
|
||||
});
|
||||
return AcApi(config: testConfig, httpClient: client);
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('ApiConfig', () {
|
||||
test('builds http uris including base path and query', () {
|
||||
final uri = testConfig.buildUri('agents', {'onlyOnline': true, 'skip': null});
|
||||
|
||||
expect(uri.toString(), 'http://api.local:5000/api/agents?onlyOnline=true');
|
||||
});
|
||||
});
|
||||
|
||||
group('AgentsService', () {
|
||||
test('parses agents with enums as names and nested tasks', () async {
|
||||
Uri? requested;
|
||||
final api = apiReturning(
|
||||
jsonEncode([
|
||||
{
|
||||
'name': 'Ada',
|
||||
'type': 'CODER',
|
||||
'lastSeen': '2026-08-28T12:00:00Z',
|
||||
'status': 'WORKING',
|
||||
'tasks': [
|
||||
{
|
||||
'title': 'Implement api layer',
|
||||
'startTime': '2026-08-28T11:00:00Z',
|
||||
'statusUpdates': ['Started', 'Half way through'],
|
||||
},
|
||||
],
|
||||
},
|
||||
]),
|
||||
onRequest: (uri) => requested = uri,
|
||||
);
|
||||
|
||||
final agents = await api.agents.getAgents();
|
||||
|
||||
expect(requested.toString(), 'http://api.local:5000/api/agents');
|
||||
expect(agents, hasLength(1));
|
||||
expect(agents.single.name, 'Ada');
|
||||
expect(agents.single.type, EAgentType.coder);
|
||||
expect(agents.single.status, EAgentStatus.working);
|
||||
expect(agents.single.lastSeen.isUtc, isTrue);
|
||||
expect(agents.single.tasks.single.title, 'Implement api layer');
|
||||
expect(agents.single.tasks.single.startTime, DateTime.utc(2026, 8, 28, 11));
|
||||
expect(agents.single.tasks.single.statusUpdates, ['Started', 'Half way through']);
|
||||
expect(agents.single.tasks.single.latestStatus, 'Half way through');
|
||||
});
|
||||
|
||||
test('parses numeric enums and falls back to unknown', () async {
|
||||
final api = apiReturning(
|
||||
jsonEncode([
|
||||
{
|
||||
'Name': 'Numeric',
|
||||
'Type': 1,
|
||||
'LastSeen': '2026-08-28T12:00:00Z',
|
||||
'Status': 2,
|
||||
'Tasks': [],
|
||||
},
|
||||
{
|
||||
'Name': 'Future',
|
||||
'Type': 'SomethingNew',
|
||||
'LastSeen': '2026-08-28T12:00:00Z',
|
||||
'Status': 'AlsoNew',
|
||||
'Tasks': [],
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
final agents = await api.agents.getAgents();
|
||||
|
||||
expect(agents.first.type, EAgentType.logAnalyzer);
|
||||
expect(agents.first.status, EAgentStatus.offline);
|
||||
expect(agents.first.tasks, isEmpty);
|
||||
expect(agents.last.type, EAgentType.unknown);
|
||||
expect(agents.last.status, EAgentStatus.unknown);
|
||||
});
|
||||
|
||||
test('throws ApiParsingException on a malformed payload', () async {
|
||||
final api = apiReturning(jsonEncode([{'Type': 'CODER'}]));
|
||||
|
||||
expect(() => api.agents.getAgents(), throwsA(isA<ApiParsingException>()));
|
||||
});
|
||||
});
|
||||
|
||||
group('ReportsService', () {
|
||||
test('returns reports sorted newest first', () async {
|
||||
final api = apiReturning(
|
||||
jsonEncode([
|
||||
{
|
||||
'Id': 'older',
|
||||
'Author': 'Ada',
|
||||
'Timestamp': '2026-08-20T10:00:00Z',
|
||||
'Type': 'LOG',
|
||||
'Text': 'first',
|
||||
},
|
||||
{
|
||||
'Id': 'newer',
|
||||
'Author': 'Grace',
|
||||
'Timestamp': '2026-08-27T10:00:00Z',
|
||||
'Type': 'CODE_REVIEW',
|
||||
'Text': 'second',
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
final reports = await api.reports.getReports();
|
||||
|
||||
expect(reports.map((report) => report.id), ['newer', 'older']);
|
||||
expect(reports.first.author, 'Grace');
|
||||
expect(reports.first.type, EReportType.codeReview);
|
||||
});
|
||||
|
||||
test('maps error status codes onto ApiHttpException', () async {
|
||||
final api = apiReturning('{"error":"boom"}', statusCode: 500);
|
||||
|
||||
await expectLater(
|
||||
api.reports.getReports(),
|
||||
throwsA(isA<ApiHttpException>().having((error) => error.isServerError, 'isServerError', isTrue)),
|
||||
);
|
||||
});
|
||||
|
||||
test('maps transport failures onto ApiNetworkException', () async {
|
||||
final api = AcApi(
|
||||
config: testConfig,
|
||||
httpClient: MockClient((request) async => throw http.ClientException('offline')),
|
||||
);
|
||||
|
||||
await expectLater(api.reports.getReports(), throwsA(isA<ApiNetworkException>()));
|
||||
});
|
||||
|
||||
test('treats an empty body as an empty list', () async {
|
||||
final api = apiReturning('', statusCode: 204);
|
||||
|
||||
expect(await api.reports.getReports(), isEmpty);
|
||||
});
|
||||
});
|
||||
|
||||
group('Dto round trip', () {
|
||||
test('agent survives toJson/fromJson', () {
|
||||
final original = AgentDto(
|
||||
name: 'Ada',
|
||||
type: EAgentType.securityAnalyst,
|
||||
lastSeen: DateTime.utc(2026, 8, 28, 12),
|
||||
tasks: [
|
||||
AgentTaskDto(
|
||||
title: 'Review',
|
||||
startTime: DateTime.utc(2026, 8, 28, 11),
|
||||
statusUpdates: const ['Open'],
|
||||
),
|
||||
],
|
||||
status: EAgentStatus.available,
|
||||
);
|
||||
|
||||
final restored = AgentDto.fromJson(original.toJson());
|
||||
|
||||
expect(restored.name, original.name);
|
||||
expect(restored.type, original.type);
|
||||
expect(restored.status, original.status);
|
||||
expect(restored.lastSeen, original.lastSeen);
|
||||
expect(restored.tasks.single.title, 'Review');
|
||||
expect(restored.tasks.single.startTime, DateTime.utc(2026, 8, 28, 11));
|
||||
expect(restored.tasks.single.statusUpdates, ['Open']);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user