-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix 12 search api #70
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
c516052
#36 Implemented searchRepositories v1
sukeshni 4a37671
Parsing input Query q,Test for searchRepositories
sukeshni 37b5cb1
searchCode, searchIssues, searchUser
sukeshni 4b91b99
Tests for searchCode,searchIssues,searchUser
sukeshni 2d39a09
Refactoring
sukeshni 725803f
Assert condition changed for searchUser
sukeshni d8ab8dd
Separate case classes for search sorts
ashawley cbbc8b6
Clean up sorting and query string for search API
ashawley 8f62cb4
Fix case of SearchCodeItems and rename repository member
ashawley 1cd570e
Improve tests for Code Search API
ashawley File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package codecheck.github.models | ||
|
||
import org.json4s.JValue | ||
import org.json4s.JArray | ||
|
||
sealed trait SearchSort { | ||
def name: String | ||
override def toString = name | ||
} | ||
|
||
sealed abstract class SearchRepositorySort(val name: String) extends SearchSort | ||
|
||
object SearchRepositorySort { | ||
case object stars extends SearchRepositorySort("stars") | ||
case object forks extends SearchRepositorySort("forks") | ||
case object updated extends SearchRepositorySort("updated") | ||
|
||
val values = Array(stars, forks, updated) | ||
|
||
def fromString(str: String) = values.filter(_.name == str).head | ||
} | ||
|
||
sealed abstract class SearchCodeSort(val name: String) extends SearchSort | ||
|
||
object SearchCodeSort { | ||
case object indexed extends SearchCodeSort("indexed") | ||
|
||
val values = Array(indexed) | ||
|
||
def fromString(str: String) = values.filter(_.name == str).head | ||
} | ||
|
||
sealed abstract class SearchIssueSort(val name: String) extends SearchSort | ||
|
||
object SearchIssueSort { | ||
case object created extends SearchIssueSort("created") | ||
case object updated extends SearchIssueSort("updated") | ||
case object comments extends SearchIssueSort("comments") | ||
|
||
val values = Array(created, updated, comments) | ||
|
||
def fromString(str: String) = values.filter(_.name == str).head | ||
} | ||
|
||
sealed abstract class SearchUserSort(val name: String) extends SearchSort | ||
|
||
object SearchUserSort { | ||
case object followers extends SearchUserSort("followers") | ||
case object repositories extends SearchUserSort("repositories") | ||
case object joined extends SearchUserSort("joined") | ||
|
||
val values = Array(followers, repositories, joined) | ||
|
||
def fromString(str: String) = values.filter(_.name == str).head | ||
} | ||
|
||
sealed trait SearchInput extends AbstractInput { | ||
def q: String | ||
def sort: Option[SearchSort] | ||
def order: SortDirection | ||
def query = s"?q=$q" + sort.map(sortBy => s"&sort=$sortBy&order=$order").getOrElse("") | ||
} | ||
|
||
case class SearchRepositoryInput ( | ||
val q: String, | ||
val sort: Option[SearchRepositorySort] = None, | ||
val order: SortDirection = SortDirection.desc | ||
) extends SearchInput | ||
|
||
case class SearchRepositoryResult(value: JValue) extends AbstractJson(value) { | ||
def total_count: Long = get("total_count").toLong | ||
def incomplete_results: Boolean = boolean("incomplete_results") | ||
lazy val items = (value \ "items") match { | ||
case JArray(arr) => arr.map(Repository(_)) | ||
case _ => Nil | ||
} | ||
} | ||
|
||
case class SearchCodeInput ( | ||
q: String, | ||
sort: Option[SearchCodeSort] = None, | ||
order: SortDirection = SortDirection.desc | ||
) extends SearchInput | ||
|
||
case class SearchCodeItem(value: JValue) extends AbstractJson(value) { | ||
def name: String = get("name") | ||
def path: String = get("path") | ||
def sha: String = get("sha") | ||
def url: String = get("url") | ||
def git_url: String = get("git_url") | ||
def html_url: String = get("html_url") | ||
def score: Double = get("score").toDouble | ||
lazy val repository = Repository(value \ "repository") | ||
} | ||
|
||
case class SearchCodeResult(value: JValue) extends AbstractJson(value) { | ||
def total_count: Long = get("total_count").toLong | ||
def incomplete_results: Boolean = boolean("incomplete_results") | ||
lazy val items = (value \ "items") match { | ||
case JArray(arr) => arr.map(SearchCodeItem(_)) | ||
case _ => Nil | ||
} | ||
} | ||
|
||
case class SearchIssueInput ( | ||
q: String, | ||
sort: Option[SearchIssueSort] = None, | ||
order: SortDirection = SortDirection.desc | ||
) extends SearchInput | ||
|
||
case class SearchIssueResult(value: JValue) extends AbstractJson(value) { | ||
def total_count: Long = get("total_count").toLong | ||
def incomplete_results: Boolean = boolean("incomplete_results") | ||
lazy val items = (value \ "items") match { | ||
case JArray(arr) => arr.map(Issue(_)) | ||
case _ => Nil | ||
} | ||
} | ||
|
||
case class SearchUserInput ( | ||
q: String, | ||
sort: Option[SearchUserSort] = None, | ||
order: SortDirection = SortDirection.desc | ||
) extends SearchInput | ||
|
||
case class SearchUserResult(value: JValue) extends AbstractJson(value) { | ||
def total_count: Long = get("total_count").toLong | ||
def incomplete_results: Boolean = boolean("incomplete_results") | ||
lazy val items = (value \ "items") match { | ||
case JArray(arr) => arr.map(User(_)) | ||
case _ => Nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package codecheck.github.operations | ||
|
||
import scala.concurrent.Future | ||
import scala.concurrent.ExecutionContext.Implicits.global | ||
|
||
import codecheck.github.api.GitHubAPI | ||
import codecheck.github.models.SearchInput | ||
import codecheck.github.models.SearchRepositoryResult | ||
import codecheck.github.models.SearchCodeResult | ||
import codecheck.github.models.SearchIssueResult | ||
import codecheck.github.models.SearchUserResult | ||
|
||
trait SearchOp { | ||
self: GitHubAPI => | ||
|
||
def searchRepositories(input: SearchInput): Future[SearchRepositoryResult] = { | ||
val path = s"/search/repositories${input.query}" | ||
exec("GET", path ).map { res => | ||
SearchRepositoryResult(res.body) | ||
} | ||
} | ||
|
||
def searchCode(input: SearchInput): Future[SearchCodeResult] = { | ||
val path = s"/search/code${input.query}" | ||
exec("GET", path ).map { res => | ||
SearchCodeResult(res.body) | ||
} | ||
} | ||
|
||
def searchIssues(input: SearchInput): Future[SearchIssueResult] = { | ||
val path = s"/search/issues${input.query}" | ||
exec("GET", path ).map { res => | ||
SearchIssueResult(res.body) | ||
} | ||
} | ||
|
||
def searchUser(input: SearchInput): Future[SearchUserResult] = { | ||
val path = s"/search/users${input.query}" | ||
exec("GET", path ).map { res => | ||
SearchUserResult(res.body) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import org.scalatest.path.FunSpec | ||
import scala.concurrent.Await | ||
import scala.concurrent.ExecutionContext.Implicits.global | ||
import codecheck.github.models.SortDirection | ||
import codecheck.github.models.SearchRepositoryInput | ||
import codecheck.github.models.SearchCodeInput | ||
import codecheck.github.models.SearchIssueInput | ||
import codecheck.github.models.SearchUserInput | ||
import codecheck.github.models.SearchRepositorySort | ||
import codecheck.github.models.SearchCodeSort | ||
import codecheck.github.models.SearchIssueSort | ||
import codecheck.github.models.SearchUserSort | ||
import codecheck.github.models.SearchRepositoryResult | ||
import codecheck.github.models.SearchCodeResult | ||
import codecheck.github.exceptions.GitHubAPIException | ||
|
||
class SearchOpSpec extends FunSpec | ||
with Constants | ||
{ | ||
|
||
describe("searchRepositories") { | ||
it("with valid SearchInput should succeed") { | ||
val q = "tetris language:assembly".trim.replaceAll(" ","+") | ||
val input = SearchRepositoryInput(q,sort=Some(SearchRepositorySort.stars),order=SortDirection.desc) | ||
val res = Await.result(api.searchRepositories(input), TIMEOUT) | ||
assert(res.total_count >= 1) | ||
assert(res.items(0).id >= 1 ) | ||
assert(res.items(0).name.length >= 1) | ||
assert(res.items(0).full_name.length >= 1) | ||
assert(res.items(0).description.isDefined) | ||
assert(res.items(0).open_issues_count >= 0) | ||
assert(res.items(0).language == "Assembly") | ||
assert(res.items(0).stargazers_count > res.items(1).stargazers_count) | ||
} | ||
it("with valid changed query(q) SearchInput should succeed") { | ||
val q = "jquery in:name,description".trim.replaceAll(" ","+") | ||
val input = SearchRepositoryInput(q,sort=Some(SearchRepositorySort.stars),order=SortDirection.desc) | ||
val res = Await.result(api.searchRepositories(input), TIMEOUT) | ||
assert(res.total_count >= 1) | ||
assert(res.items(0).id >= 1 ) | ||
assert(res.items(0).name.length >= 1) | ||
assert(res.items(0).full_name.length >= 1) | ||
assert(res.items(0).description.isDefined) | ||
assert(res.items(0).open_issues_count >= 0) | ||
} | ||
} | ||
describe("searchCode") { | ||
it("with valid SearchInput q,no SortOrder should succeed") { | ||
val q = "addClass in:file language:js repo:jquery/jquery".trim.replaceAll(" ","+") | ||
val input = SearchCodeInput(q,sort=None,order=SortDirection.desc) | ||
val res = Await.result(api.searchCode(input), TIMEOUT) | ||
assert(res.total_count >= 1) | ||
assert(res.items(0).repository.id >= 1 ) | ||
assert(res.items(0).sha.length >= 40) | ||
assert(res.items(0).score >= 0d) | ||
assert(res.items(0).repository.full_name == "jquery/jquery") | ||
} | ||
it("with valid SearchInput it should succeed") { | ||
val q = "function size:10000 language:python".trim.replaceAll(" ","+") | ||
val input = SearchCodeInput(q,sort=Some(SearchCodeSort.indexed),order=SortDirection.asc) | ||
val res = Await.result(api.searchCode(input), TIMEOUT) | ||
assert(res.total_count >= 1) | ||
assert(res.items(0).repository.id >= 1 ) | ||
assert(res.items(0).path.endsWith(".py")) | ||
assert(res.items(0).sha.length >= 40) | ||
assert(res.items(0).score >= 0d) | ||
assert(res.items(0).repository.`private` == false) | ||
} | ||
} | ||
describe("searchIssues") { | ||
it("with valid SearchInput should succeed") { | ||
val q = "windows label:bug language:python state:open".trim.replaceAll(" ","+") | ||
val input = SearchIssueInput(q,sort=Some(SearchIssueSort.created),order=SortDirection.desc) | ||
val res = Await.result(api.searchIssues(input), TIMEOUT) | ||
assert(res.total_count >= 1) | ||
assert(res.items(0).labels(0).name == "bug" ) | ||
assert(res.items(0).state == "open") | ||
assert(((res.items(0).created_at).compareTo(res.items(1).created_at)) > 0) | ||
} | ||
} | ||
describe("searchUser") { | ||
it("with valid SearchInput should succeed") { | ||
val q = "tom repos:>42 followers:>1000" | ||
.trim.replaceAll(" ","+") | ||
.replaceAll(">","%3E") | ||
val input = SearchUserInput(q,sort=None,order=SortDirection.desc) | ||
val res = Await.result(api.searchUser(input), TIMEOUT) | ||
assert(res.total_count >= 0) | ||
assert(res.items(0).login.length >= 0) | ||
assert(res.items(0).id >= 0) | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was the only compatibility change in this pull request.
There was no test case to catch it. The
RepositoryCommand
uses it, but the genericPrintList.build
function doesn't care about the type.