Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions internal/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type NFContext struct {
SBIPort int

SpyFamilyData map[string]string
NoteData map[string]string
}

var nfContext = NFContext{}
Expand Down Expand Up @@ -57,6 +58,9 @@ func InitNfContext() {
"Henry": "Henderson",
"Martha": "Marriott",
}
nfContext.NoteData = map[string]string{
"User_Guide": "/<Title>/ Show the content of the note with title <Title>.\n",
}
}

func GetSelf() *NFContext {
Expand Down
110 changes: 110 additions & 0 deletions internal/sbi/api_notebook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package sbi

import (
"net/http"

"github.com/andy89923/nf-example/internal/logger"
"github.com/gin-gonic/gin"
)

func (s *Server) getNotebookRoute() []Route {
return []Route{
{
Name: "Show Note",
Method: http.MethodGet,
Pattern: "/:Title",
APIFunc: s.HTTPShowNote,
// Use
// curl -X GET http://127.0.0.163:8000/notebook/User_Guide -w "\n"
// "Title: User_Guide"
// " /<Title>/ Show the content of the note with title <Title>."
},
{
Name: "Create Note",
Method: http.MethodPut,
Pattern: "/:Title/:Content",
APIFunc: s.HTTPCreateNote,
// Use
// curl -X PUT http://127.0.0.163:8000/notebook/New_Title/New_content -w "\n"
// "Title: New_Title"
// "Content:"
// " New_content"
},
{
Name: "Update Note",
Method: http.MethodPost,
Pattern: "/:Title/:Content",
APIFunc: s.HTTPUpdateNote,
// Use
// curl -X POST http://127.0.0.163:8000/notebook/New_Title/New_content -w "\n"
// "Title: New_Title"
// "Content:"
// " New_content"
},
{
Name: "Note Append with whitespace at front.",
Method: http.MethodPost,
Pattern: "/:Title/append/:Content_append",
APIFunc: s.HTTPNoteWhitespaceAppend,
// Use
// curl -X POST http://127.0.0.163:8000/notebook/New_Title/append/new_content_to_be_append. -w "\n"
// "Title: New_Title"
// "Content:"
// " New_content new_content_to_be_append."
},
}
}

func (s *Server) HTTPShowNote(c *gin.Context) {
logger.SBILog.Infof("In HTTPShowNote")

targetName := c.Param("Title")
if targetName == "" {
c.String(http.StatusBadRequest, "No name provided")
return
}

s.Processor().FindNote(c, targetName)
}

func (s *Server) HTTPUpdateNote(c *gin.Context) {
logger.SBILog.Infof("In HTTPUpdateNote")

targetName := c.Param("Title")
if targetName == "" {
c.String(http.StatusBadRequest, "No name provided")
return
}

newContent := c.Param("Content")

s.Processor().UpdateNote(c, targetName, newContent)
}

func (s *Server) HTTPCreateNote(c *gin.Context) {
logger.SBILog.Infof("In HTTPCreateNote")

targetName := c.Param("Title")
if targetName == "" {
c.String(http.StatusBadRequest, "No name provided")
return
}

newContent := c.Param("Content")

s.Processor().CreateNote(c, targetName, newContent)
}

func (s *Server) HTTPNoteWhitespaceAppend(c *gin.Context) {
logger.SBILog.Infof("In HTTPNoteAppend")

targetName := c.Param("Title")
if targetName == "" {
c.String(http.StatusBadRequest, "No name provided")
return
}

newContent := c.Param("Content_append")

s.Processor().NoteWhitespaceAppend(c, targetName, newContent)
}
102 changes: 102 additions & 0 deletions internal/sbi/api_notebook_test.go
Copy link
Owner

Choose a reason for hiding this comment

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

Please write the test for your service.

Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package sbi_test

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/andy89923/nf-example/internal/sbi"
"github.com/andy89923/nf-example/pkg/factory"
"github.com/gin-gonic/gin"
"go.uber.org/mock/gomock"
)

