Skip to content

Commit c9f4570

Browse files
committed
Add special union type handling
1 parent 76eb54c commit c9f4570

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed

relationship_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,17 @@ func TestRelationshipDefinitionDelete(t *testing.T) {
147147
func TestGetRelationship(t *testing.T) {
148148
// Arrange
149149
testRequest := autopilot.NewTestRequest(
150-
`query RelationshipGet($input:ID!){account{relationship(id: $input){id,source{... on Domain{id,aliases},... on InfrastructureResource{id,aliases,name},... on Service{id,aliases},... on System{id,aliases},... on Team{alias,id}},target{... on Domain{id,aliases},... on InfrastructureResource{id,aliases,name},... on Service{id,aliases},... on System{id,aliases},... on Team{alias,id}},type}}}`,
150+
`query RelationshipGet($input:ID!){account{relationship(id: $input){id,source{__typename,... on Domain{id,aliases},... on InfrastructureResource{id,aliases,name},... on Service{id,aliases},... on System{id,aliases},... on Team{alias,id}},target{__typename,... on Domain{id,aliases},... on InfrastructureResource{id,aliases,name},... on Service{id,aliases},... on System{id,aliases},... on Team{alias,id}},type}}}`,
151151
`{"input": "{{ template "id1_string" }}" }`,
152152
`{"data": {"account": {"relationship": {
153153
"id": "{{ template "id1_string" }}",
154154
"source": {
155+
"__typename": "Domain",
155156
"id": "{{ template "id2_string" }}",
156157
"aliases": ["source-alias"]
157158
},
158159
"target": {
160+
"__typename": "System",
159161
"id": "{{ template "id3_string" }}",
160162
"aliases": ["target-alias"]
161163
},
@@ -170,6 +172,8 @@ func TestGetRelationship(t *testing.T) {
170172
autopilot.Ok(t, err)
171173
autopilot.Equals(t, id1, result.Id)
172174
autopilot.Equals(t, id2, result.Source.Domain.Id)
173-
autopilot.Equals(t, id3, result.Target.Domain.Id)
175+
autopilot.Equals(t, ol.ID(""), result.Source.System.Id)
176+
autopilot.Equals(t, ol.ID(""), result.Target.Domain.Id)
177+
autopilot.Equals(t, id3, result.Target.System.Id)
174178
autopilot.Equals(t, ol.RelationshipTypeEnumBelongsTo, result.Type)
175179
}

union.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

union_type.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package opslevel
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
)
7+
8+
// TypeIdentifier represents a GraphQL __typename that can be used to identify the concrete type of an union response
9+
type TypeIdentifier string
10+
11+
func (r *RelationshipResource) MarshalJSON() ([]byte, error) {
12+
switch r.Type {
13+
case "Domain":
14+
return json.Marshal(r.Domain)
15+
case "Infrastructure":
16+
return json.Marshal(r.InfrastructureResource)
17+
case "Service":
18+
return json.Marshal(r.Service)
19+
case "System":
20+
return json.Marshal(r.System)
21+
case "Team":
22+
return json.Marshal(r.Team)
23+
default:
24+
return nil, fmt.Errorf("unknown type: %s", r.Type)
25+
}
26+
}
27+
28+
// UnmarshalJSON implements custom JSON unmarshaling for RelationshipResource to support the union type
29+
func (r *RelationshipResource) UnmarshalJSON(data []byte) error {
30+
// First unmarshal to get the type
31+
var tmp struct {
32+
Type TypeIdentifier `json:"__typename"`
33+
}
34+
if err := json.Unmarshal(data, &tmp); err != nil {
35+
return fmt.Errorf("failed to unmarshal type: %w", err)
36+
}
37+
r.Type = tmp.Type
38+
39+
// Then unmarshal the specific type
40+
switch string(r.Type) {
41+
case "Domain":
42+
if err := json.Unmarshal(data, &r.Domain); err != nil {
43+
return fmt.Errorf("failed to unmarshal Domain: %w", err)
44+
}
45+
case "Infrastructure":
46+
if err := json.Unmarshal(data, &r.InfrastructureResource); err != nil {
47+
return fmt.Errorf("failed to unmarshal Infrastructure Resource: %w", err)
48+
}
49+
case "Service":
50+
if err := json.Unmarshal(data, &r.Service); err != nil {
51+
return fmt.Errorf("failed to unmarshal Service: %w", err)
52+
}
53+
case "System":
54+
if err := json.Unmarshal(data, &r.System); err != nil {
55+
return fmt.Errorf("failed to unmarshal System: %w", err)
56+
}
57+
case "Team":
58+
if err := json.Unmarshal(data, &r.Team); err != nil {
59+
return fmt.Errorf("failed to unmarshal Team: %w", err)
60+
}
61+
default:
62+
return fmt.Errorf("unknown resource type: %s", r.Type)
63+
}
64+
return nil
65+
}

union_type_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package opslevel_test
2+
3+
import (
4+
"encoding/json"
5+
ol "github.com/opslevel/opslevel-go/v2025"
6+
"github.com/rocktavious/autopilot/v2023"
7+
"testing"
8+
)
9+
10+
func TestRelationshipResourceUnmarshalJSON(t *testing.T) {
11+
// Arrange
12+
testCases := []struct {
13+
name string
14+
input string
15+
expected ol.RelationshipResource
16+
}{
17+
{
18+
name: "Domain resource",
19+
input: `{"__typename": "Domain", "id": "Z2lkOi8vb3BzbGV2ZWwvRG9tYWluLzE"}`,
20+
expected: ol.RelationshipResource{
21+
Type: ol.TypeIdentifier("Domain"),
22+
Domain: ol.DomainId{
23+
Id: "Z2lkOi8vb3BzbGV2ZWwvRG9tYWluLzE",
24+
},
25+
},
26+
},
27+
{
28+
name: "Service resource",
29+
input: `{"__typename": "Service", "id": "Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8x"}`,
30+
expected: ol.RelationshipResource{
31+
Type: ol.TypeIdentifier("Service"),
32+
Service: ol.ServiceId{
33+
Id: ol.ID("Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8x"),
34+
},
35+
},
36+
},
37+
}
38+
39+
for _, tc := range testCases {
40+
t.Run(tc.name, func(t *testing.T) {
41+
// Act
42+
var result ol.RelationshipResource
43+
err := json.Unmarshal([]byte(tc.input), &result)
44+
45+
// Assert
46+
autopilot.Ok(t, err)
47+
autopilot.Equals(t, tc.expected.Type, result.Type)
48+
switch tc.expected.Type {
49+
case "Domain":
50+
autopilot.Equals(t, tc.expected.Domain, result.Domain)
51+
case "Service":
52+
autopilot.Equals(t, tc.expected.Service.Id, result.Service.Id)
53+
}
54+
})
55+
}
56+
}

0 commit comments

Comments
 (0)