Skip to content

Commit

Permalink
Add frontend changes to display event log
Browse files Browse the repository at this point in the history
  • Loading branch information
val500 committed Jul 9, 2024
1 parent 9267a78 commit 42d5d77
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class TestResultDTO(BaseModel):
"the last one is the oldest one."
),
)


class RerunRequest(BaseModel):
test_execution_ids: set[int]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@


@router.put("/{id}/status_update")
def put_status_update(id: int, request: StatusUpdateRequest, db: Session = Depends(get_db)):
def put_status_update(
id: int, request: StatusUpdateRequest, db: Session = Depends(get_db)
):
test_execution = db.get(
TestExecution,
id,
Expand Down
15 changes: 10 additions & 5 deletions backend/tests/controllers/test_executions/test_status_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test_status_updates_stored(test_client: TestClient, generator: DataGenerator
"event_name": "job_end",
"timestamp": "2015-03-21T11:08:15.859831",
"detail": "my_detail_three",
}
},
],
},
)
Expand All @@ -66,6 +66,7 @@ def test_status_updates_stored(test_client: TestClient, generator: DataGenerator
assert test_execution.test_events[1].detail == "my_detail_two"
assert test_execution.status == "ENDED"


def test_status_updates_is_idempotent(
test_client: TestClient, generator: DataGenerator
):
Expand Down Expand Up @@ -98,6 +99,7 @@ def test_status_updates_is_idempotent(
)
assert len(test_execution.test_events) == 2


def test_get_status_update(test_client: TestClient, generator: DataGenerator):
artefact = generator.gen_artefact("beta")
artefact_build = generator.gen_artefact_build(artefact)
Expand All @@ -106,7 +108,7 @@ def test_get_status_update(test_client: TestClient, generator: DataGenerator):
artefact_build, environment, ci_link="http://localhost"
)

response = test_client.put(
test_client.put(
f"/v1/test-executions/{test_execution.id}/status_update",
json={
"agent_id": "test_agent",
Expand All @@ -126,12 +128,14 @@ def test_get_status_update(test_client: TestClient, generator: DataGenerator):
"event_name": "job_end",
"timestamp": "2015-03-21T11:08:15.859831",
"detail": "my_detail_three",
}
},
],
},
)
get_response = test_client.get(f"/v1/test-executions/{test_execution.id}/status_update")

get_response = test_client.get(
f"/v1/test-executions/{test_execution.id}/status_update"
)

assert get_response.status_code == 200
json = get_response.json()
assert json[0]["event_name"] == "started_setup"
Expand All @@ -141,6 +145,7 @@ def test_get_status_update(test_client: TestClient, generator: DataGenerator):
assert json[1]["timestamp"] == "2015-03-21T11:08:15.859831"
assert json[1]["detail"] == "my_detail_two"


def test_status_updates_invalid_timestamp(
test_client: TestClient, generator: DataGenerator
):
Expand Down
19 changes: 19 additions & 0 deletions frontend/lib/models/test_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:yaru/yaru.dart';
import 'package:yaru_icons/yaru_icons.dart';

part 'test_event.freezed.dart';
part 'test_event.g.dart';

