Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions codegen/internal/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,10 @@ func (g *Generator) resolveInlineSchemaType(schemaRef *base.SchemaProxy, require
if schema == nil {
return g.nullableType("JsonDocument", false, required), nil
}
if len(schema.Enum) > 0 {
typeName := g.createInlineEnum(inlineBase, schema)
return g.nullableType(typeName, true, required), nil
}
if schemaDefinesStructuredObject(schema) {
typeName, err := g.createInlineModel(inlineBase, schema)
if err != nil {
Expand Down Expand Up @@ -864,6 +868,19 @@ func (g *Generator) createInlineModel(baseName string, schema *base.Schema) (str
return typeName, nil
}

func (g *Generator) createInlineEnum(baseName string, schema *base.Schema) string {
typeName := g.reserveModelName(baseName)
g.inlineModels = append(g.inlineModels, modelTemplateData{
Namespace: g.config.Namespace,
Name: typeName,
Description: sanitizeText(schema.Description),
Kind: schemaKindEnum,
EnumValues: g.buildEnumValues(schema),
UsesCollections: false,
})
return typeName
}

func (g *Generator) reserveModelName(base string) string {
name := base
index := 2
Expand Down
120 changes: 120 additions & 0 deletions codegen/internal/generator/generator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package generator

import (
"testing"

"github.com/pb33f/libopenapi"
v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
)

func TestBuildModels_GeneratesInlineEnumForLinksRelation(t *testing.T) {
const spec = `{
"openapi": "3.0.3",
"info": {
"title": "test",
"version": "1.0.0"
},
"paths": {},
"components": {
"schemas": {
"TransactionsListResponse": {
"type": "object",
"properties": {
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rel": {
"type": "string",
"enum": ["next", "previous"]
},
"href": {
"type": "string"
}
},
"required": ["rel", "href"]
}
}
}
}
}
}
}`

doc := mustBuildV3Document(t, spec)

g := New(Config{Namespace: "SumUp"})
models, err := g.buildModels(doc)
if err != nil {
t.Fatalf("buildModels() error = %v", err)
}

if len(models) != 1 {
t.Fatalf("buildModels() returned %d top-level models, want 1", len(models))
}

response := models[0]
if response.Name != "TransactionsListResponse" {
t.Fatalf("top-level model name = %q, want %q", response.Name, "TransactionsListResponse")
}

if got := propertyType(response.Properties, "Links"); got != "IEnumerable<TransactionsListResponseLinksItem>?" {
t.Fatalf("Links property type = %q, want %q", got, "IEnumerable<TransactionsListResponseLinksItem>?")
}

linkItem := findModel(t, g.inlineModels, "TransactionsListResponseLinksItem")
if got := propertyType(linkItem.Properties, "Rel"); got != "TransactionsListResponseLinksItemRel" {
t.Fatalf("Rel property type = %q, want %q", got, "TransactionsListResponseLinksItemRel")
}

relEnum := findModel(t, g.inlineModels, "TransactionsListResponseLinksItemRel")
if relEnum.Kind != schemaKindEnum {
t.Fatalf("inline rel model kind = %v, want enum", relEnum.Kind)
}
if len(relEnum.EnumValues) != 2 {
t.Fatalf("inline rel enum values = %d, want 2", len(relEnum.EnumValues))
}
if relEnum.EnumValues[0].Value != "next" || relEnum.EnumValues[1].Value != "previous" {
t.Fatalf("inline rel enum values = %#v, want next/previous", relEnum.EnumValues)
}
}

func mustBuildV3Document(t *testing.T, raw string) *v3.Document {
t.Helper()

document, err := libopenapi.NewDocument([]byte(raw))
if err != nil {
t.Fatalf("NewDocument() error = %v", err)
}

model, err := document.BuildV3Model()
if err != nil {
t.Fatalf("BuildV3Model() error = %v", err)
}

return &model.Model
}

func findModel(t *testing.T, models []modelTemplateData, name string) modelTemplateData {
t.Helper()

for _, model := range models {
if model.Name == name {
return model
}
}

t.Fatalf("model %q not found", name)
return modelTemplateData{}
}

func propertyType(properties []modelPropertyTemplateData, name string) string {
for _, property := range properties {
if property.PropertyName == name {
return property.TypeName
}
}

return ""
}
6 changes: 3 additions & 3 deletions src/SumUp.Tests/ReadersClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ public async Task GetStatusAsync_SendsProperRequestAndParsesResponse()
var statusData = statusResponse.Data!;
Assert.Equal(82.5f, statusData.BatteryLevel);
Assert.Equal(29, statusData.BatteryTemperature);
Assert.Equal("wifi", statusData.ConnectionType);
Assert.Equal(StatusResponseDataConnectionType.WiFi, statusData.ConnectionType);
Assert.Equal("3.3.40", statusData.FirmwareVersion);
var expectedLastActivity = DateTimeOffset.Parse("2024-05-23T13:45:00+00:00", CultureInfo.InvariantCulture);
Assert.Equal(expectedLastActivity, statusData.LastActivity);
Assert.Equal("WAITING_FOR_CARD", statusData.State);
Assert.Equal("ONLINE", statusData.Status);
Assert.Equal(StatusResponseDataState.WaitingForCard, statusData.State);
Assert.Equal(StatusResponseDataStatus.Online, statusData.Status);
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion src/SumUp/Models/BadRequestErrors.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public sealed partial class BadRequestErrors
public string? Detail { get; set; }
/// <summary>Key indicating type of error</summary>
[JsonPropertyName("type")]
public string Type { get; set; } = default!;
public BadRequestErrorsType Type { get; set; }
}
20 changes: 20 additions & 0 deletions src/SumUp/Models/BadRequestErrorsType.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// <auto-generated />
#nullable enable

namespace SumUp;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;

[JsonConverter(typeof(EnumMemberJsonConverterFactory))]
public enum BadRequestErrorsType
{
[EnumMember(Value = "INVALID_BEARER_TOKEN")]
InvalidBearerToken,
[EnumMember(Value = "INVALID_USER_AGENT")]
InvalidUserAgent,
[EnumMember(Value = "NOT_ENOUGH_UNPAID_PAYOUTS")]
NotEnoughUnpaidPayouts,
[EnumMember(Value = "DUPLICATE_HEADERS")]
DuplicateHeaders,
}
6 changes: 3 additions & 3 deletions src/SumUp/Models/BankAccountPayload.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public sealed partial class BankAccountPayload
{
/// <summary>Determines if this bank account is business or personal.</summary>
[JsonPropertyName("account_category")]
public string? AccountCategory { get; set; }
public BankAccountPayloadAccountCategory? AccountCategory { get; set; }
/// <summary>Account holder name</summary>
[JsonPropertyName("account_holder_name")]
public string AccountHolderName { get; set; } = default!;
Expand All @@ -18,7 +18,7 @@ public sealed partial class BankAccountPayload
public string? AccountNumber { get; set; }
/// <summary>Type of the account.</summary>
[JsonPropertyName("account_type")]
public string? AccountType { get; set; }
public BankAccountPayloadAccountType? AccountType { get; set; }
/// <summary>Bank code</summary>
[JsonPropertyName("bank_code")]
public string? BankCode { get; set; }
Expand All @@ -36,7 +36,7 @@ public sealed partial class BankAccountPayload
public bool? Primary { get; set; }
/// <summary>Determines the bank account status.</summary>
[JsonPropertyName("status")]
public string? Status { get; set; }
public BankAccountPayloadStatus? Status { get; set; }
/// <summary>SWIFT code</summary>
[JsonPropertyName("swift")]
public string Swift { get; set; } = default!;
Expand Down
16 changes: 16 additions & 0 deletions src/SumUp/Models/BankAccountPayloadAccountCategory.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// <auto-generated />
#nullable enable

namespace SumUp;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;

[JsonConverter(typeof(EnumMemberJsonConverterFactory))]
public enum BankAccountPayloadAccountCategory
{
[EnumMember(Value = "PERSONAL")]
Personal,
[EnumMember(Value = "BUSINESS")]
Business,
}
16 changes: 16 additions & 0 deletions src/SumUp/Models/BankAccountPayloadAccountType.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// <auto-generated />
#nullable enable

namespace SumUp;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;

[JsonConverter(typeof(EnumMemberJsonConverterFactory))]
public enum BankAccountPayloadAccountType
{
[EnumMember(Value = "CURRENT")]
Current,
[EnumMember(Value = "SAVINGS")]
Savings,
}
14 changes: 14 additions & 0 deletions src/SumUp/Models/BankAccountPayloadStatus.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// <auto-generated />
#nullable enable

namespace SumUp;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;

[JsonConverter(typeof(EnumMemberJsonConverterFactory))]
public enum BankAccountPayloadStatus
{
[EnumMember(Value = "OPEN")]
Open,
}
2 changes: 1 addition & 1 deletion src/SumUp/Models/Card.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public sealed partial class Card
public string Cvv { get; set; } = default!;
/// <summary>Month from the expiration time of the payment card. Accepted format is `MM`.</summary>
[JsonPropertyName("expiry_month")]
public string ExpiryMonth { get; set; } = default!;
public CardExpiryMonth ExpiryMonth { get; set; }
/// <summary>Year from the expiration time of the payment card. Accepted formats are `YY` and `YYYY`.</summary>
[JsonPropertyName("expiry_year")]
public string ExpiryYear { get; set; } = default!;
Expand Down
36 changes: 36 additions & 0 deletions src/SumUp/Models/CardExpiryMonth.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// <auto-generated />
#nullable enable

namespace SumUp;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;

[JsonConverter(typeof(EnumMemberJsonConverterFactory))]
public enum CardExpiryMonth
{
[EnumMember(Value = "01")]
_01,
[EnumMember(Value = "02")]
_02,
[EnumMember(Value = "03")]
_03,
[EnumMember(Value = "04")]
_04,
[EnumMember(Value = "05")]
_05,
[EnumMember(Value = "06")]
_06,
[EnumMember(Value = "07")]
_07,
[EnumMember(Value = "08")]
_08,
[EnumMember(Value = "09")]
_09,
[EnumMember(Value = "10")]
_10,
[EnumMember(Value = "11")]
_11,
[EnumMember(Value = "12")]
_12,
}
2 changes: 1 addition & 1 deletion src/SumUp/Models/Checkout.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public sealed partial class Checkout
public string? ReturnUrl { get; set; }
/// <summary>Current status of the checkout.</summary>
[JsonPropertyName("status")]
public string? Status { get; set; }
public CheckoutStatus? Status { get; set; }
/// <summary>List of transactions related to the payment.</summary>
[JsonPropertyName("transactions")]
public IEnumerable<CheckoutTransactionsItem>? Transactions { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/SumUp/Models/CheckoutAcceptedNextStep.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public sealed partial class CheckoutAcceptedNextStep
{
/// <summary>Indicates allowed mechanisms for redirecting an end user. If both values are provided to ensure a redirect takes place in either.</summary>
[JsonPropertyName("mechanism")]
public IEnumerable<string>? Mechanism { get; set; }
public IEnumerable<CheckoutAcceptedNextStepMechanismItem>? Mechanism { get; set; }
/// <summary>Method used to complete the redirect.</summary>
[JsonPropertyName("method")]
public string? Method { get; set; }
Expand Down
16 changes: 16 additions & 0 deletions src/SumUp/Models/CheckoutAcceptedNextStepMechanismItem.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// <auto-generated />
#nullable enable

namespace SumUp;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;

[JsonConverter(typeof(EnumMemberJsonConverterFactory))]
public enum CheckoutAcceptedNextStepMechanismItem
{
[EnumMember(Value = "iframe")]
Iframe,
[EnumMember(Value = "browser")]
Browser,
}
2 changes: 1 addition & 1 deletion src/SumUp/Models/CheckoutCreateRequest.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public sealed partial class CheckoutCreateRequest
public string MerchantCode { get; set; } = default!;
/// <summary>Purpose of the checkout.</summary>
[JsonPropertyName("purpose")]
public string? Purpose { get; set; }
public CheckoutCreateRequestPurpose? Purpose { get; set; }
/// <summary>__Required__ for [APMs](https://developer.sumup.com/online-payments/apm/introduction) and __recommended__ for card payments. Refers to a url where the end user is redirected once the payment processing completes. If not specified, the [Payment Widget](https://developer.sumup.com/online-payments/tools/card-widget) renders [3DS challenge](https://developer.sumup.com/online-payments/features/3ds) within an iframe instead of performing a full-page redirect.</summary>
[JsonPropertyName("redirect_url")]
public string? RedirectUrl { get; set; }
Expand Down
16 changes: 16 additions & 0 deletions src/SumUp/Models/CheckoutCreateRequestPurpose.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// <auto-generated />
#nullable enable

namespace SumUp;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;

[JsonConverter(typeof(EnumMemberJsonConverterFactory))]
public enum CheckoutCreateRequestPurpose
{
[EnumMember(Value = "CHECKOUT")]
Checkout,
[EnumMember(Value = "SETUP_RECURRING_PAYMENT")]
SetupRecurringPayment,
}
Loading
Loading