You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sp9rk/action/actions_test.go

619 lines
25 KiB

package action_test
import (
"io"
"net/http"
"net/http/httptest"
"os"
"path"
"strings"
"testing"
"github.com/gabehf/sp9rk/action"
"github.com/gabehf/sp9rk/app"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v3"
)
// pretty much all the other tests rely on this test working...
// i know its bad practice but I dont want to manually create every mock app and request files
// manually every time i make the test.
//
// Basically, if this test fails, fix it FIRST.
func TestWriteFiles(t *testing.T) {
cfgPath := path.Join("TestActionWriteFiles", ".sp9rk", "tests")
err := action.WriteAppFiles(cfgPath, &action.AppInfo{
Version: "1",
Name: "TestApp",
Description: "test app",
Host: "localhost",
})
assert.NoError(t, err, "FIX FIRST: failed to write app files")
p := action.AppPath(cfgPath, "TestApp")
_, err = os.Stat(p)
assert.NoError(t, err, "failed to create app directory")
_, err = os.Stat(path.Join(p, ".appinfo"))
assert.NoError(t, err, "failed to create .appinfo file")
err = action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Version: "1",
Name: "MyReq",
Description: "my request",
})
assert.NoError(t, err, "FIX FIRST: failed to write request file")
_, err = os.Stat(path.Join(p, "MyReq.yml"))
assert.NoError(t, err, "failed to stat request file")
os.RemoveAll("TestActionWriteFiles")
}
func TestActionCreateApplication(t *testing.T) {
cfgPath := path.Join("TestActionCreateApplication", ".sp9rk", "tests")
app := app.New(cfgPath, http.Client{})
assert.Error(
t,
RunWithArgs(app, "create", "app"),
"create app should fail with no args",
)
assert.Error(
t,
RunWithArgs(app, "create", "app", "-u", "hostname123", "../malicious/path"),
"create app should fail invalid name",
)
assert.Error(
t,
RunWithArgs(app, "create", "app", "-u", "hostname123", "TestApp", "secondArgument"),
"create app should fail with >1 args",
)
assert.NoError(
t,
RunWithArgs(app, "create", "app", "-u", "hostname123", "TestApp"),
"create app should succeed with 1 args",
)
assert.Error(
t,
RunWithArgs(app, "create", "app", "-u", "hostname123", "TestApp"),
"create app should fail when app already exists",
)
// cleanup
os.RemoveAll("TestActionCreateApplication")
}
func TestActionCreateRequest(t *testing.T) {
cfgPath := path.Join("TestActionCreateRequest", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestAppTwo",
})
// tests
app := app.New(cfgPath, http.Client{})
assert.Error(t, RunWithArgs(app, "create", "req"), "create req should fail with no args")
assert.Error(t, RunWithArgs(app, "create", "req", "TestReq"), "create req should fail with no default app")
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
assert.NoError(t, RunWithArgs(app, "create", "req", "TestReq"), "create req should succeed with default app")
assert.Error(t, RunWithArgs(app, "create", "req", "TestReq", "SecondArg"), "create req should fail with >1 args")
assert.NoError(t, RunWithArgs(app, "create", "req", "-a", "TestAppTwo", "TestReq"), "create req should succeed with specified app")
assert.Error(t, RunWithArgs(app, "create", "req", "-a", "TestAppThree", "TestReq"), "create req should fail with unknown app")
assert.Error(t, RunWithArgs(app, "create", "req", "../malicious/path"), "create req should fail invalid name")
assert.Error(t, RunWithArgs(app, "create", "req", "-a", "TestAppTwo", "TestReq"), "create req should fail if it already exists")
contents, _ := os.ReadFile(path.Join(action.AppPath(cfgPath, "TestApp"), "TestReq.yml"))
reqinfo := new(action.RequestInfo)
err := yaml.Unmarshal(contents, reqinfo)
assert.NoError(t, err, "contents should be YAML")
assert.EqualValues(t, reqinfo.Name, "TestReq")
assert.EqualValues(t, reqinfo.Description, "")
assert.EqualValues(t, reqinfo.Method, "GET")
assert.EqualValues(t, reqinfo.Path, "/")
assert.EqualValues(t, reqinfo.Body, "")
assert.Empty(t, reqinfo.Headers)
// flag tests
assert.NoError(
t,
RunWithArgs(app, "create", "req",
"-d", "description",
"-X", "POST",
"-p", "/path",
"-b", "request body",
"-H", "X-Header-One: 1",
"-H", "X-Header-Two: 2",
"TestReqTwo",
),
"create req should succeed with flags",
)
contents, _ = os.ReadFile(path.Join(action.AppPath(cfgPath, "TestApp"), "TestReqTwo.yml"))
reqinfo = new(action.RequestInfo)
err = yaml.Unmarshal(contents, reqinfo)
assert.NoError(t, err, "contents should be YAML")
if reqinfo.Headers == nil || len(reqinfo.Headers) < 2 {
assert.FailNow(t, "file contents were not parsed successfully")
}
assert.EqualValues(t, reqinfo.Name, "TestReqTwo")
assert.EqualValues(t, reqinfo.Description, "description")
assert.EqualValues(t, reqinfo.Method, "POST")
assert.EqualValues(t, reqinfo.Path, "/path")
assert.EqualValues(t, reqinfo.Body, "request body")
assert.EqualValues(t, reqinfo.Headers[0], "X-Header-One: 1")
assert.EqualValues(t, reqinfo.Headers[1], "X-Header-Two: 2")
// cleanup
os.RemoveAll("TestActionCreateRequest")
}
func TestActionSwitch(t *testing.T) {
cfgPath := path.Join("TestActionSwitch", ".sp9rk", "tests")
app := app.New(cfgPath, http.Client{})
assert.Error(t, RunWithArgs(app, "switch"), "switch should fail with no args")
assert.Error(t, RunWithArgs(app, "switch", "TestApp"), "switch should fail with no apps existing")
// simulate apps being created and one set as default
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestAppTwo",
})
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
// tests
assert.Error(t, RunWithArgs(app, "switch"), "switch should fail with no args")
output, err := captureOutput(RunWithArgs, app, "switch", "TestApp")
assert.NoError(t, err, "switch should NOT fail with existing app")
assert.Equal(t, "TestApp", output, "switch output should be equal to new app name on success")
assert.Error(t, RunWithArgs(app, "switch", "../malicious/path"), "switch should fail invalid name")
assert.Error(t, RunWithArgs(app, "switch", "TestApp", "somethingElse"), "switch should fail with >1 arg")
assert.Error(t, RunWithArgs(app, "switch", "NotRealApp"), "switch should fail with unknown app")
os.RemoveAll("TestActionSwitch")
}
func TestActionDeleteApp(t *testing.T) {
cfgPath := path.Join("TestActionDeleteApp", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
Description: "this is a very cool app that does cool stuff",
Host: "http://localhost:3000",
})
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestAppTwo",
Description: "this is another very cool app that does cool stuff",
Host: "http://localhost:3001",
})
// tests
app := app.New(cfgPath, http.Client{})
assert.Error(t, RunWithArgs(app, "delete", "app"), "delete app should fail with no args")
assert.NoError(t, RunWithArgs(app, "delete", "app", "--confirm", "TestApp"), "delete app should NOT fail with existing app")
assert.Error(t, RunWithArgs(app, "delete", "app", "../malicious/path"), "delete app should fail invalid name")
assert.Error(t, RunWithArgs(app, "delete", "app", "TestAppTwo", "somethingElse"), "delete app should fail with >1 arg")
assert.Error(t, RunWithArgs(app, "delete", "app", "NotRealApp"), "delete app should fail with unknown app")
assert.NoError(t, RunWithArgs(app, "delete", "app", "--confirm", "TestAppTwo"), "delete app should NOT fail with existing app")
assert.Error(t, RunWithArgs(app, "delete", "app", "TestAppTwo"), "delete app should fail with deleted app")
os.RemoveAll("TestActionDeleteApp")
}
func TestActionDeleteRequest(t *testing.T) {
cfgPath := path.Join("TestActionDeleteRequest", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
Description: "this is a very cool app that does cool stuff",
Host: "http://localhost:3000",
})
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestAppTwo",
Description: "this is a very cool app that does cool stuff",
Host: "http://localhost:3001",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Version: "1",
Name: "MyReq",
})
action.WriteRequestFiles(cfgPath, "TestAppTwo", &action.RequestInfo{
Version: "1",
Name: "AnotherReq",
})
// tests
app := app.New(cfgPath, http.Client{})
assert.Error(t, RunWithArgs(app, "delete", "req"), "delete req should fail with no args")
assert.Error(t, RunWithArgs(app, "delete", "req", "--confirm", "MyReq"), "delete req should fail with no default app")
assert.NoError(t, RunWithArgs(app, "delete", "req", "--confirm", "-a", "TestApp", "MyReq"), "delete req should NOT fail with existing req")
assert.Error(t, RunWithArgs(app, "delete", "req", "-a", "TestApp", "MyReq"), "delete req should fail with deleted req")
assert.Error(t, RunWithArgs(app, "delete", "req", "-a", "TestApp", "../malicious/path"), "delete req should fail invalid name")
// create default app
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestAppTwo"), 0700)
assert.Error(t, RunWithArgs(app, "delete", "req", "AnotherReq", "somethingElse"), "delete req should fail with >1 arg")
assert.Error(t, RunWithArgs(app, "delete", "req", "NotRealApp"), "delete req should fail with unknown req")
assert.NoError(t, RunWithArgs(app, "delete", "req", "--confirm", "AnotherReq"), "delete req should NOT fail with default app and existing req")
assert.Error(t, RunWithArgs(app, "delete", "req", "AnotherReq"), "delete req should fail with deleted req")
os.RemoveAll("TestActionDeleteRequest")
// tests
}
func TestActionEditApp(t *testing.T) {
cfgPath := path.Join("TestActionEditApp", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
// tests
app := app.New(cfgPath, http.Client{})
assert.NoError(t,
RunWithArgs(app, "edit", "app", "-d", "new description", "-u", "http://123.456.789", "TestApp"),
"edit app should not fail with 1 arg and flags",
)
contents, err := os.ReadFile(action.AppInfoFilePath(cfgPath, "TestApp"))
assert.NoError(t, err, "new .appinfo file should exist")
appinfo := new(action.AppInfo)
err = yaml.Unmarshal(contents, appinfo)
assert.NoError(t, err, "new .appinfo file should be correctly formed")
assert.EqualValues(t, "new description", appinfo.Description, "description should be updated")
assert.EqualValues(t, "http://123.456.789", appinfo.Host, "host should be updated")
assert.Error(t, RunWithArgs(app, "edit", "app"), "edit app should fail with no args")
assert.NoError(t, RunWithArgs(app, "edit", "app", "TestApp"), "edit app should NOT fail with no flags")
os.RemoveAll("TestActionEditApp")
}
func TestActionEditRequest(t *testing.T) {
cfgPath := path.Join("TestActionEditRequest", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "Req",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "ReqTwo",
Path: "/path",
Description: "hello",
Body: "request body",
Method: "POST",
Headers: []string{"Header: One"},
})
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
// tests
app := app.New(cfgPath, http.Client{})
assert.NoError(t,
RunWithArgs(app, "edit", "req",
"-a", "TestApp",
"-d", "new description",
"-X", "POST",
"-b", "new body",
"-H", "X-Header: ABC",
"-p", "/new-path",
"Req",
),
"edit app should not fail with 1 arg and flags",
)
contents, err := os.ReadFile(path.Join(action.AppPath(cfgPath, "TestApp"), "Req.yml"))
assert.NoError(t, err, "new request file should exist")
reqinfo := new(action.RequestInfo)
err = yaml.Unmarshal(contents, reqinfo)
assert.NoError(t, err, "new request file should be correctly formed")
assert.EqualValues(t, "new description", reqinfo.Description, "description should be updated")
assert.EqualValues(t, "POST", reqinfo.Method, "method should be updated")
assert.EqualValues(t, "new body", reqinfo.Body, "body should be updated")
assert.EqualValues(t, "X-Header: ABC", reqinfo.Headers[0], "header(s) should be updated")
assert.EqualValues(t, "/new-path", reqinfo.Path, "path should be updated")
assert.Error(t, RunWithArgs(app, "edit", "req"), "edit req should fail with no args")
assert.NoError(t, RunWithArgs(app, "edit", "req", "ReqTwo"), "edit req should NOT fail with no flags")
assert.NoError(t, RunWithArgs(app, "edit", "req", "-d", "new description", "ReqTwo"), "edit req should NOT fail when updating description")
contents, _ = os.ReadFile(path.Join(action.AppPath(cfgPath, "TestApp"), "ReqTwo.yml"))
reqinfo = new(action.RequestInfo)
yaml.Unmarshal(contents, reqinfo)
assert.EqualValues(t, "Header: One", reqinfo.Headers[0], "header(s) should NOT be overwritten when not updated")
assert.EqualValues(t, "/path", reqinfo.Path, "path should NOT be overwritten when not updated")
assert.EqualValues(t, "request body", reqinfo.Body, "header(s) should NOT be overwritten when not updated")
assert.EqualValues(t, "POST", reqinfo.Method, "method should NOT be overwritten when not updated")
os.RemoveAll("TestActionEditRequest")
}
func TestActionListApps(t *testing.T) {
cfgPath := path.Join("TestActionListApps", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "AnotherApp",
Description: "another one",
})
// tests
expected := "AnotherApp: another one\nTestApp\n"
app := app.New(cfgPath, http.Client{})
out, err := captureOutput(RunWithArgs, app, "list", "app")
assert.NoError(t, err, "list app should NOT generate an error")
assert.EqualValues(t, expected, out, "list app should be alphabetical")
os.RemoveAll("TestActionListApps")
}
func TestActionListRequests(t *testing.T) {
cfgPath := path.Join("TestActionListRequests", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestAppTwo",
})
action.WriteRequestFiles(cfgPath, "TestAppTwo", &action.RequestInfo{
Name: "Req",
})
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "MyReq",
Description: "my request",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "AnotherReq",
})
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
// tests
expected := "AnotherReq\nMyReq: my request\n"
app := app.New(cfgPath, http.Client{})
out, err := captureOutput(RunWithArgs, app, "list", "req")
assert.NoError(t, err, "list req should NOT generate an error")
assert.EqualValues(t, expected, out, "list req should succeed with default app")
expected = "Req\n"
out, err = captureOutput(RunWithArgs, app, "list", "req", "-a", "TestAppTwo")
assert.NoError(t, err, "list req should NOT generate an error")
assert.EqualValues(t, expected, out, "list req should succeed with specific app")
os.RemoveAll("TestActionListRequests")
}
func TestActionListAll(t *testing.T) {
cfgPath := path.Join("TestActionListAll", ".sp9rk", "tests")
// simulate apps being created
app := app.New(cfgPath, http.Client{})
expected := "No applications or requests\n"
out, err := captureOutput(RunWithArgs, app, "list")
assert.NoError(t, err, "list all with nothing loaded should NOT generate an error")
assert.EqualValues(t, expected, out, "list should generate expected output")
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestAppTwo",
})
expected = "TestAppTwo\n"
out, err = captureOutput(RunWithArgs, app, "list")
assert.NoError(t, err, "list req should NOT generate an error")
assert.EqualValues(t, expected, out, "list should generate expected output")
action.WriteRequestFiles(cfgPath, "TestAppTwo", &action.RequestInfo{
Name: "Req",
})
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "MyReq",
Description: "my request",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "AnotherReq",
})
expected = `TestApp:
- AnotherReq
- MyReq: my request
TestAppTwo:
- Req
`
out, err = captureOutput(RunWithArgs, app, "list")
assert.NoError(t, err, "list req should NOT generate an error")
assert.EqualValues(t, expected, out, "list should generate expected output")
os.RemoveAll("TestActionListAll")
}
func TestActionAppInfo(t *testing.T) {
cfgPath := path.Join("TestActionAppInfo", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
Description: "test application",
Host: "http://123.456.789",
})
// tests
expected := `TestApp:
Description: test application
Host: http://123.456.789
`
app := app.New(cfgPath, http.Client{})
out, err := captureOutput(RunWithArgs, app, "info", "app", "TestApp")
assert.NoError(t, err, "list req should NOT generate an error")
assert.EqualValues(t, expected, out, "list should generate expected output")
assert.Error(t, RunWithArgs(app, "info", "app"), "info app should generate an error with no args")
os.RemoveAll("TestActionAppInfo")
}
func TestActionRequestInfo(t *testing.T) {
cfgPath := path.Join("TestActionRequestInfo", ".sp9rk", "tests")
// simulate apps being created
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "MyReq",
Method: "GET",
Description: "my request",
Path: "/path",
Body: "request body",
Headers: []string{
"X-API-Key: ABC123",
},
})
// tests
expected := `MyReq:
description: my request
method: GET
path: /path
headers:
- 'X-API-Key: ABC123'
body: request body
`
app := app.New(cfgPath, http.Client{})
out, err := captureOutput(RunWithArgs, app, "info", "req", "-a", "TestApp", "MyReq")
assert.NoError(t, err, "list req should NOT generate an error")
assert.EqualValues(t, expected, out, "list should generate expected output")
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
out, err = captureOutput(RunWithArgs, app, "info", "req", "MyReq")
assert.NoError(t, err, "list req should NOT generate an error")
assert.EqualValues(t, expected, out, "list should generate expected output with default app")
assert.Error(t, RunWithArgs(app, "info", "req"), "info req should generate an error with no args")
os.RemoveAll("TestActionRequestInfo")
}
type ClientMock struct{}
func (c *ClientMock) Do(req *http.Request) (*http.Response, error) {
return &http.Response{
Status: "OK",
StatusCode: 200,
Body: io.NopCloser(strings.NewReader("Hello, world!")),
}, nil
}
func TestActionCall(t *testing.T) {
cfgPath := path.Join("TestActionCall", ".sp9rk", "tests")
// simulate apps being created
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.EqualValues(t, "/path", r.URL.Path, "path is incorrect")
assert.EqualValues(t, r.Header.Get("X-API-Key"), "ABC123", "headers are incorrect")
assert.EqualValues(t, r.Method, "GET", "method is incorrect")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`Hello, World!`))
}))
defer server.Close()
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
Host: server.URL,
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "MyReq",
Method: "GET",
Description: "my request",
Path: "/path",
Body: "request body",
Headers: []string{
"X-API-Key: ABC123",
},
})
// test basic functionality
app := app.New(cfgPath, http.Client{})
assert.Error(t, RunWithArgs(app, "call"), "call should fail with no argument")
assert.Error(t, RunWithArgs(app, "call", "MyReq"), "call should fail with no default app")
assert.Error(t, RunWithArgs(app, "call", "../bad/path"), "call should fail invalid request name")
assert.Error(t, RunWithArgs(app, "call", "-a", "../bad/app/path", "MyReq"), "call should fail with invalid app name")
assert.Error(t, RunWithArgs(app, "call", "-a", "TestApp", "FakeReq"), "call should fail with unknown app")
assert.Error(t, RunWithArgs(app, "call", "MyReq"), "call should fail with no default app")
output, err := captureOutput(RunWithArgs, app, "call", "-a", "TestApp", "MyReq")
assert.EqualValues(t, "Hello, World!\n", output, "call output should be response body")
assert.NoError(t, err, "call should succeed with explicit app")
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
output, err = captureOutput(RunWithArgs, app, "call", "MyReq")
assert.NoError(t, err, "call should succeed with default app")
assert.EqualValues(t, "Hello, World!\n", output, "call output should be response body")
// test extended functionality (flags)
output, err = captureOutput(RunWithArgs, app, "call", "--verbose", "MyReq")
assert.NoError(t, err, "call should succeed with verbose flag")
respData := new(action.VerboseCallResponse)
err = yaml.Unmarshal([]byte(output), respData)
assert.NoError(t, err, "output should be valid yaml")
assert.Equal(t, "GET "+server.URL+"/path", respData.Request, "request is incorrect")
assert.NotEmpty(t, respData.Latency, "latency must not be empty")
assert.Equal(t, "request body", respData.RequestBody, "request body is incorrect")
assert.Equal(t, "200 OK", respData.Status, "response status is incorrect")
assert.NotNil(t, respData.Headers, "request headers must not be nil")
assert.Equal(t, "ABC123", respData.Headers["X-API-Key"], "request headers are incorrect")
assert.Equal(t, "Hello, World!", respData.ResponseBody, "response body is incorrect")
os.RemoveAll("TestActionCall")
}
func TestActionCallFail(t *testing.T) {
cfgPath := path.Join("TestActionCallFail", ".sp9rk", "tests")
// make a new server that will make every request return >=400 status
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(400)
w.Write([]byte(`Hello, World!`))
}))
defer server.Close()
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
Host: server.URL,
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "MyReq",
Method: "GET",
Description: "my request",
Path: "/path",
Body: "request body",
Headers: []string{
"X-API-Key: ABC123",
},
})
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
app := app.New(cfgPath, http.Client{})
output, err := captureOutput(RunWithArgs, app, "call", "--fail", "MyReq")
assert.Error(t, err, "call should fail with fail flag")
assert.Empty(t, output, "failed request should be silent with fail flag")
os.RemoveAll("TestActionCallFail")
}
// TODO test redirects
func TestActionCallRedirects(t *testing.T) {
cfgPath := path.Join("TestActionCallLocation", ".sp9rk", "tests")
// make a new server that will make every request return >=400 status
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/hello" {
w.WriteHeader(http.StatusOK)
w.Write([]byte(`Hello, World!`))
return
}
w.WriteHeader(404)
}))
defer server.Close()
server2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/redirect-me" {
w.Header().Add("Location", server.URL+"/hello")
w.WriteHeader(http.StatusMovedPermanently)
w.Write([]byte(`Don't follow me!`))
return
}
w.WriteHeader(404)
}))
defer server2.Close()
action.WriteAppFiles(cfgPath, &action.AppInfo{
Name: "TestApp",
Host: server2.URL,
})
action.WriteRequestFiles(cfgPath, "TestApp", &action.RequestInfo{
Name: "MyReq",
Method: "GET",
Description: "my request",
Path: "/redirect-me",
})
os.WriteFile(path.Join(cfgPath, "current_app"), []byte("TestApp"), 0700)
app := app.New(cfgPath, http.Client{})
output, err := captureOutput(RunWithArgs, app, "call", "MyReq")
assert.NoError(t, err, "call should not fail when following valid redirect")
assert.Equal(t, "Hello, World!\n", output, "output should be equal to response body")
output, err = captureOutput(RunWithArgs, app, "call", "--no-redirect", "MyReq")
assert.NoError(t, err, "call should not fail when not following redirect")
assert.Equal(t, "Don't follow me!\n", output, "output should be equal to response body")
os.RemoveAll("TestActionCallLocation")
}
// helper functions for testing
func RunWithArgs(app *cli.App, args ...string) error {
a := os.Args[0:1]
a = append(a, args...)
return app.Run(a)
}
func captureOutput(f func(*cli.App, ...string) error, app *cli.App, args ...string) (string, error) {
orig := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
err := f(app, args...)
os.Stdout = orig
w.Close()
out, _ := io.ReadAll(r)
return string(out), err
}