@freezed
class TestEvent with _$TestEvent {
const factory TestEvent({
@JsonKey(name: 'event_name') required String eventName,
required String timestamp,
required String detail,
}) = _TestEvent;

factory TestEvent.fromJson(Map<String, Object?> json) =>
_$TestEventFromJson(json);
}
9 changes: 8 additions & 1 deletion frontend/lib/models/test_execution.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,16 @@ enum TestExecutionStatus {
@JsonValue('IN_PROGRESS')
inProgress,
@JsonValue('PASSED')
passed;
passed,
@JsonValue('ENDED')
ended;

bool get isCompleted {
switch (this) {
case notStarted:
case inProgress:
case notTested:
case ended:
return false;
case passed:
case failed:
Expand All @@ -76,6 +79,8 @@ enum TestExecutionStatus {
return 'Failed';
case notTested:
return 'Not Tested';
case ended:
return 'Ended';
}
}

Expand All @@ -92,6 +97,8 @@ enum TestExecutionStatus {
return const Icon(YaruIcons.error, color: YaruColors.red, size: size);
case notTested:
return const Icon(YaruIcons.information, size: size);
case ended:
return const Icon(YaruIcons.error, color: YaruColors.red, size: size);
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions frontend/lib/providers/test_events.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../models/test_event.dart';
import 'api.dart';

part 'test_events.g.dart';

@riverpod
Future<List<TestEvent>> testEvents(
TestEventsRef ref,
int testExecutionId,
) async {
final api = ref.watch(apiProvider);
return await api.getTestExecutionEvents(testExecutionId);
}
12 changes: 12 additions & 0 deletions frontend/lib/repositories/api_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import '../models/family_name.dart';
import '../models/rerun_request.dart';
import '../models/test_execution.dart';
import '../models/test_result.dart';
import '../models/test_event.dart';

class ApiRepository {
final Dio dio;
Expand Down Expand Up @@ -66,6 +67,17 @@ class ApiRepository {
return testResults;
}

Future<List<TestEvent>> getTestExecutionEvents(int testExecutionId) async {
final response =
await dio.get('/v1/test-executions/$testExecutionId/status_update');
final List testEventsJson = response.data;
final testEvents =
testEventsJson.map((json) => TestEvent.fromJson(json)).toList();
print(testEvents);
return testEvents;
}


Future<List<RerunRequest>> rerunTestExecutions(
Set<int> testExecutionIds,
) async {
Expand Down
77 changes: 77 additions & 0 deletions frontend/lib/ui/artefact_page/test_event_log_expandable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'package:dartx/dartx.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:yaru/yaru.dart';
import 'package:yaru_widgets/yaru_widgets.dart';

import '../../models/test_event.dart';
import '../../providers/test_events.dart';
import '../spacing.dart';

class TestEventLogExpandable extends ConsumerWidget {
const TestEventLogExpandable({
super.key,
required this.testExecutionId,
required this.initiallyExpanded,
});

final int testExecutionId;
final bool initiallyExpanded;

@override
Widget build(BuildContext context, WidgetRef ref) {
final testEvents = ref.watch(testEventsProvider(testExecutionId));

return testEvents.when(
loading: () => const Center(child: YaruCircularProgressIndicator()),
error: (error, stackTrace) => Center(child: Text('Error: $error')),
data: (testEvents) {
return ExpansionTile(
controlAffinity: ListTileControlAffinity.leading,
childrenPadding: const EdgeInsets.only(left: Spacing.level4),
shape: const Border(),
title: Text('Event Log'),
initiallyExpanded: this.initiallyExpanded,
children: <Widget>[
DataTable(
columns: const <DataColumn>[
DataColumn(
label: Expanded(
child: Text(
'Event Name',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
),
DataColumn(
label: Expanded(
child: Text(
'Timestamp',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
),
DataColumn(
label: Expanded(
child: Text(
'Detail',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
),
],
rows: testEvents.map((testEvent) => DataRow(
cells: <DataCell>[
DataCell(Text(testEvent.eventName)),
DataCell(Text(testEvent.timestamp)),
DataCell(Text(testEvent.detail)),
],
))
.toList(),
),
],
);
}
);
}
}
21 changes: 18 additions & 3 deletions frontend/lib/ui/artefact_page/test_execution_expandable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import '../inline_url_text.dart';
import '../spacing.dart';
import 'test_execution_review.dart';
import 'test_result_filter_expandable.dart';
import 'test_event_log_expandable.dart';

class TestExecutionExpandable extends ConsumerWidget {
const TestExecutionExpandable({super.key, required this.testExecution});
Expand All @@ -19,10 +20,14 @@ class TestExecutionExpandable extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
if (!testExecution.status.isCompleted) {
return ListTile(
onTap: () {},
return ExpansionTile(
controlAffinity: ListTileControlAffinity.leading,
childrenPadding: const EdgeInsets.only(left: Spacing.level4),
shape: const Border(),
title: _TestExecutionTileTitle(testExecution: testExecution),
children: <Widget>[
TestEventLogExpandable(testExecutionId: testExecution.id, initiallyExpanded: true)
]
);
}

Expand All @@ -31,14 +36,24 @@ class TestExecutionExpandable extends ConsumerWidget {
childrenPadding: const EdgeInsets.only(left: Spacing.level4),
shape: const Border(),
title: _TestExecutionTileTitle(testExecution: testExecution),
children: TestResultStatus.values
children: <Widget>[
TestEventLogExpandable(testExecutionId: testExecution.id, initiallyExpanded: false),
ExpansionTile(
controlAffinity: ListTileControlAffinity.leading,
childrenPadding: const EdgeInsets.only(left: Spacing.level4),
shape: const Border(),
title: Text('Test Results'),
initiallyExpanded: true,
children: TestResultStatus.values
.map(
(status) => TestResultsFilterExpandable(
statusToFilterBy: status,
testExecutionId: testExecution.id,
),
)
.toList(),
),
]
);
}
}
Expand Down
12 changes: 6 additions & 6 deletions frontend/lib/ui/artefact_page/test_result_filter_expandable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class TestResultsFilterExpandable extends ConsumerWidget {
error: (error, stackTrace) => Center(child: Text('Error: $error')),
data: (testResults) {
final filteredTestResults = testResults
.filter((testResult) => testResult.status == statusToFilterBy)
.toList();
.filter((testResult) => testResult.status == statusToFilterBy)
.toList();

return ExpansionTile(
controlAffinity: ListTileControlAffinity.leading,
Expand All @@ -50,10 +50,10 @@ class TestResultsFilterExpandable extends ConsumerWidget {
style: headerStyle,
),
children: filteredTestResults
.map(
(testResult) => TestResultExpandable(testResult: testResult),
)
.toList(),
.map(
(testResult) => TestResultExpandable(testResult: testResult),
)
.toList(),
);
},
);
Expand Down
Loading

0 comments on commit 42d5d77

Please sign in to comment.