Skip to content

Commit

Permalink
Merge pull request #2 from TJM/board_member
Browse files Browse the repository at this point in the history
Board members!
  • Loading branch information
Tommy McNeely committed Oct 31, 2020
2 parents 867368f + 6bc4b83 commit 592516f
Show file tree
Hide file tree
Showing 8 changed files with 362 additions and 34 deletions.
135 changes: 121 additions & 14 deletions board.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package trello

import (
"encoding/json"
"fmt"
"net/url"
"strconv"
)
Expand All @@ -31,12 +32,15 @@ type Board struct {
DescData struct {
Emoji struct{} `json:"emoji"`
} `json:"descData"`
Closed bool `json:"closed"`
IDOrganization string `json:"idOrganization"`
Pinned bool `json:"pinned"`
URL string `json:"url"`
ShortURL string `json:"shortUrl"`
Prefs struct {
Closed bool `json:"closed"`
IDMemberCreator string `json:"idMemberCreator"`
IDOrganization string `json:"idOrganization"`
Members []*Member `json:"members"`
Memberships []*Membership `json:"memberships"`
Pinned bool `json:"pinned"`
URL string `json:"url"`
ShortURL string `json:"shortUrl"`
Prefs struct {
PermissionLevel string `json:"permissionLevel"`
Voting string `json:"voting"`
Comments string `json:"comments"`
Expand Down Expand Up @@ -76,9 +80,9 @@ type BoardBackground struct {
// Board - Get board by boardID
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-id-get
func (c *Client) Board(boardID string) (board *Board, err error) {
board = &Board{}
body, err := c.Get("/boards/" + boardID)
if err == nil {
board = &Board{}
err = parseBoard(body, board, c)
}
return
Expand All @@ -87,12 +91,12 @@ func (c *Client) Board(boardID string) (board *Board, err error) {
// CreateBoard - Create Board
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-post
func (c *Client) CreateBoard(name string) (board *Board, err error) {
board = &Board{}
payload := url.Values{}
payload.Set("name", name)

body, err := c.Post("/boards", payload)
if err == nil {
board = &Board{}
err = parseBoard(body, board, c)
}
return
Expand All @@ -101,7 +105,6 @@ func (c *Client) CreateBoard(name string) (board *Board, err error) {
// Duplicate - Duplicate (Copy) Board
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-post
func (b *Board) Duplicate(name string, keepCards bool) (board *Board, err error) {
board = &Board{}
keepFromSource := "none"
if keepCards {
keepFromSource = "cards"
Expand All @@ -113,6 +116,7 @@ func (b *Board) Duplicate(name string, keepCards bool) (board *Board, err error)

body, err := b.client.Post("/boards", payload)
if err == nil {
board = &Board{}
err = parseBoard(body, board, b.client)
}
return
Expand Down Expand Up @@ -160,16 +164,104 @@ func (b *Board) Lists() (lists []List, err error) {
return
}

// Members - Get the members of a board
// GetMembers - Get the members of a board
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-id-members-get
func (b *Board) Members() (members []Member, err error) {
body, err := b.client.Get("/boards/" + b.ID + "/members")
func (b *Board) GetMembers() (members []*Member, err error) {
if len(b.Members) == 0 {
body, err := b.client.Get("/boards/" + b.ID + "/members")
if err == nil {
members, err = parseListMembers(body, b.client)

}
} else {
members = b.Members
}
return
}

// AddMember - Add a Member to a board
// memberType can be admin, normal or observer (if left blank will default to normal)
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-id-members-idmember-put
func (b *Board) AddMember(member *Member, memberType string) (err error) {
if memberType == "" {
memberType = "normal" // default to "normal"
}
payload := url.Values{}
payload.Set("type", memberType)
body, err := b.client.Put("/boards/"+b.ID+"/members/"+member.ID, payload)
if err == nil {
err = parseBoard(body, b, b.client)
}
return
}

// RemoveMember - Remove a Member from a board
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-id-members-idmember-put
func (b *Board) RemoveMember(member *Member) (err error) {
body, err := b.client.Delete("/boards/" + b.ID + "/members/" + member.ID)
if err == nil {
err = parseBoard(body, b, b.client)
}
return
}

// GetMembership - Get a Membership of a board by ID
// Get information about the memberships users have to the board.
// filter: Valid Values: admins, all, none, normal (default: all)
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-id-memberships-get
func (b *Board) GetMembership(id string) (membership *Membership, err error) {
body, err := b.client.Get("/boards/" + b.ID + "/memberships/" + id)
if err == nil {
members, err = parseListMembers(body, b.client)
membership = &Membership{}
err = parseMembership(body, membership, b)
}
return
}

// GetMemberships - Get Memberships of a board
// Get information about the memberships users have to the board.
// filter: Valid Values: admins, all, none, normal (default: all)
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-id-memberships-get
func (b *Board) GetMemberships() (memberships []*Membership, err error) {
if len(b.Memberships) == 0 {
body, err := b.client.Get("/boards/" + b.ID + "/memberships")
if err == nil {
memberships, err = parseListMemberships(body, b)
if err == nil {
b.Memberships = memberships
}
}
} else {
memberships = b.Memberships
}
return
}

// GetMembershipForMember - Return a Membership that matches a specific Member
func (b *Board) GetMembershipForMember(member *Member) (membership *Membership, err error) {
memberships, err := b.GetMemberships()
if err == nil {
for _, ms := range memberships {
if ms.IDMember == member.ID {
membership = ms
}
}
if membership == nil {
err = fmt.Errorf("ERROR: No membership found for member: " + member.ID)
}
}
return
}

// IsAdmin - Check to see if a member is an admin
func (b *Board) IsAdmin(member *Member) (isAdmin bool) {
ms, err := b.GetMembershipForMember(member)
if err == nil {
return ms.MemberType == "admin"
}
return false
}

// Cards - Get cards on a board
// - https://developer.atlassian.com/cloud/trello/rest/api-group-boards/#api-boards-id-cards-get
func (b *Board) Cards() (cards []Card, err error) {
Expand Down Expand Up @@ -273,6 +365,13 @@ func parseBoard(body []byte, board *Board, client *Client) (err error) {
err = json.Unmarshal(body, &board)
if err == nil {
board.client = client
for i := range board.Members {
board.Members[i].client = client
}
for i := range board.Memberships {
board.Memberships[i].client = client
board.Memberships[i].Board = board
}
}
return
}
Expand All @@ -281,7 +380,15 @@ func parseListBoards(body []byte, client *Client) (boards []Board, err error) {
err = json.Unmarshal(body, &boards)
if err == nil {
for i := range boards {
boards[i].client = client
board := boards[i]
board.client = client
// List of boards will not have "Members"
// for i := range board.Members {
// board.Members[i].client = client
// }
for i := range board.Memberships {
board.Memberships[i].client = client
}
}
}
return
Expand Down
74 changes: 61 additions & 13 deletions board_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,25 @@ func TestBoard(t *testing.T) {

g.Describe("Board tests", func() {
var board *Board
var member *Member
var label *Label
var testBoardName string

g.Before(func() {
testBoardName = fmt.Sprintf("GoTestTrello-Board-%v", time.Now().Unix())

})

g.It("should create a board", func() {
board, err = client.CreateBoard(testBoardName)
Expect(err).To(BeNil())
Expect(board).NotTo(BeNil())
Expect(board.Name).To(Equal(testBoardName))
member, err = client.Member("trello")
Expect(err).To(BeNil())
Expect(member).NotTo(BeNil())
})

g.It("should get a board by ID", func() {
board, err = client.Board(board.ID)
b, err := client.Board(board.ID)
Expect(err).To(BeNil())
Expect(board).NotTo(BeNil())
Expect(board.Name).To(Equal(testBoardName))
Expect(b).NotTo(BeNil())
Expect(b.Name).To(Equal(testBoardName))
})

g.It("should change the board background to red", func() {
Expand All @@ -65,6 +64,59 @@ func TestBoard(t *testing.T) {
Expect(board.Desc).To(Equal("something"))
})

g.It("should get the members of a board", func() {
members, err := board.GetMembers()
Expect(err).To(BeNil())
Expect(members).NotTo(BeNil())
})

// This needs to come before "AddMember" for code coverage reasons
g.It("should get memberships on a board", func() {
ms, err := board.GetMemberships()
Expect(err).To(BeNil())
Expect(len(ms)).To(BeNumerically(">", 0))
})

g.It("should add a member (trello) to a board", func() {
err := board.AddMember(member, "")
Expect(err).To(BeNil())
// TODO: Check to be sure trello *is* a member ... for now this should work
})

g.It("should check to see if member is an admin", func() {
isAdmin := board.IsAdmin(member)
Expect(isAdmin).To(BeFalse())
})

g.It("should check to see if an invalid member is an admin", func() {
invalidMember, err := client.Member("test")
Expect(err).To(BeNil())
Expect(invalidMember).NotTo(BeNil())
isAdmin := board.IsAdmin(invalidMember)
Expect(isAdmin).To(BeFalse())
})

g.It("should check to see if itself (me) is an admin", func() {
me, err := client.Member("me")
Expect(err).To(BeNil())
Expect(me).NotTo(BeNil())
isAdmin := board.IsAdmin(me)
Expect(isAdmin).To(BeTrue())
})

g.It("should remove a member from a board", func() {
g.Timeout(10 * time.Second) // The delete seems to take longer than 5 seconds
err := board.RemoveMember(member)
Expect(err).To(BeNil())
// TODO: Check to be sure trello is *not* a member ... for now this should work
})

g.It("should get the members of a board (after adding/removing)", func() {
members, err := board.GetMembers()
Expect(err).To(BeNil())
Expect(members).NotTo(BeNil())
})

g.It("should get the lists in a board", func() {
lists, err := board.Lists()
Expect(err).To(BeNil())
Expand All @@ -74,11 +126,6 @@ func TestBoard(t *testing.T) {
Expect(lists[2].Name).To(Equal("Done"))
})

g.It("should get the members of a board", func() {
_, err := board.Members()
Expect(err).To(BeNil())
})

g.It("should get all the actions in a board", func() {
_, err := board.Actions()
Expect(err).To(BeNil())
Expand Down Expand Up @@ -129,6 +176,7 @@ func TestBoard(t *testing.T) {
g.It("should duplicate (copy) the board", func() {
new, err := board.Duplicate("DUP-"+testBoardName, true)
Expect(err).To(BeNil())
Expect(new).NotTo(BeNil())
Expect(new.ID).NotTo(Equal(board.ID))
// and cleanup
err = new.Delete()
Expand Down
6 changes: 3 additions & 3 deletions card.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (c *Card) Checklists() (checklists []Checklist, err error) {

// Members - Get the Members of a card
// - https://developer.atlassian.com/cloud/trello/rest/api-group-cards/#api-cards-id-members-get
func (c *Card) Members() (members []Member, err error) {
func (c *Card) Members() (members []*Member, err error) {
body, err := c.client.Get("/cards/" + c.ID + "/members")
if err == nil {
members, err = parseListMembers(body, c.client)
Expand All @@ -103,7 +103,7 @@ func (c *Card) Members() (members []Member, err error) {
// The AddMember function requires a member (pointer) to add
// It returns the resulting member-list
// https://developers.trello.com/v1.0/reference#cardsididmembers
func (c *Card) AddMember(member *Member) (members []Member, err error) {
func (c *Card) AddMember(member *Member) (members []*Member, err error) {
payload := url.Values{}
payload.Set("value", member.ID)
body, err := c.client.Post("/cards/"+c.ID+"/idMembers", payload)
Expand All @@ -117,7 +117,7 @@ func (c *Card) AddMember(member *Member) (members []Member, err error) {
// - https://developer.atlassian.com/cloud/trello/rest/api-group-cards/#api-cards-id-idmembers-idmember-delete
// The RemoveMember function requires a member (pointer) to delete
// It returns the resulting member-list
func (c *Card) RemoveMember(member *Member) (members []Member, err error) {
func (c *Card) RemoveMember(member *Member) (members []*Member, err error) {
body, err := c.client.Delete("/cards/" + c.ID + "/idMembers/" + member.ID)
if err == nil {
members, err = parseListMembers(body, c.client)
Expand Down
21 changes: 20 additions & 1 deletion client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ limitations under the License.
package trello

import (
"fmt"
"net/http"
"os"
"testing"
"time"

goblin "github.com/franela/goblin"
. "github.com/onsi/gomega"
Expand All @@ -30,6 +32,12 @@ func TestClient(t *testing.T) {
RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

g.Describe("client tests", func() {
var board *Board
var testBoardName string

g.Before(func() {
testBoardName = fmt.Sprintf("GoTestTrello-Board-%v", time.Now().Unix())
})

g.It("should create a default client", func() {
_, err = NewClient()
Expand All @@ -53,7 +61,18 @@ func TestClient(t *testing.T) {
Expect(ver).To(Equal("1"))
})

// NOTE: Other methods will be tested as part of other tests
g.It("should create a board", func() {
board, err = client.CreateBoard(testBoardName)
Expect(err).To(BeNil())
Expect(board).NotTo(BeNil())
Expect(board.Name).To(Equal(testBoardName))
})

g.After(func() {
Expect(board).NotTo(BeNil())
err = board.Delete()
Expect(err).To(BeNil())
})
})

}
Loading

0 comments on commit 592516f

Please sign in to comment.