Skip to content

Commit

Permalink
Add support for listing cards, fixes #361 (#364)
Browse files Browse the repository at this point in the history
  • Loading branch information
bond15 committed Mar 13, 2020
1 parent 563f863 commit e1233d1
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 4 deletions.
37 changes: 35 additions & 2 deletions docs/docs/project.md
Expand Up @@ -3,7 +3,7 @@ layout: docs
title: Project API
permalink: project
---

# Project API

Note: The Projects API is currently available for developers to preview. During the preview period,
Expand All @@ -19,6 +19,8 @@ with Github4s, you can interact with:
- [List projects](#list-projects)
- [Columns](#columns)
- [List project columns](#list-project-columns)
- [Cards](#cards)
- [List project cards](#list-project-cards-by-column)

The following examples assume the following imports and token:

Expand Down Expand Up @@ -124,4 +126,35 @@ The `result` on the right is the corresponding [List[Column]][column-scala].

See [the API doc](https://developer.github.com/v3/projects/columns/#list-project-columns) for full reference.

[column-scala]: https://github.com/47deg/github4s/blob/master/github4s/src/main/scala/github4s/domain/Column.scala
[column-scala]: https://github.com/47deg/github4s/blob/master/github4s/src/main/scala/github4s/domain/Project.scala

### Cards

#### List project cards by column

You can list the cards for a particular column with `listCards`; it takes as arguments:

- `column_id`: column id for which we want to retrieve the cards.
- `archived_state`: filters the project cards that are returned by the card's state.
Can be one of `all`,`archived`, or `not_archived`. Default: `not_archived`, optional.
- `pagination`: Limit and Offset for pagination, optional.
- `header`: headers to include in the request, optional.

To list the columns for project_id `8271018`:

```scala mdoc:compile-only
val listCards = Github[IO](accessToken).projects.listCards(
column_id = 8271018,
headers = Map("Accept" -> "application/vnd.github.inertia-preview+json"))
val response = listCards.unsafeRunSync()
response.result match {
case Left(e) => println(s"Something went wrong: ${e.getMessage}")
case Right(r) => println(r)
}
```

The `result` on the right is the corresponding [List[Card]][card-scala].

See [the API doc](https://developer.github.com/v3/projects/cards/#list-project-cards) for full reference.

[card-scala]: https://github.com/47deg/github4s/blob/master/github4s/src/main/scala/github4s/domain/Project.scala
1 change: 1 addition & 0 deletions github4s/src/main/scala/github4s/Decoders.scala
Expand Up @@ -280,5 +280,6 @@ object Decoders {
implicit val decodeMilestone: Decoder[Milestone] = deriveDecoder[Milestone]
implicit val decodeProject: Decoder[Project] = deriveDecoder[Project]
implicit val decodeColumn: Decoder[Column] = deriveDecoder[Column]
implicit val decodeCard: Decoder[Card] = deriveDecoder[Card]

}
17 changes: 17 additions & 0 deletions github4s/src/main/scala/github4s/algebras/Projects.scala
Expand Up @@ -71,4 +71,21 @@ trait Projects[F[_]] {
headers: Map[String, String] = Map()
): F[GHResponse[List[Column]]]

/**
* List the cards belonging to a specific column id
*
* @param column_id Column id for which we want to retrieve the cards
* @param archived_state Filters the project cards that are returned by the card's state.
* Can be one of all,archived, or not_archived. Default: not_archived
* @param pagination Limit and Offset for pagination
* @param headers Optional user headers to include in the request
* @return GHResponse with the list of cards belonging to this column id
*/
def listCards(
column_id: Int,
archived_state: Option[String] = None,
pagination: Option[Pagination] = None,
headers: Map[String, String] = Map()
): F[GHResponse[List[Card]]]

}
14 changes: 14 additions & 0 deletions github4s/src/main/scala/github4s/domain/Project.scala
Expand Up @@ -64,3 +64,17 @@ final case class Column(
created_at: String,
updated_at: String
)

final case class Card(
url: String,
project_url: String,
id: Int,
node_id: String,
note: Option[String],
archived: Boolean,
creator: Creator,
created_at: String,
updated_at: String,
column_url: String,
content_url: Option[String]
)
Expand Up @@ -18,7 +18,7 @@ package github4s.interpreters

import github4s.GithubResponses.GHResponse
import github4s.algebras.Projects
import github4s.domain.{Column, Pagination, Project}
import github4s.domain.{Column, Card, Pagination, Project}
import github4s.http.HttpClient
import github4s.Decoders._

Expand Down Expand Up @@ -67,4 +67,19 @@ class ProjectsInterpreter[F[_]](
Map(),
pagination
)

override def listCards(
column_id: Int,
archived_state: Option[String],
pagination: Option[Pagination],
headers: Map[String, String]
): F[GHResponse[List[Card]]] =
client.get[List[Card]](
accessToken,
s"projects/columns/$column_id/cards",
headers,
archived_state.fold(Map.empty[String, String])(s => Map("archived_state" -> s)),
pagination
)

}
Expand Up @@ -18,7 +18,7 @@ package github4s.integration

import cats.effect.IO
import github4s.Github
import github4s.domain.{Column, Project}
import github4s.domain.{Card, Column, Project}
import github4s.utils.{BaseIntegrationSpec, Integration}

trait GHProjectsSpec extends BaseIntegrationSpec {
Expand Down Expand Up @@ -103,4 +103,22 @@ trait GHProjectsSpec extends BaseIntegrationSpec {
response.statusCode shouldBe notFoundStatusCode
}

"Project >> ListCards" should "return the expected cards when a valid column id is provided" taggedAs Integration in {
val response = Github[IO](accessToken).projects
.listCards(validColumnId, headers = headerUserAgent ++ headerAccept)
.unsafeRunSync()

testIsRight[List[Card]](response, r => r.nonEmpty shouldBe true)
response.statusCode shouldBe okStatusCode
}

it should "return error when an invalid column id is passed" taggedAs Integration in {
val response =
Github[IO](accessToken).projects
.listCards(invalidColumnId, headers = headerUserAgent ++ headerAccept)
.unsafeRunSync()

testIsLeft(response)
response.statusCode shouldBe notFoundStatusCode
}
}
18 changes: 18 additions & 0 deletions github4s/src/test/scala/github4s/unit/ProjectSpec.scala
Expand Up @@ -83,4 +83,22 @@ class ProjectSpec extends BaseSpec {
projects.listColumns(validProjectId, None, headers = headerUserAgent ++ headerAccept)

}

"Project.listCards" should "call to httpClient.get with the right parameters" in {

val response: IO[GHResponse[List[Card]]] =
IO(GHResponse(List(card).asRight, okStatusCode, Map.empty))

implicit val httpClientMock = httpClientMockGet[List[Card]](
url = s"projects/columns/$validColumnId/cards",
headers = headerAccept,
response = response
)

val project = new ProjectsInterpreter[IO]

project.listCards(validColumnId, None, None, headerUserAgent ++ headerAccept)

}

}
36 changes: 36 additions & 0 deletions github4s/src/test/scala/github4s/utils/TestData.scala
Expand Up @@ -486,4 +486,40 @@ trait TestData extends DummyGithubUrls {
updated_at = "2019-07-04T09:39:01Z"
)

val validColumnId = 8271018
val invalidColumnId = -32

val card = Card(
url = "https://api.github.com/projects/columns/cards/34323195",
project_url = "https://api.github.com/projects/4085286",
id = 34323195,
node_id = "MDExOlByb2plY3RDYXJkMzQzMjMxOTU=",
note = Some("Test Card"),
archived = false,
creator = Creator(
login = "calvellido",
id = 7753447,
node_id = "MDQ6VXNlcjc3NTM0NDc=",
avatar_url = "https://avatars0.githubusercontent.com/u/7753447?v=4",
gravatar_id = None,
url = "https://api.github.com/users/calvellido",
html_url = "https://github.com/calvellido",
followers_url = "https://api.github.com/users/calvellido/followers",
following_url = "https://api.github.com/users/calvellido/following{/other_user}",
gists_url = "https://api.github.com/users/calvellido/gists{/gist_id}",
starred_url = "https://api.github.com/users/calvellido/starred{/owner}{/repo}",
subscriptions_url = "https://api.github.com/users/calvellido/subscriptions",
organizations_url = "https://api.github.com/users/calvellido/orgs",
repos_url = "https://api.github.com/users/calvellido/repos",
events_url = "https://api.github.com/users/calvellido/events{/privacy}",
received_events_url = "https://api.github.com/users/calvellido/received_events",
`type` = "User",
site_admin = false
),
created_at = "2018-11-02T09:36:28Z",
updated_at = "2019-07-04T09:39:01Z",
column_url = "https://api.github.com/projects/columns/8271018",
content_url = None
)

}

0 comments on commit e1233d1

Please sign in to comment.