Skip to content

Commit

Permalink
feat: new step into http feature (#40)
Browse files Browse the repository at this point in the history
* new step added into http feature and new table parser

* Solve S3 issue

* Clean up S3 bucket

* fix typo

Co-authored-by: Cesar Brea <cesar.breacano@telefonica.com>
  • Loading branch information
Miriam Benito Diez and cbrea authored Sep 6, 2021
1 parent 1edbee0 commit 12ab041
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 15 deletions.
20 changes: 15 additions & 5 deletions steps/http/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ import (
"context"
"errors"
"fmt"
"strings"
"io/ioutil"
"net"
"net/http"
"net/url"
"time"
"path"
"strings"
"time"

"github.com/Telefonica/golium"
"github.com/google/uuid"
Expand All @@ -35,8 +35,8 @@ import (

const (
slash string = "/"
)
)

// Request information of the Session.
type Request struct {
// Endpoint of the HTTP server. It might include a base path.
Expand Down Expand Up @@ -82,7 +82,7 @@ func (s *Session) URL() (*url.URL, error) {
}
u.Path = path.Join(u.Path, s.Request.Path)
/*
* NOTE: path.Join removes trailing slash using Clean thus,
* NOTE: path.Join removes trailing slash using Clean thus,
* we need to add it if is in s.Request.Path
* - Reference: https://forum.golangbridge.org/t/how-to-concatenate-paths-for-api-request/5791
* - Docs: https://pkg.go.dev/path#Join
Expand Down Expand Up @@ -259,6 +259,16 @@ func (s *Session) ValidateResponseHeaders(ctx context.Context, expectedHeaders m
return nil
}

// ValidateNotResponseHeaders checks that a set of response headers are not included in HTTP response.
func (s *Session) ValidateNotResponseHeaders(ctx context.Context, expectedHeaders []string) error {
for _, expectedHeader := range expectedHeaders {
if len(s.Response.Response.Header.Values(expectedHeader)) > 0 {
return fmt.Errorf("HTTP response includes the header '%s'", expectedHeader)
}
}
return nil
}

// ValidateResponseBodyJSONSchema validates the response body against the JSON schema.
func (s *Session) ValidateResponseBodyJSONSchema(ctx context.Context, schema string) error {
schemasDir := golium.GetConfig().Dir.Schemas
Expand Down
7 changes: 7 additions & 0 deletions steps/http/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ func (s Steps) InitializeSteps(ctx context.Context, scenCtx *godog.ScenarioConte
}
return session.ValidateResponseHeaders(ctx, headers)
})
scenCtx.Step(`^the HTTP response must not contain the headers$`, func(t *godog.Table) error {
headers, err := golium.ConvertTableColumnToArray(ctx, t)
if err != nil {
return fmt.Errorf("failed processing HTTP headers from table: %w", err)
}
return session.ValidateNotResponseHeaders(ctx, headers)
})
scenCtx.Step(`^the HTTP response body must comply with the JSON schema "([^"]*)"$`, func(schema string) error {
return session.ValidateResponseBodyJSONSchema(ctx, golium.ValueAsString(ctx, schema))
})
Expand Down
42 changes: 36 additions & 6 deletions steps/s3/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ import (

type Session struct {
Client *aws_s.Session
CreatedBuckets []*CreatedBucket
CreatedDocuments []*CreatedDocument
}

type CreatedBucket struct {
bucket string
}

type CreatedDocument struct {
bucket string
key string
Expand Down Expand Up @@ -76,7 +81,6 @@ func (s *Session) UploadS3FileWithContent(ctx context.Context, bucket, key, mess
Body: strings.NewReader(message),
})
if err != nil {
logger.LogMessage("unable to upload file")
return fmt.Errorf("unable to upload %q to %q, %v", key, bucket, err)
}

Expand All @@ -95,8 +99,27 @@ func (s *Session) CreateS3Bucket(ctx context.Context, bucket string) error {
s3Client := s3.New(s.Client)

if _, err := s3Client.CreateBucket(cparams); err != nil {
logger.LogMessage(fmt.Sprintf("error creating a new bucket: %s, err: %v", bucket, err))
return fmt.Errorf("error creating a new bucket: %s, err: %v", bucket, err)
}

s.CreatedBuckets = append(s.CreatedBuckets, &CreatedBucket{bucket: bucket})
return nil
}

// DeleteS3Bucket deletes the bucket in S3.
func (s *Session) DeleteS3Bucket(ctx context.Context, bucket string) error {
logger := GetLogger()
logger.LogMessage(fmt.Sprintf("deleting bucket: %s", bucket))
cparams := &s3.DeleteBucketInput{
Bucket: aws.String(bucket),
}

s3Client := s3.New(s.Client)

if _, err := s3Client.DeleteBucket(cparams); err != nil {
return fmt.Errorf("error deleting bucket: %s, err: %v", bucket, err)
}

return nil
}

Expand All @@ -110,7 +133,7 @@ func (s *Session) ValidateS3BucketExists(ctx context.Context, bucket string) err
Bucket: aws.String(bucket),
}
if _, err := s3svc.GetBucketLocation(input); err != nil {
return fmt.Errorf("bucket: '%s' does not exists", bucket)
return fmt.Errorf("bucket: '%s' does not exist", bucket)
}
return nil
}
Expand All @@ -125,7 +148,7 @@ func (s *Session) ValidateS3FileExists(ctx context.Context, bucket, key string)
return err
}
if !exists {
return fmt.Errorf("failed validating s3 file exits: no file exists in bucket '%s' with name '%s' ", bucket, key)
return fmt.Errorf("failed validating s3 file exists: file '%s' does not exist in bucket '%s', err %v ", key, bucket, err)
}
return nil
}
Expand Down Expand Up @@ -189,10 +212,17 @@ func (s *Session) s3KeyExists(s3svc *s3.S3, bucket string, key string) (bool, er

// CleanUp cleans session by deleting all documents created in S3
func (s *Session) CleanUp(ctx context.Context) {
logger := GetLogger()
// Remove keys
for _, file := range s.CreatedDocuments {
if err := s.DeleteS3File(ctx, file.bucket, file.key); err != nil {
logger := GetLogger()
logger.LogMessage(fmt.Sprintf("Failure on deletion of s3 file '%s' in bucket '%s', err %v", file.key, file.bucket, err))
logger.LogMessage(fmt.Sprintf("failure on deletion of s3 file '%s' in bucket '%s', err %v", file.key, file.bucket, err))
}
}
// Remove buckets
for _, file := range s.CreatedBuckets {
if err := s.DeleteS3Bucket(ctx, file.bucket); err != nil {
logger.LogMessage(fmt.Sprintf("failure on deletion of s3 bucket '%s', err %v", file.bucket, err))
}
}
}
12 changes: 9 additions & 3 deletions steps/s3/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,25 @@ func (cs Steps) InitializeSteps(ctx context.Context, scenCtx *godog.ScenarioCont
})
scenCtx.Step(`^I create a file in S3 bucket "([^"]+)" with key "([^"]+)" and the content$`, func(bucket, key string, message *godog.DocString) error {
if session.Client == nil {
return fmt.Errorf("failed creating S3 file: nil session: may forget step 'I create a new S3 session'")
return fmt.Errorf("failed creating S3 session: nil session: may forget step 'I create a new S3 session'")
}
return session.UploadS3FileWithContent(ctx, golium.ValueAsString(ctx, bucket), golium.ValueAsString(ctx, key), golium.ValueAsString(ctx, message.Content))
})
scenCtx.Step(`^I create the S3 bucket "([^"]+)"$`, func(bucket string) error {
if session.Client == nil {
return fmt.Errorf("failed creating S3 file: nil session: may forget step 'I create a new S3 session'")
return fmt.Errorf("failed creating S3 session: nil session: may forget step 'I create a new S3 session'")
}
return session.CreateS3Bucket(ctx, golium.ValueAsString(ctx, bucket))
})
scenCtx.Step(`^I delete the S3 bucket "([^"]+)"$`, func(bucket string) error {
if session.Client == nil {
return fmt.Errorf("failed creating S3 session: nil session: may forget step 'I create a new S3 session'")
}
return session.DeleteS3Bucket(ctx, golium.ValueAsString(ctx, bucket))
})
scenCtx.Step(`^the S3 bucket "([^"]+)" exists$`, func(bucket string) error {
if session.Client == nil {
return fmt.Errorf("failed creating S3 file: nil session: may forget step 'I create a new S3 session'")
return fmt.Errorf("failed creating S3 session: nil session: may forget step 'I create a new S3 session'")
}
return session.ValidateS3BucketExists(ctx, golium.ValueAsString(ctx, bucket))
})
Expand Down
17 changes: 17 additions & 0 deletions table.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ func ConvertTableToMap(ctx context.Context, t *godog.Table) (map[string]interfac
return m, nil
}

// ConvertTableColumnToArray converts a godog table with 1 column into a []string.
func ConvertTableColumnToArray(ctx context.Context, t *godog.Table) ([]string, error) {
m := []string{}
if len(t.Rows) == 0 {
return m, nil
}
for i := 0; i < len(t.Rows); i++ {
cells := t.Rows[i].Cells
if len(cells) > 1 {
return m, errors.New("table must have 1 unique column")
}
propKey := cells[0].Value
m = append(m, propKey)
}
return m, nil
}

// ConvertTableToMultiMap converts a godog table with 2 columns into a map[string][]string.
// The multimap is using url.Values.
// The multimap is useful to support multiple values for the same key (e.g. for query parameters
Expand Down
2 changes: 1 addition & 1 deletion test/acceptance/environments/local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,4 @@ minio: true
minioEndpoint: https://play.min.io:9000
minioAwsAccessKeyId: Q3AM3UQ867SPQQA43P2F
minioAwsSecretAccessKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
minioAwsRegion: eu-west-1
minioAwsRegion: us-east-1
14 changes: 14 additions & 0 deletions test/acceptance/features/http.feature
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,17 @@ Feature: HTTP client
And the HTTP path "/jpeg/"
When I send a HTTP "POST" request
Then the HTTP status code must be "404"

@http1
Scenario: Send a GET request and check if a specific header is not in response headers
Given the HTTP endpoint "[CONF:url]/anything"
And the HTTP path "/test-query"
And the HTTP query parameters
| exists | true |
| sort | name |
And the HTTP request headers
| Authorization | Bearer access-token |
When I send a HTTP "GET" request
Then the HTTP status code must be "200"
And the HTTP response must not contain the headers
| non-existent-header |
1 change: 1 addition & 0 deletions test/acceptance/features/s3.feature
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ Feature: S3 client
Document content line 2
"""
And I delete the file in S3 bucket "[CONF:s3Bucket]" with key "[CTXT:key]"
And I delete the S3 bucket "[CONF:s3Bucket]"

0 comments on commit 12ab041

Please sign in to comment.