From 977e07a87d016a39b736e6f689f7a7b89519f111 Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Wed, 9 Oct 2024 10:16:41 -0700 Subject: [PATCH 01/11] new unit testing framework --- test/unit/base.go | 39 ++++++++++++++++++ test/unit/fixtures.go | 59 +++++++++++++++++++++++++++ test/unit/fixtures/linodes_list.json | 60 ++++++++++++++++++++++++++++ test/unit/instance_test.go | 45 +++++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 test/unit/base.go create mode 100644 test/unit/fixtures.go create mode 100644 test/unit/fixtures/linodes_list.json create mode 100644 test/unit/instance_test.go diff --git a/test/unit/base.go b/test/unit/base.go new file mode 100644 index 000000000..8e24846b1 --- /dev/null +++ b/test/unit/base.go @@ -0,0 +1,39 @@ +package unit + +import ( + "github.com/jarcoal/httpmock" + "github.com/linode/linodego" + "github.com/linode/linodego/internal/testutil" + "github.com/stretchr/testify/mock" + "testing" +) + +type MockResponse struct { + StatusCode int + Body interface{} +} + +// ClientBaseCase provides a base for unit tests +type ClientBaseCase struct { + Client *linodego.Client + Mock *mock.Mock + BaseURL string // Base URL up to /v4 +} + +// SetUp initializes the Linode client using the mock HTTP client +func (c *ClientBaseCase) SetUp(t *testing.T) { + c.Mock = &mock.Mock{} + c.Client = testutil.CreateMockClient(t, linodego.NewClient) + c.BaseURL = "https://api.linode.com/v4/" +} + +func (c *ClientBaseCase) TearDown(t *testing.T) { + httpmock.DeactivateAndReset() // Reset HTTP mock after tests + c.Mock.AssertExpectations(t) +} + +// MockGet mocks a GET request to the client. +func (c *ClientBaseCase) MockGet(path string, response interface{}) { + fullURL := c.BaseURL + path + httpmock.RegisterResponder("GET", fullURL, httpmock.NewJsonResponderOrPanic(200, response)) +} diff --git a/test/unit/fixtures.go b/test/unit/fixtures.go new file mode 100644 index 000000000..25d7b7188 --- /dev/null +++ b/test/unit/fixtures.go @@ -0,0 +1,59 @@ +package unit + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" +) + +// TestFixtures manages loading and retrieving test fixtures +type TestFixtures struct { + fixtures map[string]interface{} +} + +// NewTestFixtures creates a new TestFixtures instance +func NewTestFixtures() *TestFixtures { + tf := &TestFixtures{} + tf.loadFixtures() + return tf +} + +// loadFixtures loads all JSON files in fixtures directory +func (tf *TestFixtures) loadFixtures() { + tf.fixtures = make(map[string]interface{}) + fixturesDir := "fixtures" + + err := filepath.Walk(fixturesDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && filepath.Ext(path) == ".json" { + data, err := os.ReadFile(path) + if err != nil { + return err + } + var jsonData interface{} + if err := json.Unmarshal(data, &jsonData); err != nil { + return err + } + fixtureName := filepath.Base(path) + tf.fixtures[fixtureName[:len(fixtureName)-5]] = jsonData + } + return nil + }) + if err != nil { + panic(err) + } +} + +// GetFixture retrieves the fixture data for the given URL +func (tf *TestFixtures) GetFixture(jsonFile string) (interface{}, error) { + data, ok := tf.fixtures[jsonFile] + if !ok { + return nil, os.ErrNotExist + } + fmt.Printf("Loading fixture: %s\n", jsonFile) // TODO:: debugging remove later + + return data, nil +} diff --git a/test/unit/fixtures/linodes_list.json b/test/unit/fixtures/linodes_list.json new file mode 100644 index 000000000..0db4d7f4d --- /dev/null +++ b/test/unit/fixtures/linodes_list.json @@ -0,0 +1,60 @@ +{ + "data": [ + { + "alerts": { + "cpu": 180, + "io": 10000, + "network_in": 10, + "network_out": 10, + "transfer_quota": 80 + }, + "backups": { + "available": true, + "enabled": true, + "last_successful": "2018-01-01T00:01:01", + "schedule": { + "day": "Saturday", + "window": "W22" + } + }, + "created": "2018-01-01T00:01:01", + "has_user_data": true, + "host_uuid": "3a3ddd59d9a78bb8de041391075df44de62bfec8", + "hypervisor": "kvm", + "id": 123, + "image": "linode/debian10", + "ipv4": [ + "203.0.113.1", + "192.0.2.1" + ], + "ipv6": "c001:d00d::1337/128", + "label": "linode123", + "placement_group": { + "id": 528, + "label": "PG_Miami_failover", + "migrating_to": 2468, + "placement_group_policy": "strict", + "placement_group_type": "anti-affinity:local" + }, + "region": "us-east", + "specs": { + "disk": 81920, + "gpus": 0, + "memory": 4096, + "transfer": 4000, + "vcpus": 2 + }, + "status": "running", + "tags": [ + "example tag", + "another example" + ], + "type": "g6-standard-1", + "updated": "2018-01-01T00:01:01", + "watchdog_enabled": true + } + ], + "page": 1, + "pages": 1, + "results": 1 +} diff --git a/test/unit/instance_test.go b/test/unit/instance_test.go new file mode 100644 index 000000000..887b3501b --- /dev/null +++ b/test/unit/instance_test.go @@ -0,0 +1,45 @@ +package unit + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestListInstances(t *testing.T) { + // Initialize the TestFixtures to load the fixture + fixtures := NewTestFixtures() + + // Mock the expected response from the ListInstances endpoint + fixtureData, err := fixtures.GetFixture("linodes_list") // Use the correct fixture name without ".json" + if err != nil { + t.Fatalf("Failed to load fixture: %v", err) + } + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("linode/instances", fixtureData) + + instances, err := base.Client.ListInstances(context.Background(), nil) + if err != nil { + t.Fatalf("Error listing instances: %v", err) + } + + assert.Equal(t, 1, len(instances)) + linode := instances[0] + assert.Equal(t, 123, linode.ID) + assert.Equal(t, "linode123", linode.Label) + + // Fix for the status comparison + assert.Equal(t, "running", string(linode.Status)) + + // Fix for the IP address comparison + assert.Equal(t, "203.0.113.1", linode.IPv4[0].String()) + + assert.Equal(t, "g6-standard-1", linode.Type) + assert.Equal(t, "us-east", linode.Region) + assert.Equal(t, 4096, linode.Specs.Memory) +} From e0b319bc2725dc61d9792a3deca8bf71c760ddfb Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Wed, 9 Oct 2024 16:33:56 -0700 Subject: [PATCH 02/11] load fixtures with embed --- test/unit/fixtures.go | 49 +++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/test/unit/fixtures.go b/test/unit/fixtures.go index 25d7b7188..ba442d81b 100644 --- a/test/unit/fixtures.go +++ b/test/unit/fixtures.go @@ -1,12 +1,15 @@ package unit import ( + "embed" "encoding/json" "fmt" - "os" "path/filepath" ) +//go:embed fixtures/*.json +var fixtureFiles embed.FS // Embeds all JSON files in the fixtures directory + // TestFixtures manages loading and retrieving test fixtures type TestFixtures struct { fixtures map[string]interface{} @@ -19,41 +22,41 @@ func NewTestFixtures() *TestFixtures { return tf } -// loadFixtures loads all JSON files in fixtures directory +// loadFixtures loads all embedded JSON files func (tf *TestFixtures) loadFixtures() { tf.fixtures = make(map[string]interface{}) - fixturesDir := "fixtures" - err := filepath.Walk(fixturesDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() && filepath.Ext(path) == ".json" { - data, err := os.ReadFile(path) + // You can use the `ReadDir` function to list all files in the embedded directory. + entries, err := fixtureFiles.ReadDir("fixtures") + if err != nil { + panic(fmt.Sprintf("failed to read embedded fixtures: %v", err)) + } + + for _, entry := range entries { + if !entry.IsDir() && filepath.Ext(entry.Name()) == ".json" { + // Read the embedded JSON file + data, err := fixtureFiles.ReadFile("fixtures/" + entry.Name()) if err != nil { - return err + panic(fmt.Sprintf("failed to read fixture %s: %v", entry.Name(), err)) } + var jsonData interface{} if err := json.Unmarshal(data, &jsonData); err != nil { - return err + panic(fmt.Sprintf("failed to unmarshal fixture %s: %v", entry.Name(), err)) } - fixtureName := filepath.Base(path) - tf.fixtures[fixtureName[:len(fixtureName)-5]] = jsonData + + // Remove ".json" from the file name + fixtureName := entry.Name()[:len(entry.Name())-5] + tf.fixtures[fixtureName] = jsonData } - return nil - }) - if err != nil { - panic(err) } } -// GetFixture retrieves the fixture data for the given URL -func (tf *TestFixtures) GetFixture(jsonFile string) (interface{}, error) { - data, ok := tf.fixtures[jsonFile] +// GetFixture retrieves the fixture data for the given name. +func (tf *TestFixtures) GetFixture(name string) (interface{}, error) { + data, ok := tf.fixtures[name] if !ok { - return nil, os.ErrNotExist + return nil, fmt.Errorf("fixture not found: %s", name) } - fmt.Printf("Loading fixture: %s\n", jsonFile) // TODO:: debugging remove later - return data, nil } From 83155cc016e7f23a91488f8e8d637f1ad6f8ac8e Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Wed, 9 Oct 2024 16:34:58 -0700 Subject: [PATCH 03/11] load fixtures with embed --- test/unit/fixtures.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/unit/fixtures.go b/test/unit/fixtures.go index ba442d81b..fb59847e3 100644 --- a/test/unit/fixtures.go +++ b/test/unit/fixtures.go @@ -8,7 +8,7 @@ import ( ) //go:embed fixtures/*.json -var fixtureFiles embed.FS // Embeds all JSON files in the fixtures directory +var fixtureFiles embed.FS // TestFixtures manages loading and retrieving test fixtures type TestFixtures struct { @@ -26,7 +26,6 @@ func NewTestFixtures() *TestFixtures { func (tf *TestFixtures) loadFixtures() { tf.fixtures = make(map[string]interface{}) - // You can use the `ReadDir` function to list all files in the embedded directory. entries, err := fixtureFiles.ReadDir("fixtures") if err != nil { panic(fmt.Sprintf("failed to read embedded fixtures: %v", err)) @@ -52,7 +51,7 @@ func (tf *TestFixtures) loadFixtures() { } } -// GetFixture retrieves the fixture data for the given name. +// GetFixture retrieves the fixture data for the given name func (tf *TestFixtures) GetFixture(name string) (interface{}, error) { data, ok := tf.fixtures[name] if !ok { From 0b63cd9e7988e51baf4577616aef201abb19046d Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Thu, 10 Oct 2024 16:39:38 -0700 Subject: [PATCH 04/11] migrating account, image, instance_stats tests; fix var type in Account and CreditCard struct --- account.go | 4 +- test/unit/account_child_test.go | 163 +++++++++--------- test/unit/account_transfer_test.go | 46 ++--- test/unit/base.go | 23 ++- .../fixtures/account_child_create_token.json | 8 + test/unit/fixtures/account_child_get.json | 29 ++++ test/unit/fixtures/account_child_list.json | 36 ++++ test/unit/fixtures/account_transfer_get.json | 13 ++ test/unit/fixtures/image_replicate.json | 31 ++++ test/unit/fixtures/instance_stats_get.json | 44 +++++ test/unit/images_test.go | 65 +++---- test/unit/instance_stats_test.go | 80 ++++----- test/unit/instance_test.go | 9 +- 13 files changed, 354 insertions(+), 197 deletions(-) create mode 100644 test/unit/fixtures/account_child_create_token.json create mode 100644 test/unit/fixtures/account_child_get.json create mode 100644 test/unit/fixtures/account_child_list.json create mode 100644 test/unit/fixtures/account_transfer_get.json create mode 100644 test/unit/fixtures/image_replicate.json create mode 100644 test/unit/fixtures/instance_stats_get.json diff --git a/account.go b/account.go index ed022f47b..6a3c65fb5 100644 --- a/account.go +++ b/account.go @@ -28,7 +28,7 @@ type Account struct { EUUID string `json:"euuid"` BillingSource string `json:"billing_source"` Capabilities []string `json:"capabilities"` - ActiveSince *time.Time `json:"-"` + ActiveSince *time.Time `json:"active_since"` } // UnmarshalJSON implements the json.Unmarshaler interface @@ -53,7 +53,7 @@ func (account *Account) UnmarshalJSON(b []byte) error { // CreditCard information associated with the Account. type CreditCard struct { - LastFour string `json:"last_four"` + LastFour int `json:"last_four"` Expiry string `json:"expiry"` } diff --git a/test/unit/account_child_test.go b/test/unit/account_child_test.go index a58d9ea04..72b4aeb21 100644 --- a/test/unit/account_child_test.go +++ b/test/unit/account_child_test.go @@ -2,102 +2,105 @@ package unit import ( "context" - "fmt" - "reflect" + "github.com/stretchr/testify/assert" + "os" "testing" - - "github.com/jarcoal/httpmock" - "github.com/linode/linodego" - "github.com/linode/linodego/internal/testutil" - "github.com/stretchr/testify/require" + "time" ) -var testChildAccount = linodego.ChildAccount{ - Address1: "123 Main Street", - Address2: "Suite A", - Balance: 200, - BalanceUninvoiced: 145, - Capabilities: []string{ - "Linodes", - "NodeBalancers", - "Block Storage", - "Object Storage", - }, - City: "Philadelphia", - Company: "Linode LLC", - Country: "US", - CreditCard: &linodego.CreditCard{ - Expiry: "11/2022", - LastFour: "1111", - }, - Email: "john.smith@linode.com", - EUUID: "E1AF5EEC-526F-487D-B317EBEB34C87D71", - FirstName: "John", - LastName: "Smith", - Phone: "215-555-1212", - State: "PA", - TaxID: "ATU99999999", - Zip: "19102-1234", -} +var fixtures *TestFixtures -func TestAccountChild_list(t *testing.T) { - client := createMockClient(t) - - desiredResponse := map[string]any{ - "page": 1, - "pages": 1, - "results": 1, - "data": []linodego.ChildAccount{ - testChildAccount, - }, - } +func TestMain(m *testing.M) { + fixtures = NewTestFixtures() - httpmock.RegisterRegexpResponder( - "GET", - testutil.MockRequestURL("/account/child-accounts"), - httpmock.NewJsonResponderOrPanic(200, &desiredResponse), - ) + code := m.Run() - accounts, err := client.ListChildAccounts(context.Background(), nil) - require.NoError(t, err) + os.Exit(code) +} - require.True(t, reflect.DeepEqual(accounts, desiredResponse["data"])) +func TestAccountChild_list(t *testing.T) { + fixtureData, err := fixtures.GetFixture("account_child_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("account/child-accounts", fixtureData) + + accounts, err := base.Client.ListChildAccounts(context.Background(), nil) + assert.NoError(t, err) + + assert.Equal(t, 1, len(accounts), "Expected one child account") + + if len(accounts) > 0 { + childAccount := accounts[0] + assert.Equal(t, "123 Main Street", childAccount.Address1) + assert.Equal(t, "Suite A", childAccount.Address2) + assert.Equal(t, float32(200), childAccount.Balance) + assert.Equal(t, float32(145), childAccount.BalanceUninvoiced) + assert.Equal(t, "San Diego", childAccount.City) + assert.Equal(t, "john.smith@linode.com", childAccount.Email) + assert.Equal(t, "858-555-1212", childAccount.Phone) + assert.Equal(t, "CA", childAccount.State) + assert.Equal(t, "92111-1234", childAccount.Zip) + } } func TestAccountChild_get(t *testing.T) { - client := createMockClient(t) - - httpmock.RegisterRegexpResponder( - "GET", - testutil.MockRequestURL(fmt.Sprintf("/account/child-accounts/%s", testChildAccount.EUUID)), - httpmock.NewJsonResponderOrPanic(200, &testChildAccount), - ) - - account, err := client.GetChildAccount(context.Background(), testChildAccount.EUUID) - require.NoError(t, err) + fixtureData, err := fixtures.GetFixture("account_child_get") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("account/child-accounts/A1BC2DEF-34GH-567I-J890KLMN12O34P56", fixtureData) + + account, err := base.Client.GetChildAccount(context.Background(), "A1BC2DEF-34GH-567I-J890KLMN12O34P56") + assert.NoError(t, err) + + assert.Equal(t, "John", account.FirstName) + assert.Equal(t, "Smith", account.LastName) + assert.Equal(t, "123 Main Street", account.Address1) + assert.Equal(t, "Suite A", account.Address2) + assert.Equal(t, float32(200), account.Balance) + assert.Equal(t, float32(145), account.BalanceUninvoiced) + assert.Equal(t, "San Diego", account.City) + assert.Equal(t, "john.smith@linode.com", account.Email) + assert.Equal(t, "858-555-1212", account.Phone) + assert.Equal(t, "CA", account.State) + assert.Equal(t, "92111-1234", account.Zip) + assert.Equal(t, "US", account.Country) + assert.Equal(t, "external", account.BillingSource) + assert.Equal(t, []string{"Linodes", "NodeBalancers", "Block Storage", "Object Storage"}, account.Capabilities) + + if account.CreditCard != nil { + assert.Equal(t, "11/2024", account.CreditCard.Expiry) + assert.Equal(t, 1111, account.CreditCard.LastFour) + } - require.True(t, reflect.DeepEqual(*account, testChildAccount)) + assert.Equal(t, "A1BC2DEF-34GH-567I-J890KLMN12O34P56", account.EUUID) } func TestAccountChild_createToken(t *testing.T) { - client := createMockClient(t) + fixtureData, err := fixtures.GetFixture("account_child_create_token") + assert.NoError(t, err) - desiredResponse := linodego.ChildAccountToken{ - ID: 123, - Scopes: "*", - Label: "child_token", - } + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) - httpmock.RegisterRegexpResponder( - "POST", - testutil.MockRequestURL( - fmt.Sprintf("/account/child-accounts/%s/token", testChildAccount.EUUID), - ), - httpmock.NewJsonResponderOrPanic(200, &desiredResponse), - ) + base.MockPost("account/child-accounts/A1BC2DEF-34GH-567I-J890KLMN12O34P56/token", fixtureData) - token, err := client.CreateChildAccountToken(context.Background(), testChildAccount.EUUID) - require.NoError(t, err) + token, err := base.Client.CreateChildAccountToken(context.Background(), "A1BC2DEF-34GH-567I-J890KLMN12O34P56") + assert.NoError(t, err) - require.True(t, reflect.DeepEqual(*token, desiredResponse)) + // Assertions for the created token data + assert.Equal(t, 918, token.ID) + assert.Equal(t, "parent1_1234_2024-05-01T00:01:01", token.Label) + assert.Equal(t, "2024-05-01T00:01:01Z", token.Created.Format(time.RFC3339)) + assert.Equal(t, "2024-05-01T00:16:01Z", token.Expiry.Format(time.RFC3339)) + assert.Equal(t, "*", token.Scopes) + assert.Equal(t, "abcdefghijklmnop", token.Token) } diff --git a/test/unit/account_transfer_test.go b/test/unit/account_transfer_test.go index d924f986c..cd89b83d5 100644 --- a/test/unit/account_transfer_test.go +++ b/test/unit/account_transfer_test.go @@ -2,40 +2,30 @@ package unit import ( "context" - "reflect" + "github.com/stretchr/testify/assert" "testing" - - "github.com/google/go-cmp/cmp" - "github.com/jarcoal/httpmock" - "github.com/linode/linodego" ) func TestAccount_getTransfer(t *testing.T) { - client := createMockClient(t) + fixtureData, err := fixtures.GetFixture("account_transfer_get") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) - desiredResponse := linodego.AccountTransfer{ - Billable: 123, - Quota: 456, - Used: 789, - RegionTransfers: []linodego.AccountTransferRegion{ - { - ID: "us-southeast", - Billable: 987, - Quota: 654, - Used: 3211, - }, - }, - } + base.MockGet("account/transfer", fixtureData) - httpmock.RegisterRegexpResponder("GET", mockRequestURL(t, "/account/transfer"), - httpmock.NewJsonResponderOrPanic(200, &desiredResponse)) + transferInfo, err := base.Client.GetAccountTransfer(context.Background()) + assert.NoError(t, err) - questions, err := client.GetAccountTransfer(context.Background()) - if err != nil { - t.Fatal(err) - } + assert.Equal(t, 0, transferInfo.Billable) + assert.Equal(t, 9141, transferInfo.Quota) + assert.Equal(t, 2, transferInfo.Used) - if !reflect.DeepEqual(*questions, desiredResponse) { - t.Fatalf("actual response does not equal desired response: %s", cmp.Diff(questions, desiredResponse)) - } + assert.Len(t, transferInfo.RegionTransfers, 1) + assert.Equal(t, "us-east", transferInfo.RegionTransfers[0].ID) + assert.Equal(t, 0, transferInfo.RegionTransfers[0].Billable) + assert.Equal(t, 5010, transferInfo.RegionTransfers[0].Quota) + assert.Equal(t, 1, transferInfo.RegionTransfers[0].Used) } diff --git a/test/unit/base.go b/test/unit/base.go index 8e24846b1..1fb2f8248 100644 --- a/test/unit/base.go +++ b/test/unit/base.go @@ -5,6 +5,7 @@ import ( "github.com/linode/linodego" "github.com/linode/linodego/internal/testutil" "github.com/stretchr/testify/mock" + "net/http" "testing" ) @@ -32,8 +33,26 @@ func (c *ClientBaseCase) TearDown(t *testing.T) { c.Mock.AssertExpectations(t) } -// MockGet mocks a GET request to the client. +// MockGet mocks a GET request to the client func (c *ClientBaseCase) MockGet(path string, response interface{}) { fullURL := c.BaseURL + path - httpmock.RegisterResponder("GET", fullURL, httpmock.NewJsonResponderOrPanic(200, response)) + httpmock.RegisterResponder("GET", fullURL, httpmock.NewJsonResponderOrPanic(http.StatusOK, response)) +} + +// MockPost mocks a POST request for a given path with the provided response body +func (c *ClientBaseCase) MockPost(path string, response interface{}) { + fullURL := c.BaseURL + path + httpmock.RegisterResponder("POST", fullURL, httpmock.NewJsonResponderOrPanic(http.StatusOK, response)) +} + +// MockPut mocks a PUT request for a given path with the provided response body +func (c *ClientBaseCase) MockPut(path string, response interface{}) { + fullURL := c.BaseURL + path + httpmock.RegisterResponder("PUT", fullURL, httpmock.NewJsonResponderOrPanic(http.StatusOK, response)) +} + +// MockDelete mocks a DELETE request for a given path with the provided response body +func (c *ClientBaseCase) MockDelete(path string, response interface{}) { + fullURL := c.BaseURL + path + httpmock.RegisterResponder("DELETE", fullURL, httpmock.NewJsonResponderOrPanic(http.StatusOK, response)) } diff --git a/test/unit/fixtures/account_child_create_token.json b/test/unit/fixtures/account_child_create_token.json new file mode 100644 index 000000000..b0e82ef23 --- /dev/null +++ b/test/unit/fixtures/account_child_create_token.json @@ -0,0 +1,8 @@ +{ + "created": "2024-05-01T00:01:01", + "expiry": "2024-05-01T00:16:01", + "id": 918, + "label": "parent1_1234_2024-05-01T00:01:01", + "scopes": "*", + "token": "abcdefghijklmnop" +} \ No newline at end of file diff --git a/test/unit/fixtures/account_child_get.json b/test/unit/fixtures/account_child_get.json new file mode 100644 index 000000000..4b52a9dbe --- /dev/null +++ b/test/unit/fixtures/account_child_get.json @@ -0,0 +1,29 @@ +{ + "active_since": "2018-01-01T00:01:01", + "address_1": "123 Main Street", + "address_2": "Suite A", + "balance": 200, + "balance_uninvoiced": 145, + "billing_source": "external", + "capabilities": [ + "Linodes", + "NodeBalancers", + "Block Storage", + "Object Storage" + ], + "city": "San Diego", + "company": "Acme", + "country": "US", + "credit_card": { + "expiry": "11/2024", + "last_four": 1111 + }, + "email": "john.smith@linode.com", + "euuid": "A1BC2DEF-34GH-567I-J890KLMN12O34P56", + "first_name": "John", + "last_name": "Smith", + "phone": "858-555-1212", + "state": "CA", + "tax_id": "ATU99999999", + "zip": "92111-1234" +} \ No newline at end of file diff --git a/test/unit/fixtures/account_child_list.json b/test/unit/fixtures/account_child_list.json new file mode 100644 index 000000000..00c284275 --- /dev/null +++ b/test/unit/fixtures/account_child_list.json @@ -0,0 +1,36 @@ +{ + "data": [ + { + "active_since": "2018-01-01T00:01:01", + "address_1": "123 Main Street", + "address_2": "Suite A", + "balance": 200, + "balance_uninvoiced": 145, + "billing_source": "external", + "capabilities": [ + "Linodes", + "NodeBalancers", + "Block Storage", + "Object Storage" + ], + "city": "San Diego", + "company": "Acme", + "country": "US", + "credit_card": { + "expiry": "11/2024", + "last_four": 1111 + }, + "email": "john.smith@linode.com", + "euuid": "A1BC2DEF-34GH-567I-J890KLMN12O34P56", + "first_name": "John", + "last_name": "Smith", + "phone": "858-555-1212", + "state": "CA", + "tax_id": "ATU99999999", + "zip": "92111-1234" + } + ], + "page": 1, + "pages": 1, + "results": 1 +} \ No newline at end of file diff --git a/test/unit/fixtures/account_transfer_get.json b/test/unit/fixtures/account_transfer_get.json new file mode 100644 index 000000000..0a8d40c5d --- /dev/null +++ b/test/unit/fixtures/account_transfer_get.json @@ -0,0 +1,13 @@ +{ + "billable": 0, + "quota": 9141, + "region_transfers": [ + { + "billable": 0, + "id": "us-east", + "quota": 5010, + "used": 1 + } + ], + "used": 2 +} \ No newline at end of file diff --git a/test/unit/fixtures/image_replicate.json b/test/unit/fixtures/image_replicate.json new file mode 100644 index 000000000..9d9042f31 --- /dev/null +++ b/test/unit/fixtures/image_replicate.json @@ -0,0 +1,31 @@ +{ + "capabilities": [ + "cloud-init", + "distributed-sites" + ], + "created": "2021-08-14T22:44:02", + "created_by": "linode", + "deprecated": false, + "description": "Example image description.", + "eol": "2026-07-01T04:00:00", + "expiry": null, + "id": "linode/debian11", + "is_public": true, + "label": "Debian 11", + "regions": [ + { + "region": "us-iad", + "status": "available" + } + ], + "size": 2500, + "status": "available", + "tags": [ + "repair-image", + "fix-1" + ], + "total_size": 1234567, + "type": "manual", + "updated": "2021-08-14T22:44:02", + "vendor": "Debian" +} \ No newline at end of file diff --git a/test/unit/fixtures/instance_stats_get.json b/test/unit/fixtures/instance_stats_get.json new file mode 100644 index 000000000..3d6aaaac9 --- /dev/null +++ b/test/unit/fixtures/instance_stats_get.json @@ -0,0 +1,44 @@ +{ + "title": "linode.com - my-linode (linode123456) - day (5 min avg)", + "data": { + "cpu": [ + [1521483600000, 0.42] + ], + "io": { + "io": [ + [1521484800000, 0.19] + ], + "swap": [ + [1521484800000, 0] + ] + }, + "netv4": { + "in": [ + [1521484800000, 2004.36] + ], + "out": [ + [1521484800000, 3928.91] + ], + "private_in": [ + [1521484800000, 0] + ], + "private_out": [ + [1521484800000, 5.6] + ] + }, + "netv6": { + "in": [ + [1521484800000, 0] + ], + "out": [ + [1521484800000, 0] + ], + "private_in": [ + [1521484800000, 195.18] + ], + "private_out": [ + [1521484800000, 5.6] + ] + } + } +} diff --git a/test/unit/images_test.go b/test/unit/images_test.go index d93353844..72894df29 100644 --- a/test/unit/images_test.go +++ b/test/unit/images_test.go @@ -2,15 +2,20 @@ package unit import ( "context" + "github.com/stretchr/testify/assert" "testing" + "time" - "github.com/jarcoal/httpmock" "github.com/linode/linodego" - "github.com/stretchr/testify/require" ) func TestImage_Replicate(t *testing.T) { - client := createMockClient(t) + fixtureData, err := fixtures.GetFixture("image_replicate") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) requestData := linodego.ImageReplicateOptions{ Regions: []string{ @@ -19,43 +24,29 @@ func TestImage_Replicate(t *testing.T) { }, } - responseData := linodego.Image{ - ID: "private/1234", - Label: "test", - Regions: []linodego.ImageRegion{ - { - Region: "us-iad", - Status: linodego.ImageRegionStatusAvailable, - }, - { - Region: "us-mia", - Status: linodego.ImageRegionStatusReplicating, - }, - { - Region: "us-ord", - Status: linodego.ImageRegionStatusPendingReplication, - }, - }, - } - - httpmock.RegisterRegexpResponder( - "POST", - mockRequestURL(t, "images/private%2F1234/regions"), - mockRequestBodyValidate(t, requestData, responseData), - ) + base.MockPost("images/private%2F1234/regions", fixtureData) - image, err := client.ReplicateImage(context.Background(), "private/1234", requestData) - require.NoError(t, err) + image, err := base.Client.ReplicateImage(context.Background(), "private/1234", requestData) + assert.NoError(t, err) - require.Equal(t, "private/1234", image.ID) - require.Equal(t, "test", image.Label) + assert.Equal(t, "linode/debian11", image.ID) + assert.Equal(t, "Debian 11", image.Label) + assert.Equal(t, "Example image description.", image.Description) + assert.Equal(t, "Debian", image.Vendor) + assert.Equal(t, true, image.IsPublic) + assert.Equal(t, false, image.Deprecated) + assert.Equal(t, "available", string(image.Status)) + assert.Equal(t, "2021-08-14T22:44:02Z", image.Created.Format(time.RFC3339)) + assert.Equal(t, "2021-08-14T22:44:02Z", image.Updated.Format(time.RFC3339)) + assert.Equal(t, "2026-07-01T04:00:00Z", image.EOL.Format(time.RFC3339)) + assert.Equal(t, 2500, image.Size) + assert.Equal(t, 1234567, image.TotalSize) - require.EqualValues(t, "us-iad", image.Regions[0].Region) - require.EqualValues(t, linodego.ImageRegionStatusAvailable, image.Regions[0].Status) + assert.ElementsMatch(t, []string{"cloud-init", "distributed-sites"}, image.Capabilities) - require.EqualValues(t, "us-mia", image.Regions[1].Region) - require.EqualValues(t, linodego.ImageRegionStatusReplicating, image.Regions[1].Status) + assert.Len(t, image.Regions, 1) + assert.Equal(t, "us-iad", image.Regions[0].Region) + assert.Equal(t, "available", string(image.Regions[0].Status)) - require.EqualValues(t, "us-ord", image.Regions[2].Region) - require.EqualValues(t, linodego.ImageRegionStatusPendingReplication, image.Regions[2].Status) + assert.ElementsMatch(t, []string{"repair-image", "fix-1"}, image.Tags) } diff --git a/test/unit/instance_stats_test.go b/test/unit/instance_stats_test.go index 03d36dc4a..3e6fe3f9f 100644 --- a/test/unit/instance_stats_test.go +++ b/test/unit/instance_stats_test.go @@ -2,49 +2,49 @@ package unit import ( "context" - "reflect" + "fmt" "testing" - "github.com/google/go-cmp/cmp" - "github.com/jarcoal/httpmock" - "github.com/linode/linodego" + "github.com/stretchr/testify/assert" ) func TestInstanceStats_Get(t *testing.T) { - client := createMockClient(t) - - desiredResponse := linodego.InstanceStats{ - Title: "test_title", - Data: linodego.InstanceStatsData{ - CPU: [][]float64{}, - IO: linodego.StatsIO{ - IO: [][]float64{{1.2, 2.3}, {3.4, 4.5}}, - Swap: [][]float64{{14, 2.3}, {34, 4.5}}, - }, - NetV4: linodego.StatsNet{ - In: [][]float64{{1.2, 2.3}, {3.4, 4.5}}, - Out: [][]float64{{1, 2}, {3, 4}}, - PrivateIn: [][]float64{{2, 3}, {4, 5}}, - PrivateOut: [][]float64{{12.1, 2.33}, {4.4, 4.5}}, - }, - NetV6: linodego.StatsNet{ - In: [][]float64{{1.2, .3}, {3.4, .5}}, - Out: [][]float64{{0, 2.3}, {3, 4.55}}, - PrivateIn: [][]float64{{1.24, 3}, {3, 5}}, - PrivateOut: [][]float64{{1, 6}, {7, 8}}, - }, - }, - } - - httpmock.RegisterRegexpResponder("GET", mockRequestURL(t, "/instances/36183732/stats"), - httpmock.NewJsonResponderOrPanic(200, &desiredResponse)) - - questions, err := client.GetInstanceStats(context.Background(), 36183732) - if err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(*questions, desiredResponse) { - t.Fatalf("actual response does not equal desired response: %s", cmp.Diff(questions, desiredResponse)) - } + fixtureData, err := fixtures.GetFixture("instance_stats_get") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("linode/instances/36183732/stats", fixtureData) + + stats, err := base.Client.GetInstanceStats(context.Background(), 36183732) + assert.NoError(t, err) + + assert.Equal(t, "linode.com - my-linode (linode123456) - day (5 min avg)", stats.Title) + + fmt.Printf("Stats: %+v\n", stats) //TODO:: Debug for assertion remove later + + assert.Len(t, stats.Data.CPU, 1) + + assert.Len(t, stats.Data.IO.IO, 1) + assert.Len(t, stats.Data.IO.Swap, 1) + + assert.Len(t, stats.Data.NetV4.In, 1) + assert.Len(t, stats.Data.NetV4.Out, 1) + assert.Len(t, stats.Data.NetV4.PrivateIn, 1) + assert.Len(t, stats.Data.NetV4.PrivateOut, 1) + + assert.Len(t, stats.Data.NetV6.In, 1) + assert.Len(t, stats.Data.NetV6.Out, 1) + assert.Len(t, stats.Data.NetV6.PrivateIn, 1) + assert.Len(t, stats.Data.NetV6.PrivateOut, 1) + + assert.Equal(t, 0.42, stats.Data.CPU[0][1]) + assert.Equal(t, 0.19, stats.Data.IO.IO[0][1]) + assert.Equal(t, 0.0, stats.Data.IO.Swap[0][1]) + assert.Equal(t, 2004.36, stats.Data.NetV4.In[0][1]) + assert.Equal(t, 3928.91, stats.Data.NetV4.Out[0][1]) + assert.Equal(t, 195.18, stats.Data.NetV6.PrivateIn[0][1]) + assert.Equal(t, 5.6, stats.Data.NetV6.PrivateOut[0][1]) } diff --git a/test/unit/instance_test.go b/test/unit/instance_test.go index 887b3501b..790e90f48 100644 --- a/test/unit/instance_test.go +++ b/test/unit/instance_test.go @@ -8,11 +8,9 @@ import ( ) func TestListInstances(t *testing.T) { - // Initialize the TestFixtures to load the fixture fixtures := NewTestFixtures() - // Mock the expected response from the ListInstances endpoint - fixtureData, err := fixtures.GetFixture("linodes_list") // Use the correct fixture name without ".json" + fixtureData, err := fixtures.GetFixture("linodes_list") if err != nil { t.Fatalf("Failed to load fixture: %v", err) } @@ -32,13 +30,8 @@ func TestListInstances(t *testing.T) { linode := instances[0] assert.Equal(t, 123, linode.ID) assert.Equal(t, "linode123", linode.Label) - - // Fix for the status comparison assert.Equal(t, "running", string(linode.Status)) - - // Fix for the IP address comparison assert.Equal(t, "203.0.113.1", linode.IPv4[0].String()) - assert.Equal(t, "g6-standard-1", linode.Type) assert.Equal(t, "us-east", linode.Region) assert.Equal(t, 4096, linode.Specs.Memory) From 8b4007c3a88248ed6ecc464f6af13cd8e882a12a Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Tue, 15 Oct 2024 14:17:22 -0700 Subject: [PATCH 05/11] migrate profile grants, tfa tcs and create fixtures --- test/unit/fixtures/profile_grants_list.json | 96 ++++++++++++ .../profile_security_question_answer.json | 9 ++ .../profile_security_question_list.json | 9 ++ .../fixtures/profile_two_factor_enable.json | 3 + .../profile_two_factor_secret_create.json | 4 + test/unit/profile_grants_list_test.go | 137 +++++------------- test/unit/profile_security_questions_test.go | 34 ++--- test/unit/profile_tfa_test.go | 48 +++--- 8 files changed, 191 insertions(+), 149 deletions(-) create mode 100644 test/unit/fixtures/profile_grants_list.json create mode 100644 test/unit/fixtures/profile_security_question_answer.json create mode 100644 test/unit/fixtures/profile_security_question_list.json create mode 100644 test/unit/fixtures/profile_two_factor_enable.json create mode 100644 test/unit/fixtures/profile_two_factor_secret_create.json diff --git a/test/unit/fixtures/profile_grants_list.json b/test/unit/fixtures/profile_grants_list.json new file mode 100644 index 000000000..dc3913d1c --- /dev/null +++ b/test/unit/fixtures/profile_grants_list.json @@ -0,0 +1,96 @@ +{ + "database": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "domain": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "firewall": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "global": { + "account_access": "read_only", + "add_databases": true, + "add_domains": true, + "add_firewalls": true, + "add_images": true, + "add_linodes": true, + "add_longview": true, + "add_nodebalancers": true, + "add_placement_groups": true, + "add_stackscripts": true, + "add_volumes": true, + "add_vpcs": true, + "cancel_account": false, + "child_account_access": true, + "longview_subscription": true + }, + "image": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "linode": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "longview": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "nodebalancer": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "placement_group": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "stackscript": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "volume": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "vpc": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ] +} \ No newline at end of file diff --git a/test/unit/fixtures/profile_security_question_answer.json b/test/unit/fixtures/profile_security_question_answer.json new file mode 100644 index 000000000..9b4212f34 --- /dev/null +++ b/test/unit/fixtures/profile_security_question_answer.json @@ -0,0 +1,9 @@ +{ + "security_questions": [ + { + "question_id": 1, + "response": "Gotham City", + "security_question": "In what city were you born?" + } + ] +} \ No newline at end of file diff --git a/test/unit/fixtures/profile_security_question_list.json b/test/unit/fixtures/profile_security_question_list.json new file mode 100644 index 000000000..87207990f --- /dev/null +++ b/test/unit/fixtures/profile_security_question_list.json @@ -0,0 +1,9 @@ +{ + "security_questions": [ + { + "id": 1, + "question": "In what city were you born?", + "response": "Gotham City" + } + ] +} \ No newline at end of file diff --git a/test/unit/fixtures/profile_two_factor_enable.json b/test/unit/fixtures/profile_two_factor_enable.json new file mode 100644 index 000000000..8fe968d80 --- /dev/null +++ b/test/unit/fixtures/profile_two_factor_enable.json @@ -0,0 +1,3 @@ +{ + "scratch": "reallycoolandlegittfacode" +} \ No newline at end of file diff --git a/test/unit/fixtures/profile_two_factor_secret_create.json b/test/unit/fixtures/profile_two_factor_secret_create.json new file mode 100644 index 000000000..1e886a7b0 --- /dev/null +++ b/test/unit/fixtures/profile_two_factor_secret_create.json @@ -0,0 +1,4 @@ +{ + "expiry": "2018-03-01T00:01:01", + "secret": "5FXX6KLACOC33GTC" +} \ No newline at end of file diff --git a/test/unit/profile_grants_list_test.go b/test/unit/profile_grants_list_test.go index c3817af63..5fda2a48e 100644 --- a/test/unit/profile_grants_list_test.go +++ b/test/unit/profile_grants_list_test.go @@ -2,113 +2,46 @@ package unit import ( "context" - "reflect" + "github.com/stretchr/testify/assert" "testing" - - "github.com/google/go-cmp/cmp" - "github.com/jarcoal/httpmock" - "github.com/linode/linodego" ) func TestGrantsList(t *testing.T) { - // username := usernamePrefix + "grantslist" - client := createMockClient(t) - accessLevel := linodego.AccessLevelReadOnly - desiredResponse := linodego.GrantsListResponse{ - Database: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_write", - }, - }, - Domain: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_only", - }, - }, - Firewall: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_only", - }, - }, - Image: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_only", - }, - }, - Linode: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_write", - }, - }, - Longview: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_write", - }, - }, - NodeBalancer: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_only", - }, - }, - StackScript: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_only", - }, - }, - Volume: []linodego.GrantedEntity{ - { - ID: 1, - Label: "example-entity-label", - Permissions: "read_only", - }, - }, + fixtureData, err := fixtures.GetFixture("profile_grants_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("profile/grants", fixtureData) + + grants, err := base.Client.GrantsList(context.Background()) + assert.NoError(t, err) + + assert.Equal(t, "read_only", string(*grants.Global.AccountAccess)) + assert.True(t, grants.Global.AddDatabases) + assert.True(t, grants.Global.AddDomains) + assert.True(t, grants.Global.AddFirewalls) + assert.False(t, grants.Global.CancelAccount) + + assert.Len(t, grants.Database, 1) + assert.Equal(t, 123, grants.Database[0].ID) + assert.Equal(t, "example-entity", grants.Database[0].Label) + assert.Equal(t, "read_only", string(grants.Database[0].Permissions)) - Global: linodego.GlobalUserGrants{ - AccountAccess: &accessLevel, - AddDomains: false, - AddDatabases: true, - AddFirewalls: false, - AddImages: true, - AddLinodes: true, - AddLongview: true, - AddNodeBalancers: true, - AddStackScripts: true, - AddVolumes: false, - CancelAccount: false, - LongviewSubscription: true, - }, - } + assert.Len(t, grants.Domain, 1) + assert.Equal(t, 123, grants.Domain[0].ID) + assert.Equal(t, "example-entity", grants.Domain[0].Label) + assert.Equal(t, "read_only", string(grants.Domain[0].Permissions)) - httpmock.RegisterRegexpResponder( - "GET", - mockRequestURL(t, "/profile/grants"), - httpmock.NewJsonResponderOrPanic(200, &desiredResponse), - ) - grants, err := client.GrantsList(context.Background()) - if err != nil { - t.Fatal(err) - } + assert.Len(t, grants.Firewall, 1) + assert.Equal(t, 123, grants.Firewall[0].ID) + assert.Equal(t, "example-entity", grants.Firewall[0].Label) + assert.Equal(t, "read_only", string(grants.Firewall[0].Permissions)) - if !reflect.DeepEqual(*grants, desiredResponse) { - t.Fatalf( - "actual response does not equal desired response: %s", - cmp.Diff(grants, desiredResponse), - ) - } + assert.Len(t, grants.Linode, 1) + assert.Equal(t, 123, grants.Linode[0].ID) + assert.Equal(t, "example-entity", grants.Linode[0].Label) + assert.Equal(t, "read_only", string(grants.Linode[0].Permissions)) } diff --git a/test/unit/profile_security_questions_test.go b/test/unit/profile_security_questions_test.go index 5940e25d3..c9af32d56 100644 --- a/test/unit/profile_security_questions_test.go +++ b/test/unit/profile_security_questions_test.go @@ -2,38 +2,30 @@ package unit import ( "context" - "reflect" + "github.com/stretchr/testify/assert" "testing" - "github.com/google/go-cmp/cmp" "github.com/jarcoal/httpmock" "github.com/linode/linodego" ) func TestSecurityQuestions_List(t *testing.T) { - client := createMockClient(t) + fixtureData, err := fixtures.GetFixture("profile_security_question_list") + assert.NoError(t, err) - desiredResponse := linodego.SecurityQuestionsListResponse{ - SecurityQuestions: []linodego.SecurityQuestion{ - { - ID: 1, - Question: "Really cool question", - Response: "uhhhh", - }, - }, - } + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) - httpmock.RegisterRegexpResponder("GET", mockRequestURL(t, "/profile/security-questions"), - httpmock.NewJsonResponderOrPanic(200, &desiredResponse)) + base.MockGet("profile/security-questions", fixtureData) - questions, err := client.SecurityQuestionsList(context.Background()) - if err != nil { - t.Fatal(err) - } + securityQuestions, err := base.Client.SecurityQuestionsList(context.Background()) + assert.NoError(t, err) - if !reflect.DeepEqual(*questions, desiredResponse) { - t.Fatalf("actual response does not equal desired response: %s", cmp.Diff(questions, desiredResponse)) - } + assert.Len(t, securityQuestions.SecurityQuestions, 1) + assert.Equal(t, 1, securityQuestions.SecurityQuestions[0].ID) + assert.Equal(t, "In what city were you born?", securityQuestions.SecurityQuestions[0].Question) + assert.Equal(t, "Gotham City", securityQuestions.SecurityQuestions[0].Response) } func TestSecurityQuestions_Answer(t *testing.T) { diff --git a/test/unit/profile_tfa_test.go b/test/unit/profile_tfa_test.go index 85227a886..f8ef40075 100644 --- a/test/unit/profile_tfa_test.go +++ b/test/unit/profile_tfa_test.go @@ -2,32 +2,29 @@ package unit import ( "context" - "reflect" + "github.com/stretchr/testify/assert" "testing" + "time" - "github.com/google/go-cmp/cmp" "github.com/jarcoal/httpmock" "github.com/linode/linodego" ) func TestTwoFactor_CreateSecret_smoke(t *testing.T) { - client := createMockClient(t) + fixtureData, err := fixtures.GetFixture("profile_two_factor_secret_create") + assert.NoError(t, err) - expectedResponse := linodego.TwoFactorSecret{ - Secret: "verysecureverysecureverysecure", - } + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) - httpmock.RegisterRegexpResponder("POST", mockRequestURL(t, "/profile/tfa-enable"), - httpmock.NewJsonResponderOrPanic(200, expectedResponse)) + base.MockPost("profile/tfa-enable", fixtureData) - secret, err := client.CreateTwoFactorSecret(context.Background()) - if err != nil { - t.Fatal(err) - } + secret, err := base.Client.CreateTwoFactorSecret(context.Background()) + assert.NoError(t, err) - if !reflect.DeepEqual(*secret, expectedResponse) { - t.Fatalf("returned value did not match expected response: %s", cmp.Diff(*secret, expectedResponse)) - } + assert.Equal(t, time.Time(time.Date(2018, time.March, 1, 0, 1, 1, 0, time.UTC)), *secret.Expiry) + assert.Equal(t, "5FXX6KLACOC33GTC", secret.Secret) } func TestTwoFactor_Disable(t *testing.T) { @@ -42,20 +39,19 @@ func TestTwoFactor_Disable(t *testing.T) { } func TestTwoFactor_Confirm(t *testing.T) { - client := createMockClient(t) + fixtureData, err := fixtures.GetFixture("profile_two_factor_enable") + assert.NoError(t, err) request := linodego.ConfirmTwoFactorOptions{TFACode: "reallycoolandlegittfacode"} - response := linodego.ConfirmTwoFactorResponse{Scratch: "really cool scratch code"} - httpmock.RegisterRegexpResponder("POST", mockRequestURL(t, "/profile/tfa-enable-confirm"), - mockRequestBodyValidate(t, request, response)) + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) - runResult, err := client.ConfirmTwoFactor(context.Background(), request) - if err != nil { - t.Fatal(err) - } + base.MockPost("profile/tfa-enable-confirm", fixtureData) - if !reflect.DeepEqual(*runResult, response) { - t.Fatalf("actual response does not equal desired response: %s", cmp.Diff(*runResult, response)) - } + response, err := base.Client.ConfirmTwoFactor(context.Background(), request) + assert.NoError(t, err) + + assert.Equal(t, "reallycoolandlegittfacode", response.Scratch) } From 94c6df46e64ebf6125c371fce5d384305b978bc5 Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Tue, 22 Oct 2024 08:39:12 -0700 Subject: [PATCH 06/11] go mod tidy --- test/go.mod | 1 + test/go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/test/go.mod b/test/go.mod index e7cbba158..abb9a08b2 100644 --- a/test/go.mod +++ b/test/go.mod @@ -34,6 +34,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.2 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.19.0 // indirect diff --git a/test/go.sum b/test/go.sum index 14c05dac1..204273b33 100644 --- a/test/go.sum +++ b/test/go.sum @@ -76,6 +76,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= From a2790987bc4a8272f38ac5ce3d85eb8baa75af1c Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Tue, 22 Oct 2024 08:42:31 -0700 Subject: [PATCH 07/11] go mod tidy --- go.work.sum | 8 ++------ test/go.mod | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.work.sum b/go.work.sum index a14e3036b..9f606b521 100644 --- a/go.work.sum +++ b/go.work.sum @@ -29,8 +29,6 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= @@ -47,11 +45,9 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= diff --git a/test/go.mod b/test/go.mod index 2be942017..15a9876f7 100644 --- a/test/go.mod +++ b/test/go.mod @@ -34,11 +34,9 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.2 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/term v0.25.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/protobuf v1.33.0 // indirect From 431d1647d603e28a24b5db09796c3d074c08df8b Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Tue, 22 Oct 2024 09:29:00 -0700 Subject: [PATCH 08/11] active_since field update --- account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account.go b/account.go index 6a3c65fb5..ef8588ef1 100644 --- a/account.go +++ b/account.go @@ -53,7 +53,7 @@ func (account *Account) UnmarshalJSON(b []byte) error { // CreditCard information associated with the Account. type CreditCard struct { - LastFour int `json:"last_four"` + LastFour string `json:"last_four"` Expiry string `json:"expiry"` } From 68f3e386e8a0f5bb66f57e7bb23ce928b66dd59b Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Tue, 22 Oct 2024 09:34:04 -0700 Subject: [PATCH 09/11] update variable type and assertion --- test/unit/account_child_test.go | 2 +- test/unit/fixtures/account_child_get.json | 2 +- test/unit/fixtures/account_child_list.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/account_child_test.go b/test/unit/account_child_test.go index 72b4aeb21..478f73a5a 100644 --- a/test/unit/account_child_test.go +++ b/test/unit/account_child_test.go @@ -77,7 +77,7 @@ func TestAccountChild_get(t *testing.T) { if account.CreditCard != nil { assert.Equal(t, "11/2024", account.CreditCard.Expiry) - assert.Equal(t, 1111, account.CreditCard.LastFour) + assert.Equal(t, "1111", account.CreditCard.LastFour) } assert.Equal(t, "A1BC2DEF-34GH-567I-J890KLMN12O34P56", account.EUUID) diff --git a/test/unit/fixtures/account_child_get.json b/test/unit/fixtures/account_child_get.json index 4b52a9dbe..7475311db 100644 --- a/test/unit/fixtures/account_child_get.json +++ b/test/unit/fixtures/account_child_get.json @@ -16,7 +16,7 @@ "country": "US", "credit_card": { "expiry": "11/2024", - "last_four": 1111 + "last_four": "1111" }, "email": "john.smith@linode.com", "euuid": "A1BC2DEF-34GH-567I-J890KLMN12O34P56", diff --git a/test/unit/fixtures/account_child_list.json b/test/unit/fixtures/account_child_list.json index 00c284275..53de71d5b 100644 --- a/test/unit/fixtures/account_child_list.json +++ b/test/unit/fixtures/account_child_list.json @@ -18,7 +18,7 @@ "country": "US", "credit_card": { "expiry": "11/2024", - "last_four": 1111 + "last_four": "1111" }, "email": "john.smith@linode.com", "euuid": "A1BC2DEF-34GH-567I-J890KLMN12O34P56", From b820b90f0e26f44ee8974f6f404af6bffb52c36d Mon Sep 17 00:00:00 2001 From: Youjung Kim <126618609+ykim-1@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:46:10 -0700 Subject: [PATCH 10/11] Update test/unit/fixtures.go Co-authored-by: Lena Garber <114949949+lgarber-akamai@users.noreply.github.com> --- test/unit/fixtures.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/fixtures.go b/test/unit/fixtures.go index fb59847e3..b113a9f8a 100644 --- a/test/unit/fixtures.go +++ b/test/unit/fixtures.go @@ -45,7 +45,7 @@ func (tf *TestFixtures) loadFixtures() { } // Remove ".json" from the file name - fixtureName := entry.Name()[:len(entry.Name())-5] + fixtureName := strings.TrimSuffix(entry.Name(), ".json") tf.fixtures[fixtureName] = jsonData } } From 8327f62946029bca708f374a54c883424de0d0cb Mon Sep 17 00:00:00 2001 From: ykim-1 Date: Tue, 22 Oct 2024 13:48:41 -0700 Subject: [PATCH 11/11] change to trim suffix on fixtureName --- test/unit/fixtures.go | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/fixtures.go b/test/unit/fixtures.go index b113a9f8a..0bc17346c 100644 --- a/test/unit/fixtures.go +++ b/test/unit/fixtures.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "path/filepath" + "strings" ) //go:embed fixtures/*.json