github.com/snyk/vervet/v6@v6.2.4/spec_test.go (about)

     1  package vervet_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	qt "github.com/frankban/quicktest"
     7  	"github.com/getkin/kin-openapi/openapi3"
     8  
     9  	. "github.com/snyk/vervet/v6"
    10  	"github.com/snyk/vervet/v6/testdata"
    11  )
    12  
    13  func TestSpecs(t *testing.T) {
    14  	c := qt.New(t)
    15  	specs, err := LoadSpecVersions(testdata.Path("resources"))
    16  	c.Assert(err, qt.IsNil)
    17  	versions := specs.Versions()
    18  	c.Assert(versions, qt.ContentEquals, VersionSlice{
    19  		MustParseVersion("2021-06-01~experimental"),
    20  		MustParseVersion("2021-06-04~experimental"),
    21  		MustParseVersion("2021-06-07~experimental"),
    22  		MustParseVersion("2021-06-13~experimental"),
    23  		MustParseVersion("2021-06-13~beta"),
    24  		MustParseVersion("2021-08-20~experimental"),
    25  		MustParseVersion("2023-06-01~experimental"),
    26  		MustParseVersion("2023-06-02~experimental"),
    27  		MustParseVersion("2023-06-03~experimental"),
    28  	})
    29  
    30  	type expectResourceVersion struct {
    31  		version     string
    32  		path        string
    33  		opFunc      func(*openapi3.PathItem) *openapi3.Operation
    34  		shouldExist bool
    35  	}
    36  	tests := []struct {
    37  		query, match string
    38  		hasVersions  []expectResourceVersion
    39  		err          string
    40  	}{{
    41  		query: "2021-07-01~experimental",
    42  		match: "2021-06-13~experimental",
    43  		hasVersions: []expectResourceVersion{{
    44  			version:     "2021-06-13~beta",
    45  			path:        "/examples/hello-world",
    46  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
    47  			shouldExist: true,
    48  		}, {
    49  			version:     "2021-06-13~beta",
    50  			path:        "/examples/hello-world/{id}",
    51  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
    52  			shouldExist: true,
    53  		}, {
    54  			version:     "2021-06-04~experimental",
    55  			path:        "/orgs/{orgId}/projects",
    56  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
    57  			shouldExist: true,
    58  		}},
    59  	}, {
    60  		query: "2021-09-01~experimental",
    61  		match: "2021-08-20~experimental",
    62  		hasVersions: []expectResourceVersion{{
    63  			version:     "2021-06-13~beta",
    64  			path:        "/examples/hello-world",
    65  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
    66  			shouldExist: true,
    67  		}, {
    68  			version:     "2021-06-13~beta",
    69  			path:        "/examples/hello-world/{id}",
    70  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
    71  			shouldExist: true,
    72  		}, {
    73  			version:     "2021-06-04~experimental",
    74  			path:        "/orgs/{orgId}/projects",
    75  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
    76  			shouldExist: true,
    77  		}, {
    78  			version:     "2021-08-20~experimental",
    79  			path:        "/orgs/{org_id}/projects/{project_id}",
    80  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Delete },
    81  			shouldExist: true,
    82  		}},
    83  	}, {
    84  		query: "2021-07-01~wip",
    85  		match: "2021-06-13~experimental",
    86  	}, {
    87  		query: "2021-06-01",
    88  		err:   "no matching version",
    89  	}, {
    90  		query: "2021-07-01~beta",
    91  		match: "2021-06-13~beta",
    92  		hasVersions: []expectResourceVersion{{
    93  			version:     "2021-06-13~beta",
    94  			path:        "/examples/hello-world",
    95  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Post },
    96  			shouldExist: true,
    97  		}, {
    98  			version:     "2021-06-13~beta",
    99  			path:        "/examples/hello-world/{id}",
   100  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
   101  			shouldExist: true,
   102  		}},
   103  	}, {
   104  		query: "2023-06-02~experimental",
   105  		match: "2023-06-02~experimental",
   106  		hasVersions: []expectResourceVersion{{
   107  			version:     "2023-06-02~experimental",
   108  			path:        "/users",
   109  			opFunc:      func(p *openapi3.PathItem) *openapi3.Operation { return p.Get },
   110  			shouldExist: true,
   111  		}},
   112  	}, {
   113  		query: "2023-06-03~experimental",
   114  		match: "2023-06-03~experimental",
   115  		hasVersions: []expectResourceVersion{{
   116  			version: "2023-06-03~experimental",
   117  			path:    "/users",
   118  			// should be omitted from the 2023-06-03 spec because it was marked sunset
   119  			// in version 2023-06-02
   120  			shouldExist: false,
   121  		}},
   122  	}}
   123  	for i, t := range tests {
   124  		c.Logf("test#%d: %#v", i, t)
   125  		spec, err := specs.At(MustParseVersion(t.query))
   126  		if t.err != "" {
   127  			c.Assert(err, qt.ErrorMatches, t.err)
   128  			continue
   129  		}
   130  		c.Assert(err, qt.IsNil)
   131  		_, err = ExtensionString(spec.Extensions, ExtSnykApiStability)
   132  		c.Assert(err, qt.ErrorMatches, `extension "x-snyk-api-stability" not found`)
   133  		c.Assert(IsExtensionNotFound(err), qt.IsTrue)
   134  		version, err := ExtensionString(spec.Extensions, ExtSnykApiVersion)
   135  		c.Assert(err, qt.IsNil)
   136  		c.Assert(version, qt.Equals, t.match)
   137  		for _, expected := range t.hasVersions {
   138  			pathItem := spec.Paths[expected.path]
   139  
   140  			if !expected.shouldExist {
   141  				c.Assert(pathItem, qt.IsNil)
   142  				continue
   143  			}
   144  
   145  			c.Assert(pathItem, qt.Not(qt.IsNil))
   146  			op := expected.opFunc(pathItem)
   147  			versionStr, err := ExtensionString(op.Extensions, ExtSnykApiVersion)
   148  			c.Assert(err, qt.IsNil)
   149  			c.Assert(versionStr, qt.Equals, expected.version)
   150  		}
   151  	}
   152  }
   153  
   154  func TestDoesNotGenerateSpecsForStabilitiesWithNoChanges(t *testing.T) {
   155  	c := qt.New(t)
   156  	specs, err := LoadSpecVersions(testdata.Path("overgen"))
   157  	c.Assert(err, qt.IsNil)
   158  	versions := specs.Versions()
   159  	c.Assert(versions, qt.ContentEquals, VersionSlice{
   160  		MustParseVersion("2021-08-11"),
   161  		MustParseVersion("2021-08-11~beta"),
   162  		MustParseVersion("2021-08-11~experimental"),
   163  		MustParseVersion("2023-11-15~experimental"),
   164  	})
   165  }