Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
39 changes: 39 additions & 0 deletions test/unit/base.go
Original file line number Diff line number Diff line change
@@ -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))
}
59 changes: 59 additions & 0 deletions test/unit/fixtures.go
Original file line number Diff line number Diff line change
@@ -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() {
Copy link
Contributor

@lgarber-akamai lgarber-akamai Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional: One other potential way to handle this would be using the embed directive with the embed.FS type. I think the current implementation is perfectly acceptable too, just figured I'd share another potential approach 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate the feedback. I wasn't aware of this option at all, but it seems like a great improvement to implement. This change should enhance performance as the test framework scales with additional tests and components 👍

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
}
60 changes: 60 additions & 0 deletions test/unit/fixtures/linodes_list.json
Original file line number Diff line number Diff line change
@@ -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
}
45 changes: 45 additions & 0 deletions test/unit/instance_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
Loading