Skip to content

Commit e42e08d

Browse files
Convert test details page backend to GraphQL (#3662)
This PR adds all the missing pieces required to render the test details page based on data obtained via the GraphQL API, and switches the page to use them. While this page also desperately needs some UI improvements, the goal of this PR is simply to move away from the legacy API endpoint. I'll follow up with a separate PR containing UI improvements.
1 parent 5466ddc commit e42e08d

12 files changed

Lines changed: 544 additions & 91 deletions

File tree

app/Http/Controllers/TestDetailsController.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public function details(int $id): View
3030
return $this->vue('test-details-page', 'Test Results', [
3131
'build-id' => $this->build->Id,
3232
'test-id' => $test->id,
33+
'testing-day' => $this->date,
3334
])
3435
->with('previousUrl', $previousTest?->GetUrlForSelf())
3536
->with('latestUrl', $latestTest?->GetUrlForSelf())

app/Models/TestImage.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Models;
44

55
use Illuminate\Database\Eloquent\Builder;
6+
use Illuminate\Database\Eloquent\Casts\Attribute;
67
use Illuminate\Database\Eloquent\Model;
78
use Illuminate\Database\Eloquent\Relations\BelongsTo;
89

@@ -47,4 +48,20 @@ public function image(): BelongsTo
4748
{
4849
return $this->belongsTo(Image::class, 'imgid');
4950
}
51+
52+
/**
53+
* @return Attribute<?string,void>
54+
*/
55+
protected function url(): Attribute
56+
{
57+
return Attribute::make(
58+
get: function (mixed $value, array $attributes): ?string {
59+
if ($attributes['imgid'] === null || (int) $attributes['imgid'] === 0) {
60+
return null;
61+
}
62+
63+
return url('/image/' . $attributes['imgid']);
64+
},
65+
);
66+
}
5067
}

app/Policies/TestPolicy.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace App\Policies;
4+
5+
use App\Models\Test;
6+
use App\Models\User;
7+
use Illuminate\Support\Facades\Gate;
8+
9+
class TestPolicy
10+
{
11+
public function view(?User $user, Test $test): bool
12+
{
13+
return Gate::check('view', $test->build);
14+
}
15+
}

app/cdash/tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ add_feature_test_in_transaction(/Feature/GraphQL/ConfigureTypeTest)
208208

209209
add_feature_test_in_transaction(/Feature/GraphQL/TestTypeTest)
210210

211+
add_feature_test_in_transaction(/Feature/GraphQL/TestImageTypeTest)
212+
211213
add_feature_test_in_transaction(/Feature/GraphQL/TestMeasurementTypeTest)
212214

213215
add_feature_test_in_transaction(/Feature/GraphQL/NoteTypeTest)

graphql/schema.graphql

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ type Query {
5151
id: ID @eq
5252
): Build @find @canResolved(ability: "view")
5353

54+
"Find a single test by ID."
55+
test(
56+
"Search by primary key."
57+
id: ID @eq
58+
): Test @find @canResolved(ability: "view", action: RETURN_VALUE, returnValue: null)
59+
5460
"""
5561
Find a single site by ID. All sites are currently public (although not necessarily
5662
the projects they contribute to). In the future, the concept of "private sites"
@@ -930,6 +936,12 @@ type Test {
930936

931937
runningTime: NonNegativeSeconds! @rename(attribute: "time") @filterable
932938

939+
"The average of recent running times for this test"
940+
meanRunningTime: NonNegativeSeconds! @rename(attribute: "timemean") @filterable
941+
942+
"The standard deviation of recent running times for this test"
943+
stdDevRunningTime: Float! @rename(attribute: "timestd") @filterable
944+
933945
startTime: DateTimeTz @rename(attribute: "starttime") @filterable
934946

935947
details: String! @filterable
@@ -944,6 +956,10 @@ type Test {
944956
filters: _ @filter
945957
): [TestMeasurement!]! @hasMany @orderBy(column: "id", direction: DESC)
946958

959+
testImages(
960+
filters: _ @filter
961+
): [TestImage!]! @hasMany(type: CONNECTION) @orderBy(column: "id", direction: DESC)
962+
947963
labels(
948964
filters: _ @filter
949965
): [Label!]! @belongsToMany(type: CONNECTION) @orderBy(column: "id", direction: DESC)
@@ -984,6 +1000,17 @@ type TestMeasurement {
9841000
}
9851001

9861002

1003+
"Test Measurement."
1004+
type TestImage {
1005+
"Unique primary key."
1006+
id: ID!
1007+
1008+
role: String! @filterable
1009+
1010+
url: String
1011+
}
1012+
1013+
9871014
"""
9881015
Represents a command run during the build step.
9891016

phpstan-baseline.neon

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5043,6 +5043,18 @@ parameters:
50435043
count: 1
50445044
path: app/Models/Test.php
50455045

5046+
-
5047+
rawMessage: Binary operation "." between '/image/' and mixed results in an error.
5048+
identifier: binaryOp.invalid
5049+
count: 1
5050+
path: app/Models/TestImage.php
5051+
5052+
-
5053+
rawMessage: Cannot cast mixed to int.
5054+
identifier: cast.int
5055+
count: 1
5056+
path: app/Models/TestImage.php
5057+
50465058
-
50475059
rawMessage: '''
50485060
Call to deprecated method forceRootUrl() of class Illuminate\Routing\UrlGenerator:

0 commit comments

Comments
 (0)