Skip to content

Commit

Permalink
Merge pull request #3 from speakeasy-api/sync-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
TristanSpeakEasy authored Nov 4, 2024
2 parents 03a52fd + 668c17e commit 47cbcb0
Show file tree
Hide file tree
Showing 16 changed files with 316 additions and 127 deletions.
10 changes: 9 additions & 1 deletion arazzo/arazzo.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,19 @@ func (a *Arazzo) GetCore() *core.Arazzo {
return &a.core
}

// Sync will sync any changes made to the Arazzo document models back to the core models.
func (a *Arazzo) Sync(ctx context.Context) error {
if _, err := marshaller.SyncValue(ctx, a, &a.core, nil, false); err != nil {
return err
}
return nil
}

// Marshal will marshal the Arazzo document to the provided io.Writer.
func (a *Arazzo) Marshal(ctx context.Context, w io.Writer) error {
ctx = yml.ContextWithConfig(ctx, a.core.Config)

if _, err := marshaller.SyncValue(ctx, a, &a.core, nil); err != nil {
if _, err := marshaller.SyncValue(ctx, a, &a.core, nil, false); err != nil {
return err
}

Expand Down
72 changes: 66 additions & 6 deletions arazzo/arazzo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ var testArazzoInstance = &arazzo.Arazzo{
Type: arazzo.FailureActionTypeRetry,
RetryAfter: pointer.From(10.0),
RetryLimit: pointer.From(3),
Criteria: []criterion.Criterion{{Condition: "$statusCode == 500", Type: criterion.CriterionTypeUnion{
Criteria: []criterion.Criterion{{Context: pointer.From(expression.Expression("$statusCode")), Condition: "$statusCode == 500", Type: criterion.CriterionTypeUnion{
Type: pointer.From(criterion.CriterionTypeSimple),
}}},
Valid: true,
Expand Down Expand Up @@ -320,6 +320,9 @@ func TestArazzo_Mutate_Success(t *testing.T) {
err = arazzo.Marshal(ctx, a, outBuf)
require.NoError(t, err)

errs := a.Validate(ctx)
require.Empty(t, errs)

assert.Equal(t, `arazzo: 1.0.0
info:
title: My updated workflow title
Expand Down Expand Up @@ -383,17 +386,23 @@ components:
retryAfter: 10
retryLimit: 3
criteria:
- condition: $statusCode == 500
- context: $statusCode
condition: $statusCode == 500
x-test: some-value
`, outBuf.String())
}

func TestArazzo_Create_Success(t *testing.T) {
outBuf := bytes.NewBuffer([]byte{})

err := arazzo.Marshal(context.Background(), testArazzoInstance, outBuf)
ctx := context.Background()

err := arazzo.Marshal(ctx, testArazzoInstance, outBuf)
require.NoError(t, err)

errs := testArazzoInstance.Validate(ctx)
require.Empty(t, errs)

data, err := os.ReadFile("testdata/test.arazzo.yaml")
require.NoError(t, err)

Expand Down Expand Up @@ -561,15 +570,66 @@ var stressTests = []struct {
wantTitle: "",
},
{
name: "DevAttila87 Example",
name: "Itarazzo Library Example",
args: args{
location: "https://raw.githubusercontent.com/devAttila87/arazzo/24dd4c896f98b942e61831f3529fe538089baedf/application-integration-test/src/test/resources/arazzo.yaml",
location: "https://raw.githubusercontent.com/leidenheit/itarazzo-library/3b335e1c4293444add52b5f2476420e2d871b1a5/src/test/resources/test.arazzo.yaml",
validationIgnores: []string{
"only one of operationId, operationPath or workflowId can be set", // legit issue
"expression is not valid, must begin with $: <root><id>4711</id><name>Chocolate</name></root>", // legit issue
},
},
wantTitle: "A cookie eating workflow",
},
{
name: "Itarazzo Client Pet Store Example",
args: args{
location: "https://raw.githubusercontent.com/leidenheit/itarazzo-client/b744ca1ca3a036964ae30be601f10a25b14dc52d/src/test/resources/pet-store.arazzo.yaml",
validationIgnores: []string{
"jsonpointer must start with /: $.status", // legit issues TODO: improve the error returned as it is wrong
"jsonpointer must start with /: $.id", // legit issues TODO: improve the error returned as it is wrong
},
},
wantTitle: "PetStore - Example of Workflows",
},
{
name: "Ritza build-a-bot workflow",
args: args{
location: "https://raw.githubusercontent.com/ritza-co/e2e-testing-arazzo/c0615c3708a1e4c0fcaeb79edae78ddc4eb5ba82/arazzo.yaml",
validationIgnores: []string{},
},
wantTitle: "Build-a-Bot Workflow",
},
{
name: " API-Flows adyen-giving workflow",
args: args{
location: "https://raw.githubusercontent.com/API-Flows/openapi-workflow-registry/3d85d79232fa8f42993b2f5bd47e273b9369dc2d/root/adyen/adyen-giving.yaml",
validationIgnores: []string{
"in must be one of [path, query, header, cookie] but was body",
},
},
wantTitle: "Adyen Giving",
},
{
name: "API-Flows simple workflow",
args: args{
location: "https://raw.githubusercontent.com/API-Flows/openapi-workflow-parser/6b28ba4def262969c5a96bc54d08433e6c336643/src/test/resources/1.0.0/simple.workflow.yaml",
validationIgnores: []string{},
},
wantTitle: "simple",
},
// Disabled for now as it is currently failing round tripping due to missing conditions
// {
// name: "Kartikhub swap tokens workflow",
// args: args{
// location: "https://raw.githubusercontent.com/Kartikhub/web3-basics/d95bc51bb935ef07d627e52c6fdfe18aaea69e18/swap-react/docs/swap-transaction-arazzo.yaml",
// validationIgnores: []string{ // All valid issues
// "field condition is missing",
// "condition is required",
// "field value is missing",
// "expression is not valid, must begin with $",
// },
// },
// wantTitle: "Swap Tokens",
// },
}

func TestArazzo_StressTests_Validate(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions arazzo/core/arazzo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package core

import (
"context"
"errors"
"fmt"
"io"

Expand Down Expand Up @@ -32,6 +33,10 @@ func Unmarshal(ctx context.Context, doc io.Reader) (*Arazzo, error) {
return nil, fmt.Errorf("failed to read Arazzo document: %w", err)
}

if len(data) == 0 {
return nil, errors.New("empty document")
}

var root yaml.Node
if err := yaml.Unmarshal(data, &root); err != nil {
return nil, fmt.Errorf("failed to unmarshal Arazzo document: %w", err)
Expand Down
4 changes: 2 additions & 2 deletions arazzo/core/criterion.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ func (c *CriterionTypeUnion) SyncChanges(ctx context.Context, model any, valueNo
tf := mv.FieldByName("Type")
ef := mv.FieldByName("ExpressionType")

tv, err := marshaller.SyncValue(ctx, tf.Interface(), &c.Type, valueNode)
tv, err := marshaller.SyncValue(ctx, tf.Interface(), &c.Type, valueNode, false)
if err != nil {
return nil, err
}

ev, err := marshaller.SyncValue(ctx, ef.Interface(), &c.ExpressionType, valueNode)
ev, err := marshaller.SyncValue(ctx, ef.Interface(), &c.ExpressionType, valueNode, false)
if err != nil {
return nil, err
}
Expand Down
17 changes: 2 additions & 15 deletions arazzo/core/reusable.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,14 @@ func (r *Reusable[T]) SyncChanges(ctx context.Context, model any, valueNode *yam

of := mv.FieldByName("Object")
if of.IsZero() {
type reusable[T any] struct {
Reference marshaller.Node[*Expression] `key:"reference"`
Value marshaller.Node[Value] `key:"value"`

RootNode *yaml.Node
}

rl := reusable[T]{
Reference: r.Reference,
Value: r.Value,
RootNode: r.RootNode,
}

var err error
valueNode, err = marshaller.SyncValue(ctx, model, &rl, valueNode)
valueNode, err = marshaller.SyncValue(ctx, model, r, valueNode, true)
if err != nil {
return nil, err
}
} else {
var err error
valueNode, err = marshaller.SyncValue(ctx, of.Interface(), &r.Object, valueNode)
valueNode, err = marshaller.SyncValue(ctx, of.Interface(), &r.Object, valueNode, false)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions arazzo/criterion/criterion.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ func (c *Criterion) Validate(opts ...validation.Option) []error {
func (c *Criterion) validateCondition(opts ...validation.Option) []error {
errs := []error{}

conditionLine := c.core.Condition.GetValueNodeOrRoot(c.core.RootNode).Line
conditionColumn := c.core.Condition.GetValueNodeOrRoot(c.core.RootNode).Column
conditionLine := c.GetCore().Condition.GetValueNodeOrRoot(c.GetCore().RootNode).Line
conditionColumn := c.GetCore().Condition.GetValueNodeOrRoot(c.GetCore().RootNode).Column

switch c.Type.GetType() {
case CriterionTypeSimple:
Expand Down
2 changes: 1 addition & 1 deletion arazzo/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func (p *Parameter) Validate(ctx context.Context, opts ...validation.Option) []e

if in != "" {
errs = append(errs, &validation.Error{
Message: fmt.Sprintf("in must be one of [%s]", strings.Join([]string{string(InPath), string(InQuery), string(InHeader), string(InCookie)}, ", ")),
Message: fmt.Sprintf("in must be one of [%s] but was %s", strings.Join([]string{string(InPath), string(InQuery), string(InHeader), string(InCookie)}, ", "), in),
Line: p.core.In.GetValueNodeOrRoot(p.core.RootNode).Line,
Column: p.core.In.GetValueNodeOrRoot(p.core.RootNode).Column,
})
Expand Down
10 changes: 5 additions & 5 deletions arazzo/testdata/speakeasybar.arazzo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ workflows:
operationId: createOrder
parameters:
- name: orderType
in: body
in: query
value: $inputs.orderType
- name: productCode
in: body
in: query
value: $inputs.productCode
- name: quantity
in: body
in: query
value: $inputs.quantity
outputs:
orderNumber: $response.body#/orderNumber
Expand Down Expand Up @@ -176,9 +176,9 @@ components:
value: $steps.authenticate.outputs.token
username:
name: username
in: body
in: query
value: $inputs.username
password:
name: password
in: body
in: query
value: $inputs.password
3 changes: 2 additions & 1 deletion arazzo/testdata/test.arazzo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,6 @@ components:
retryAfter: 10
retryLimit: 3
criteria:
- condition: $statusCode == 500%s
- context: $statusCode
condition: $statusCode == 500%s
x-test: some-value
4 changes: 2 additions & 2 deletions jsonschema/oas31/core/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ func (v *EitherValue[L, R]) SyncChanges(ctx context.Context, model any, valueNod
lf := mv.FieldByName("Left")
rf := mv.FieldByName("Right")

lv, err := marshaller.SyncValue(ctx, lf.Interface(), &v.Left, valueNode)
lv, err := marshaller.SyncValue(ctx, lf.Interface(), &v.Left, valueNode, false)
if err != nil {
return nil, err
}

rv, err := marshaller.SyncValue(ctx, rf.Interface(), &v.Right, valueNode)
rv, err := marshaller.SyncValue(ctx, rf.Interface(), &v.Right, valueNode, false)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion jsonschema/oas31/core/value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestEitherValue_SyncChanges_Success(t *testing.T) {
Left: pointer.From("some-value"),
}
var target EitherValue[string, string]
outNode, err := marshaller.SyncValue(ctx, source, &target, nil)
outNode, err := marshaller.SyncValue(ctx, source, &target, nil, false)
require.NoError(t, err)
assert.Equal(t, testutils.CreateStringYamlNode("some-value", 0, 0), outNode)
assert.Equal(t, "some-value", *target.Left)
Expand Down
2 changes: 1 addition & 1 deletion marshaller/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (n Node[V]) GetValueType() reflect.Type {
func (n *Node[V]) SyncValue(ctx context.Context, key string, value any) (*yaml.Node, *yaml.Node, error) {
n.Key = key
n.KeyNode = yml.CreateOrUpdateKeyNode(ctx, key, n.KeyNode)
valueNode, err := SyncValue(ctx, value, &n.Value, n.ValueNode)
valueNode, err := SyncValue(ctx, value, &n.Value, n.ValueNode, false)
if err != nil {
return nil, nil, err
}
Expand Down
Loading

0 comments on commit 47cbcb0

Please sign in to comment.