Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
asadow committed Oct 30, 2023
1 parent 41b251c commit 4989fd6
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 35 deletions.
25 changes: 21 additions & 4 deletions R/parse.R
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
#' Extract and parse body from Megamation API response
#' Extract data from Megamation API response
#'
#' `mm_resp_parse()` extracts the raw bytes from an API response and parses
#' it, returning an R list object. After converting bytes to characters, encoding is done to resolve
#' a UTF-8 issue from Megamation's side.
#' `mm_resp_extract()` parses the raw bytes from an API response,
#' and extracts data from the parsed object.
#'
#' @param resp An API response.
#' @description The body of the response contains raw bytes.
#' After converting these bytes to a string, encoding is done to resolve
#' a UTF-8 issue from Megamation's side.
#' @returns A list.
#' @export
mm_resp_extract <- function(resp) {
.from <- sub(".*/@", "", resp$url) |> tolower()

resp |>
mm_resp_parse() |>
parsed_extract(.from)
}

#' Parse body from Megamation API response
#'
#' `mm_resp_parse()` parses the raw bytes from an API response,
#' returning an R list object. After converting bytes to characters,
#' encoding is done to resolve
#' a UTF-8 issue from Megamation's side.
#'
#' @param resp An API response.
#' @returns A list.
#' @export
mm_resp_parse <- function(resp) {
resp |>
httr2::resp_body_raw() |>
Expand Down
12 changes: 6 additions & 6 deletions R/perform.R
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@
mm_get <- function(endpoint, ..., opts = req_opts()) {

req <- mm_request(endpoint, ..., opts = opts)
req <- if (!opts$.paginate) {
req
} else mm_req_paginate(req)

resp <- mm_req_perform(req)

tbl_result <- if (!is_paginated(req)) {
tbl_result <- if (!opts$.paginate) {
resp[[1]] |>
mm_resp_parse() |>
parsed_extract(.get) |>
mm_resp_extract() |>
tibble::as_tibble()
} else {
resp |>
Expand All @@ -61,11 +64,8 @@ mm_get <- function(endpoint, ..., opts = req_opts()) {
}

remove_api_urls(tbl_result)

}



#' Perform a Megamation API request
#'
#' @description
Expand Down
49 changes: 40 additions & 9 deletions R/request.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,40 @@
#' Create a Megamation API request
#'
#' @description
#' `mm_req()` creates a request using [httr2::request()] and
#' does the following:
#'
#' * Inserts the base URL using the environment variable `MEGAMATION_URL` from
#' your `.Renviron`. Your key and base URL can be set using [mm_set_creds()].
#' * Appends the URL with the endpoint defined by parameter `endpoint`.
#' * Sets the user-agent as the GitHub `megamation` package.
#' * Authenticates the request with HTTP basic authentication using
#' environment variables `MEGAMATION_KEY` and `MEGAMATION_URL`
#' from your `.Renviron`.
#' * Handles HTTP errors so useful information from the response is extracted
#' (e.g. "No response body").
#' * Adds caching of responses if available. See [httr2::req_cache()].
#'
#' @param endpoint The API endpoint. For example,
#' `"timecard"` for employee transactions, and `"workorder"`
#' for work orders. All endpoints are listed at
#' https://apidocs.megamation.com/.
#' @returns An object of class `httr2_request`.
#' @export
mm_req <- function(endpoint, opts = req_opts()) {
if (!inherits(opts, "megamation_req_opts")) {
cli::cli_abort("{.arg opts} must be created by {.fun req_opts}.")
}

req <- req |>
httr2::req_user_agent(
"megamation (https://github.com/asadow/megamation)"
) |>
httr2::req_auth_basic("APIDL", opts$.key) |>
httr2::req_error(body = mm_error_body) |>
httr2::req_cache(tempdir(), debug = TRUE)
}

#' Create a Megamation API request
#'
#' @description
Expand All @@ -15,16 +52,16 @@
#' from your `.Renviron`.
#' * Handles HTTP errors so useful information from the response is extracted
#' (e.g. "No response body").
#' * Automatic caching of responses. See [httr2::req_cache()].
#' * Adds caching of responses if available. See [httr2::req_cache()].
#'
#' After creating a request with `mm_request()`, you can
#' If you create a GET request with `mm_request()`, you can then
#'
#' * Paginate the request using [mm_req_paginate()].
#' * Perform the request and fetch the response using [httr2::req_perform()] or
#' [httr2::req_perform_iteratively()] if the request is paginated.
#'
#' Alternatively,
#' [mm_get()] can at once define, paginate, and perform a request.
#' [mm_get()] can at once define, paginate, and perform a GET request.
#'
#' @param endpoint The API endpoint. For example,
#' `"timecard"` for employee transactions, and `"workorder"`
Expand Down Expand Up @@ -71,12 +108,6 @@ mm_request <- function(endpoint, ..., allfields = TRUE, opts = req_opts()) {
httr2::req_error(body = mm_error_body) |>
httr2::req_cache(tempdir(), debug = TRUE)

cannot_be_paginated <- opts$.get != "data"
if (cannot_be_paginated || !opts$.paginate) {
return(req)
}

mm_req_paginate(req)
}


10 changes: 9 additions & 1 deletion man/mm_error_body.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions man/mm_get.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions man/mm_req_perform.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/mm_request.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 14 additions & 11 deletions tests/testthat/test-creds.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ test_that("absence of API key or URL raises an error", {
})

test_that("testing key", {
skip_on_cran()
expect_equal(
get_env_key(),
testing_key()
Expand All @@ -33,29 +34,31 @@ test_that("mm_set_creds() gives bad url error", {
})

test_that("mm_set_creds() sets credentials", {
defer({
mm_set_creds(
key = testing_key(),
url = 'https://api.megamation.com/uog/dl',
overwrite = TRUE
)
})
mm_set_creds(
key = "1",
url = "https://api.megamation.com/uw/joe/",
overwrite = TRUE
)
expect_equal(
get_env_key(),
"1"
)
expect_false(
endsWith(Sys.getenv("MEGAMATION_URL"), "/")
)
expect_equal(
get_env_url(),
"https://api.megamation.com/uw/joe"
)

skip_on_cran()
withr::defer({
mm_set_creds(
key = testing_key(),
url = 'https://api.megamation.com/uog/dl',
overwrite = TRUE
)
})
expect_equal(
get_env_key(),
"1"
)
})

test_that("presence of bad creds raises an error", {
Expand Down
4 changes: 2 additions & 2 deletions tests/testthat/test-parse.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ with_mock_dir("status", {

with_mock_dir("status_schema", {
test_that("parse() gives list with embedded data", {
resp <- mm_request("status", opts = req_opts(.get = "criteria")) |>
resp <- mm_request("status", allfields = FALSE, opts = req_opts(.get = "schema")) |>
httr2::req_perform()
parsed <- resp |> mm_resp_parse()
df <- extract_schema(parsed)
Expand All @@ -37,7 +37,7 @@ with_mock_dir("status_schema", {

with_mock_dir("status_criteria-or-labels", {
test_that("extract_criteria() gives correct names", {
resp <- mm_request("status", opts = req_opts(.get = "criteria")) |>
resp <- mm_request("status", allfields = FALSE, opts = req_opts(.get = "criteria")) |>
httr2::req_perform()
parsed <- resp |> mm_resp_parse()
df <- extract_criteria(parsed)
Expand Down

0 comments on commit 4989fd6

Please sign in to comment.