mirror of
https://github.com/hanzoskill/mogcli.git
synced 2026-10-30 21:03:34 +00:00
683 lines
16 KiB
Go
683 lines
16 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/visionik/mogcli/internal/testutil"
|
|
)
|
|
|
|
func TestOneNoteNotebooksCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful list notebooks",
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "nb-123", "displayName": "Work Notebook"},
|
|
{"id": "nb-456", "displayName": "Personal"},
|
|
},
|
|
}),
|
|
wantInOut: "Work Notebook",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
root: &Root{JSON: true},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "nb-123", "displayName": "Notebook"},
|
|
},
|
|
}),
|
|
wantInOut: `"displayName": "Notebook"`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
GetFunc: func(ctx context.Context, path string, query url.Values) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
cmd := &OneNoteNotebooksCmd{}
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNoteSectionsCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNoteSectionsCmd
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful list sections",
|
|
cmd: &OneNoteSectionsCmd{NotebookID: "nb-123"},
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "sec-123", "displayName": "Meeting Notes"},
|
|
{"id": "sec-456", "displayName": "Ideas"},
|
|
},
|
|
}),
|
|
wantInOut: "Meeting Notes",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
cmd: &OneNoteSectionsCmd{NotebookID: "nb-123"},
|
|
root: &Root{JSON: true},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "sec-123", "displayName": "Section"},
|
|
},
|
|
}),
|
|
wantInOut: `"displayName": "Section"`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNoteSectionsCmd{NotebookID: "nb-123"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
GetFunc: func(ctx context.Context, path string, query url.Values) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNotePagesCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNotePagesCmd
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful list pages",
|
|
cmd: &OneNotePagesCmd{SectionID: "sec-123"},
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "page-123", "title": "Project Planning"},
|
|
{"id": "page-456", "title": "Sprint Notes"},
|
|
},
|
|
}),
|
|
wantInOut: "Project Planning",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
cmd: &OneNotePagesCmd{SectionID: "sec-123"},
|
|
root: &Root{JSON: true},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "page-123", "title": "Page"},
|
|
},
|
|
}),
|
|
wantInOut: `"title": "Page"`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNotePagesCmd{SectionID: "sec-123"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
GetFunc: func(ctx context.Context, path string, query url.Values) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNoteGetCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNoteGetCmd
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful get page content",
|
|
cmd: &OneNoteGetCmd{PageID: "page-123"},
|
|
root: &Root{},
|
|
mockResp: []byte("<html><body><p>Page content</p></body></html>"),
|
|
wantInOut: "Page content",
|
|
},
|
|
{
|
|
name: "get with HTML output",
|
|
cmd: &OneNoteGetCmd{PageID: "page-123", HTML: true},
|
|
root: &Root{},
|
|
mockResp: []byte("<html><body><p>Page content</p></body></html>"),
|
|
wantInOut: "<html>",
|
|
},
|
|
{
|
|
name: "get with JSON flag shows raw",
|
|
cmd: &OneNoteGetCmd{PageID: "page-123"},
|
|
root: &Root{JSON: true},
|
|
mockResp: []byte("<html><body><p>Content</p></body></html>"),
|
|
wantInOut: "<html>",
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNoteGetCmd{PageID: "page-123"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
GetFunc: func(ctx context.Context, path string, query url.Values) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNoteSearchCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNoteSearchCmd
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful search",
|
|
cmd: &OneNoteSearchCmd{Query: "meeting"},
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "page-123", "title": "Meeting Notes"},
|
|
},
|
|
}),
|
|
wantInOut: "Meeting Notes",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
cmd: &OneNoteSearchCmd{Query: "test"},
|
|
root: &Root{JSON: true},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"value": []map[string]interface{}{
|
|
{"id": "page-123", "title": "Test Page"},
|
|
},
|
|
}),
|
|
wantInOut: `"title": "Test Page"`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNoteSearchCmd{Query: "test"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
GetFunc: func(ctx context.Context, path string, query url.Values) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNoteCreateNotebookCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNoteCreateNotebookCmd
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful create notebook",
|
|
cmd: &OneNoteCreateNotebookCmd{Name: "New Notebook"},
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"id": "nb-new-123",
|
|
"displayName": "New Notebook",
|
|
}),
|
|
wantInOut: "Notebook created",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
cmd: &OneNoteCreateNotebookCmd{Name: "Test"},
|
|
root: &Root{JSON: true},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"id": "nb-new",
|
|
"displayName": "Test",
|
|
}),
|
|
wantInOut: `"displayName": "Test"`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNoteCreateNotebookCmd{Name: "Fail"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
PostFunc: func(ctx context.Context, path string, body interface{}) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNoteCreateSectionCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNoteCreateSectionCmd
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful create section",
|
|
cmd: &OneNoteCreateSectionCmd{NotebookID: "nb-123", Name: "New Section"},
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"id": "sec-new-123",
|
|
"displayName": "New Section",
|
|
}),
|
|
wantInOut: "Section created",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
cmd: &OneNoteCreateSectionCmd{NotebookID: "nb-123", Name: "Test"},
|
|
root: &Root{JSON: true},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"id": "sec-new",
|
|
"displayName": "Test",
|
|
}),
|
|
wantInOut: `"displayName": "Test"`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNoteCreateSectionCmd{NotebookID: "nb-123", Name: "Fail"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
PostFunc: func(ctx context.Context, path string, body interface{}) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNoteCreatePageCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNoteCreatePageCmd
|
|
root *Root
|
|
mockResp []byte
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful create page",
|
|
cmd: &OneNoteCreatePageCmd{SectionID: "sec-123", Title: "New Page"},
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"id": "page-new-123",
|
|
"title": "New Page",
|
|
}),
|
|
wantInOut: "Page created",
|
|
},
|
|
{
|
|
name: "create page with content",
|
|
cmd: &OneNoteCreatePageCmd{SectionID: "sec-123", Title: "Content Page", Content: "Some content here"},
|
|
root: &Root{},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"id": "page-new-456",
|
|
"title": "Content Page",
|
|
}),
|
|
wantInOut: "Page created",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
cmd: &OneNoteCreatePageCmd{SectionID: "sec-123", Title: "Test"},
|
|
root: &Root{JSON: true},
|
|
mockResp: mustJSON(map[string]interface{}{
|
|
"id": "page-new",
|
|
"title": "Test",
|
|
}),
|
|
wantInOut: `"title": "Test"`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNoteCreatePageCmd{SectionID: "sec-123", Title: "Fail"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
PostHTMLFunc: func(ctx context.Context, path string, html string) ([]byte, error) {
|
|
return tt.mockResp, tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOneNoteDeleteCmd_Run(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cmd *OneNoteDeleteCmd
|
|
root *Root
|
|
mockErr error
|
|
wantErr bool
|
|
wantInOut string
|
|
}{
|
|
{
|
|
name: "successful delete",
|
|
cmd: &OneNoteDeleteCmd{PageID: "page-123"},
|
|
root: &Root{},
|
|
wantInOut: "Page deleted",
|
|
},
|
|
{
|
|
name: "JSON output",
|
|
cmd: &OneNoteDeleteCmd{PageID: "page-123"},
|
|
root: &Root{JSON: true},
|
|
wantInOut: `"success": true`,
|
|
},
|
|
{
|
|
name: "API error",
|
|
cmd: &OneNoteDeleteCmd{PageID: "page-123"},
|
|
root: &Root{},
|
|
mockErr: errors.New("API error"),
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mock := &testutil.MockClient{
|
|
DeleteFunc: func(ctx context.Context, path string) error {
|
|
return tt.mockErr
|
|
},
|
|
}
|
|
tt.root.ClientFactory = mockClientFactory(mock)
|
|
|
|
var output string
|
|
err := error(nil)
|
|
output = captureOutput(func() {
|
|
err = tt.cmd.Run(tt.root)
|
|
})
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
if tt.wantInOut != "" {
|
|
assert.Contains(t, output, tt.wantInOut)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Test escapeHTML function
|
|
func TestEscapeHTML(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{name: "empty string", input: "", expected: ""},
|
|
{name: "no special chars", input: "Hello World", expected: "Hello World"},
|
|
{name: "ampersand", input: "A & B", expected: "A & B"},
|
|
{name: "less than", input: "A < B", expected: "A < B"},
|
|
{name: "greater than", input: "A > B", expected: "A > B"},
|
|
{name: "double quote", input: `Say "Hello"`, expected: "Say "Hello""},
|
|
{name: "single quote", input: "It's fine", expected: "It's fine"},
|
|
{name: "mixed", input: `<a href="test">&</a>`, expected: "<a href="test">&</a>"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := escapeHTML(tt.input)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
// Test type unmarshaling
|
|
func TestNotebook_Unmarshal(t *testing.T) {
|
|
jsonData := `{
|
|
"id": "nb-123",
|
|
"displayName": "My Notebook"
|
|
}`
|
|
|
|
var nb Notebook
|
|
err := json.Unmarshal([]byte(jsonData), &nb)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "nb-123", nb.ID)
|
|
assert.Equal(t, "My Notebook", nb.DisplayName)
|
|
}
|
|
|
|
func TestSection_Unmarshal(t *testing.T) {
|
|
jsonData := `{
|
|
"id": "sec-123",
|
|
"displayName": "My Section"
|
|
}`
|
|
|
|
var sec Section
|
|
err := json.Unmarshal([]byte(jsonData), &sec)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "sec-123", sec.ID)
|
|
assert.Equal(t, "My Section", sec.DisplayName)
|
|
}
|
|
|
|
func TestPage_Unmarshal(t *testing.T) {
|
|
jsonData := `{
|
|
"id": "page-123",
|
|
"title": "My Page"
|
|
}`
|
|
|
|
var page Page
|
|
err := json.Unmarshal([]byte(jsonData), &page)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "page-123", page.ID)
|
|
assert.Equal(t, "My Page", page.Title)
|
|
}
|