func Test_getNotebookRoutes(t *testing.T) {
gin.SetMode(gin.TestMode)

mockCtrl := gomock.NewController(t)
nfApp := sbi.NewMocknfApp(mockCtrl)
nfApp.EXPECT().Config().Return(&factory.Config{
Configuration: &factory.Configuration{
Sbi: &factory.Sbi{
Port: 8000,
},
},
}).AnyTimes()
server := sbi.NewServer(nfApp, "")

t.Run("No name provided", func(t *testing.T) {
Copy link
Owner

Choose a reason for hiding this comment

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

"No name provided" ?

Copy link
Owner

Choose a reason for hiding this comment

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

The following test with same name.

const EXPECTED_STATUS = http.StatusBadRequest
const EXPECTED_BODY = "No name provided"

httpRecorder := httptest.NewRecorder()
ginCtx, _ := gin.CreateTestContext(httpRecorder)

var err error
ginCtx.Request, err = http.NewRequest("GET", "/notebook/", nil)
if err != nil {
t.Errorf("Failed to create request: %s", err)
return
}

server.HTTPShowNote(ginCtx)

if httpRecorder.Code != EXPECTED_STATUS {
t.Errorf("Expected status code %d, got %d", EXPECTED_STATUS, httpRecorder.Code)
}

if httpRecorder.Body.String() != EXPECTED_BODY {
t.Errorf("Expected body %s, got %s", EXPECTED_BODY, httpRecorder.Body.String())
}
})

t.Run("No name provided", func(t *testing.T) {
const EXPECTED_STATUS = http.StatusBadRequest
const EXPECTED_BODY = "No name provided"

httpRecorder := httptest.NewRecorder()
ginCtx, _ := gin.CreateTestContext(httpRecorder)

var err error
ginCtx.Request, err = http.NewRequest("POST", "/notebook/", nil)
if err != nil {
t.Errorf("Failed to create request: %s", err)
return
}

server.HTTPUpdateNote(ginCtx)

if httpRecorder.Code != EXPECTED_STATUS {
t.Errorf("Expected status code %d, got %d", EXPECTED_STATUS, httpRecorder.Code)
}

if httpRecorder.Body.String() != EXPECTED_BODY {
t.Errorf("Expected body %s, got %s", EXPECTED_BODY, httpRecorder.Body.String())
}
})

t.Run("No name provided", func(t *testing.T) {
const EXPECTED_STATUS = http.StatusBadRequest
const EXPECTED_BODY = "No name provided"

httpRecorder := httptest.NewRecorder()
ginCtx, _ := gin.CreateTestContext(httpRecorder)

var err error
ginCtx.Request, err = http.NewRequest("POST", "/notebook//append/", nil)
if err != nil {
t.Errorf("Failed to create request: %s", err)
return
}

server.HTTPUpdateNote(ginCtx)

if httpRecorder.Code != EXPECTED_STATUS {
t.Errorf("Expected status code %d, got %d", EXPECTED_STATUS, httpRecorder.Code)
}

if httpRecorder.Body.String() != EXPECTED_BODY {
t.Errorf("Expected body %s, got %s", EXPECTED_BODY, httpRecorder.Body.String())
}
})
}
58 changes: 58 additions & 0 deletions internal/sbi/processor/notebook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package processor

import (
"fmt"
"net/http"
"strings"

"github.com/gin-gonic/gin"
)

func (p *Processor) FindNote(c *gin.Context, targetName string) {
if content, ok := p.Context().NoteData[targetName]; ok {
c.String(http.StatusOK, fmt.Sprintf("Title: %s\nContent:\n\t%s\n", targetName, content))
return
}
c.String(http.StatusNotFound, fmt.Sprintf("[%s] not found in Notebook\n", targetName))
}

func (p *Processor) UpdateNote(c *gin.Context, targetName string, newContent string) {
p.Context().NoteData[targetName] = newContent

if content, ok := p.Context().NoteData[targetName]; ok {
c.String(http.StatusOK, fmt.Sprintf("Title: %s\nContent:\n\t%s\n", targetName, content))
return
}
c.String(http.StatusNotFound, fmt.Sprintf("[%s] not found in Notebook\n", targetName))
}

func (p *Processor) CreateNote(c *gin.Context, targetName string, newContent string) {
if _, ok := p.Context().NoteData[targetName]; !ok {
p.Context().NoteData[targetName] = newContent

content := p.Context().NoteData[targetName]
c.String(http.StatusOK, fmt.Sprintf("Title: %s\nContent:\n\t%s\n", targetName, content))
return
} else if ok {
c.String(http.StatusForbidden, fmt.Sprintf(
"[%s] already exist. Please use POST to modify the content.\n",
targetName),
)
}
}

func (p *Processor) NoteWhitespaceAppend(c *gin.Context, targetName string, newContent string) {
if _, ok := p.Context().NoteData[targetName]; ok {
var sb strings.Builder
sb.WriteString(p.Context().NoteData[targetName])
sb.WriteString(" ")
sb.WriteString(newContent)

p.Context().NoteData[targetName] = sb.String()

content := p.Context().NoteData[targetName]
c.String(http.StatusOK, fmt.Sprintf("Title: %s\nContent:\n\t%s\n", targetName, content))
return
}
c.String(http.StatusNotFound, fmt.Sprintf("[%s] not found in Notebook\n", targetName))
}
Loading
Loading