Skip to content

Commit cbbc8b6

Browse files
committed
Clean up sorting and query string for search API
1 parent d8ab8dd commit cbbc8b6

File tree

3 files changed

+68
-29
lines changed

3 files changed

+68
-29
lines changed

src/main/scala/codecheck/github/models/Search.scala

+50-17
Original file line numberDiff line numberDiff line change
@@ -3,64 +3,85 @@ package codecheck.github.models
33
import org.json4s.JValue
44
import org.json4s.JArray
55

6-
sealed abstract class SearchSort(val name: String) {
6+
sealed trait SearchSort {
7+
def name: String
78
override def toString = name
89
}
910

11+
sealed abstract class SearchRepositorySort(val name: String) extends SearchSort
12+
1013
object SearchRepositorySort {
11-
case object stars extends SearchSort("stars")
12-
case object forks extends SearchSort("forks")
13-
case object updated extends SearchSort("updated")
14+
case object stars extends SearchRepositorySort("stars")
15+
case object forks extends SearchRepositorySort("forks")
16+
case object updated extends SearchRepositorySort("updated")
1417

1518
val values = Array(stars, forks, updated)
1619

1720
def fromString(str: String) = values.filter(_.name == str).head
1821
}
1922

23+
sealed abstract class SearchCodeSort(val name: String) extends SearchSort
24+
2025
object SearchCodeSort {
21-
case object indexed extends SearchSort("indexed")
26+
case object indexed extends SearchCodeSort("indexed")
2227

2328
val values = Array(indexed)
2429

2530
def fromString(str: String) = values.filter(_.name == str).head
2631
}
2732

33+
sealed abstract class SearchIssueSort(val name: String) extends SearchSort
34+
2835
object SearchIssueSort {
29-
case object created extends IssueSort("created")
30-
case object updated extends IssueSort("updated")
31-
case object comments extends IssueSort("comments")
36+
case object created extends SearchIssueSort("created")
37+
case object updated extends SearchIssueSort("updated")
38+
case object comments extends SearchIssueSort("comments")
3239

3340
val values = Array(created, updated, comments)
3441

3542
def fromString(str: String) = values.filter(_.name == str).head
3643
}
3744

45+
sealed abstract class SearchUserSort(val name: String) extends SearchSort
3846

3947
object SearchUserSort {
40-
case object followers extends SearchSort("followers")
41-
case object repositories extends SearchSort("repositories")
42-
case object joined extends SearchSort("joined")
48+
case object followers extends SearchUserSort("followers")
49+
case object repositories extends SearchUserSort("repositories")
50+
case object joined extends SearchUserSort("joined")
4351

4452
val values = Array(followers, repositories, joined)
4553

4654
def fromString(str: String) = values.filter(_.name == str).head
4755
}
4856

49-
case class SearchInput (
50-
q: String,
51-
sort: Option[SearchSort] = None,
52-
order: SortDirection = SortDirection.desc
53-
) extends AbstractInput
57+
sealed trait SearchInput extends AbstractInput {
58+
def q: String
59+
def sort: Option[SearchSort]
60+
def order: SortDirection
61+
def query = s"?q=$q" + sort.map(sortBy => s"&sort=$sortBy&order=$order").getOrElse("")
62+
}
63+
64+
case class SearchRepositoryInput (
65+
val q: String,
66+
val sort: Option[SearchRepositorySort] = None,
67+
val order: SortDirection = SortDirection.desc
68+
) extends SearchInput
5469

5570
case class SearchRepositoryResult(value: JValue) extends AbstractJson(value) {
5671
def total_count: Long = get("total_count").toLong
5772
def incomplete_results: Boolean = boolean("incomplete_results")
5873
lazy val items = (value \ "items") match {
59-
case JArray(arr) => arr.map(new Repository(_))
74+
case JArray(arr) => arr.map(Repository(_))
6075
case _ => Nil
6176
}
6277
}
6378

79+
case class SearchCodeInput (
80+
q: String,
81+
sort: Option[SearchCodeSort] = None,
82+
order: SortDirection = SortDirection.desc
83+
) extends SearchInput
84+
6485
case class searchCodeItems (value: JValue) extends AbstractJson(value){
6586
def name: String = get("name")
6687
lazy val Repo = new Repository(value \ "repository")
@@ -75,6 +96,12 @@ case class SearchCodeResult(value: JValue) extends AbstractJson(value) {
7596
}
7697
}
7798

99+
case class SearchIssueInput (
100+
q: String,
101+
sort: Option[SearchIssueSort] = None,
102+
order: SortDirection = SortDirection.desc
103+
) extends SearchInput
104+
78105
case class SearchIssueResult(value: JValue) extends AbstractJson(value) {
79106
def total_count: Long = get("total_count").toLong
80107
def incomplete_results: Boolean = boolean("incomplete_results")
@@ -84,6 +111,12 @@ case class SearchIssueResult(value: JValue) extends AbstractJson(value) {
84111
}
85112
}
86113

114+
case class SearchUserInput (
115+
q: String,
116+
sort: Option[SearchUserSort] = None,
117+
order: SortDirection = SortDirection.desc
118+
) extends SearchInput
119+
87120
case class SearchUserResult(value: JValue) extends AbstractJson(value) {
88121
def total_count: Long = get("total_count").toLong
89122
def incomplete_results: Boolean = boolean("incomplete_results")

src/main/scala/codecheck/github/operations/SearchOp.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,28 @@ trait SearchOp {
1414
self: GitHubAPI =>
1515

1616
def searchRepositories(input: SearchInput): Future[SearchRepositoryResult] = {
17-
val path = s"/search/repositories?q=${input.q}&sort=${input.sort}&order=${input.order}"
17+
val path = s"/search/repositories${input.query}"
1818
exec("GET", path ).map { res =>
1919
SearchRepositoryResult(res.body)
2020
}
2121
}
2222

2323
def searchCode(input: SearchInput): Future[SearchCodeResult] = {
24-
val path = s"/search/code?q=${input.q}&sort=${input.sort}&order=${input.order}"
24+
val path = s"/search/code${input.query}"
2525
exec("GET", path ).map { res =>
2626
SearchCodeResult(res.body)
2727
}
2828
}
2929

3030
def searchIssues(input: SearchInput): Future[SearchIssueResult] = {
31-
val path = s"/search/issues?q=${input.q}&sort=${input.sort}&order=${input.order}"
31+
val path = s"/search/issues${input.query}"
3232
exec("GET", path ).map { res =>
3333
SearchIssueResult(res.body)
3434
}
3535
}
3636

3737
def searchUser(input: SearchInput): Future[SearchUserResult] = {
38-
val path = s"/search/users?q=${input.q}&sort=${input.sort}&order=${input.order}"
38+
val path = s"/search/users${input.query}"
3939
exec("GET", path ).map { res =>
4040
SearchUserResult(res.body)
4141
}

src/test/scala/SearchOpSpec.scala

+14-8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@ import org.scalatest.path.FunSpec
22
import scala.concurrent.Await
33
import scala.concurrent.ExecutionContext.Implicits.global
44
import codecheck.github.models.SortDirection
5-
import codecheck.github.models.SearchInput
6-
import codecheck.github.models.SearchSort
5+
import codecheck.github.models.SearchRepositoryInput
6+
import codecheck.github.models.SearchCodeInput
7+
import codecheck.github.models.SearchIssueInput
8+
import codecheck.github.models.SearchUserInput
9+
import codecheck.github.models.SearchRepositorySort
10+
import codecheck.github.models.SearchCodeSort
11+
import codecheck.github.models.SearchIssueSort
12+
import codecheck.github.models.SearchUserSort
713
import codecheck.github.models.SearchRepositoryResult
814
import codecheck.github.models.SearchCodeResult
915
import codecheck.github.models.searchCodeItems
@@ -17,7 +23,7 @@ class SearchOpSpec extends FunSpec
1723
it("with valid SearchInput should succeed") {
1824
var q = "tetris language:assembly"
1925
val q1 = q.trim.replaceAll(" ","+");
20-
val input = SearchInput(q1,sort=Some(SearchSort.stars),order=SortDirection.desc)
26+
val input = SearchRepositoryInput(q1,sort=Some(SearchRepositorySort.stars),order=SortDirection.desc)
2127
val res = Await.result(api.searchRepositories(input), TIMEOUT)
2228
assert(res.total_count >= 1)
2329
assert(res.items(0).id >= 1 )
@@ -31,7 +37,7 @@ class SearchOpSpec extends FunSpec
3137
it("with valid changed query(q) SearchInput should succeed") {
3238
var q = "jquery in:name,description"
3339
val q1 = q.trim.replaceAll(" ","+");
34-
val input = SearchInput(q1,sort=Some(SearchSort.stars),order=SortDirection.desc)
40+
val input = SearchRepositoryInput(q1,sort=Some(SearchRepositorySort.stars),order=SortDirection.desc)
3541
val res = Await.result(api.searchRepositories(input), TIMEOUT)
3642
assert(res.total_count >= 1)
3743
assert(res.items(0).id >= 1 )
@@ -45,7 +51,7 @@ class SearchOpSpec extends FunSpec
4551
it("with valid SearchInput q,no SortOrder should succeed") {
4652
var q = "addClass in:file language:js repo:jquery/jquery"
4753
val q1 = q.trim.replaceAll(" ","+");
48-
val input = SearchInput(q1,sort=None,order=SortDirection.desc)
54+
val input = SearchCodeInput(q1,sort=None,order=SortDirection.desc)
4955
val res = Await.result(api.searchCode(input), TIMEOUT)
5056
assert(res.total_count >= 1)
5157
assert(res.items(0).Repo.id >= 1 )
@@ -58,7 +64,7 @@ class SearchOpSpec extends FunSpec
5864
it("with valid SearchInput it should succeed") {
5965
var q = "function size:10000 language:python"
6066
val q1 = q.trim.replaceAll(" ","+");
61-
val input = SearchInput(q1,sort=Some(SearchSort.indexed),order=SortDirection.desc)
67+
val input = SearchCodeInput(q1,sort=Some(SearchCodeSort.indexed),order=SortDirection.desc)
6268
try {
6369
val res = Await.result(api.searchCode(input), TIMEOUT)
6470
} catch {
@@ -72,7 +78,7 @@ class SearchOpSpec extends FunSpec
7278
it("with valid SearchInput should succeed") {
7379
var q = "windows label:bug language:python state:open"
7480
val q1 = q.trim.replaceAll(" ","+");
75-
val input = SearchInput(q1,sort=Some(SearchSort.created),order=SortDirection.desc)
81+
val input = SearchIssueInput(q1,sort=Some(SearchIssueSort.created),order=SortDirection.desc)
7682
val res = Await.result(api.searchIssues(input), TIMEOUT)
7783
assert(res.total_count >= 1)
7884
assert(res.items(0).labels(0).name == "bug" )
@@ -85,7 +91,7 @@ class SearchOpSpec extends FunSpec
8591
var q = "tom repos:>42 followers:>1000"
8692
q = q.trim.replaceAll(" ","+")
8793
val q1 = q.replaceAll(">","%3E")
88-
val input = SearchInput(q1,sort=None,order=SortDirection.desc)
94+
val input = SearchUserInput(q1,sort=None,order=SortDirection.desc)
8995
val res = Await.result(api.searchUser(input), TIMEOUT)
9096
assert(res.total_count >= 0)
9197
assert(res.items(0).login.length >= 0)

0 commit comments

Comments
 (0)