package internal import ( "fmt" "io" "net/http" "net/http/httptest" "net/url" "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) const testAPIKey = "secret" func TestClient_GetZones(t *testing.T) { client := setupTest(t, "/user/v1/zones", testHandler(http.MethodGet, http.StatusOK, "zones.json")) zones, err := client.GetZones("", 100, 0) require.NoError(t, err) expected := []Zone{ { ID: 10, Name: "user1.ch", Email: "test@hosttech.ch", TTL: 10800, Nameserver: "ns1.hosttech.ch", Dnssec: false, DnssecEmail: "test@hosttech.ch", }, } assert.Equal(t, expected, zones) } func TestClient_GetZones_error(t *testing.T) { client := setupTest(t, "/user/v1/zones", testHandler(http.MethodGet, http.StatusUnauthorized, "error.json")) _, err := client.GetZones("", 100, 0) require.Error(t, err) } func TestClient_GetZone(t *testing.T) { client := setupTest(t, "/user/v1/zones/123", testHandler(http.MethodGet, http.StatusOK, "zone.json")) zone, err := client.GetZone("123") require.NoError(t, err) expected := &Zone{ ID: 10, Name: "user1.ch", Email: "test@hosttech.ch", TTL: 10800, Nameserver: "ns1.hosttech.ch", Dnssec: false, DnssecEmail: "test@hosttech.ch", } assert.Equal(t, expected, zone) } func TestClient_GetZone_error(t *testing.T) { client := setupTest(t, "/user/v1/zones/123", testHandler(http.MethodGet, http.StatusUnauthorized, "error.json")) _, err := client.GetZone("123") require.Error(t, err) } func TestClient_GetRecords(t *testing.T) { client := setupTest(t, "/user/v1/zones/123/records", testHandler(http.MethodGet, http.StatusOK, "records.json")) records, err := client.GetRecords("123", "TXT") require.NoError(t, err) expected := []Record{ { ID: 10, Type: "A", Name: "www", TTL: 3600, Comment: "my first record", }, { ID: 11, Type: "AAAA", Name: "www", TTL: 3600, Comment: "my first record", }, { ID: 12, Type: "CAA", TTL: 3600, Comment: "my first record", }, { ID: 13, Type: "CNAME", Name: "www", TTL: 3600, Comment: "my first record", }, { ID: 14, Type: "MX", Name: "mail.example.com", TTL: 3600, Comment: "my first record", }, { ID: 14, Type: "NS", Name: "ns1.example.com", TTL: 3600, Comment: "my first record", }, { ID: 15, Type: "PTR", Name: "smtp.example.com", TTL: 3600, Comment: "my first record", }, { ID: 16, Type: "SRV", TTL: 3600, Comment: "my first record", }, { ID: 17, Type: "TXT", Text: "v=spf1 ip4:1.2.3.4/32 -all", TTL: 3600, Comment: "my first record", }, { ID: 17, Type: "TLSA", Text: "0 0 1 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971", TTL: 3600, Comment: "my first record", }, } assert.Equal(t, expected, records) } func TestClient_GetRecords_error(t *testing.T) { client := setupTest(t, "/user/v1/zones/123/records", testHandler(http.MethodGet, http.StatusUnauthorized, "error.json")) _, err := client.GetRecords("123", "TXT") require.Error(t, err) } func TestClient_AddRecord(t *testing.T) { client := setupTest(t, "/user/v1/zones/123/records", testHandler(http.MethodPost, http.StatusCreated, "record.json")) record := Record{ Type: "TXT", Name: "lego", Text: "content", TTL: 3600, Comment: "example", } newRecord, err := client.AddRecord("123", record) require.NoError(t, err) expected := &Record{ ID: 10, Type: "TXT", Name: "lego", Text: "content", TTL: 3600, Comment: "example", } assert.Equal(t, expected, newRecord) } func TestClient_AddRecord_error(t *testing.T) { client := setupTest(t, "/user/v1/zones/123/records", testHandler(http.MethodPost, http.StatusUnauthorized, "error-details.json")) record := Record{ Type: "TXT", Name: "lego", Text: "content", TTL: 3600, Comment: "example", } _, err := client.AddRecord("123", record) require.Error(t, err) } func TestClient_DeleteRecord(t *testing.T) { client := setupTest(t, "/user/v1/zones/123/records/6", testHandler(http.MethodDelete, http.StatusUnauthorized, "error.json")) err := client.DeleteRecord("123", "6") require.Error(t, err) } func TestClient_DeleteRecord_error(t *testing.T) { client := setupTest(t, "/user/v1/zones/123/records/6", testHandler(http.MethodDelete, http.StatusNoContent, "")) err := client.DeleteRecord("123", "6") require.NoError(t, err) } func setupTest(t *testing.T, path string, handler http.Handler) *Client { t.Helper() mux := http.NewServeMux() server := httptest.NewServer(mux) t.Cleanup(server.Close) mux.Handle(path, handler) client := NewClient(testAPIKey) client.baseURL, _ = url.Parse(server.URL) return client } func testHandler(method string, statusCode int, filename string) http.HandlerFunc { return func(rw http.ResponseWriter, req *http.Request) { if req.Method != method { http.Error(rw, fmt.Sprintf(`{"message":"unsupported method: %s"}`, req.Method), http.StatusMethodNotAllowed) return } if req.Header.Get("Authorization") != "Bearer "+testAPIKey { http.Error(rw, `{"message":"Unauthenticated"}`, http.StatusUnauthorized) return } rw.WriteHeader(statusCode) if statusCode == http.StatusNoContent { return } file, err := os.Open(filepath.Join("fixtures", filename)) if err != nil { http.Error(rw, fmt.Sprintf(`{"message":"%v"}`, err), http.StatusInternalServerError) return } defer func() { _ = file.Close() }() _, err = io.Copy(rw, file) if err != nil { http.Error(rw, fmt.Sprintf(`{"message":"%v"}`, err), http.StatusInternalServerError) return } } }