Skip to content

Commit

Permalink
feat: Update the interface of sentence.get() and test.
Browse files Browse the repository at this point in the history
  • Loading branch information
vxern committed Jun 9, 2024
1 parent e4ee803 commit 6e7d970
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 18 deletions.
66 changes: 48 additions & 18 deletions src/tatoeba/sentence.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,7 @@ pub type Sentence {
correctness: Int,
/// A list of `Translation`s of the sentence.
translations: List(Translation),
/// ⚠️ It's not clear what this value represents.
///
/// If you know what it is, please fill it in.
///
// TODO(vxern): What does this value represent?
/// Note: This value will always be `None` given that this API wrapper does not
/// act as a user.
user_sentences: Option(List(Unknown)),
Expand Down Expand Up @@ -533,30 +530,63 @@ pub fn sentence(
))
}

/// Represents the ID of a sentence in the Tatoeba corpus.
///
pub opaque type SentenceId {
SentenceId(value: Int)
}

/// Represents an error resulting from an invalid value being used for
/// creating an ID.
///
pub type IdError {
/// Received an invalid input.
InvalidValueError(Int)
}

/// Creates a new ID to be used for querying the Tatoeba corpus.
///
pub fn new_id(id: Int) -> Result(SentenceId, IdError) {
case id {
negative if id < 0 || id == 0 -> Error(InvalidValueError(negative))
_ -> Ok(SentenceId(id))
}
}

/// The possible errors sentence retrieval can fail with.
///
pub type SentenceError {
/// Failed to make a request to Tatoeba.
RequestError(Dynamic)
/// Failed to decode the response data.
DecodeError(json.DecodeError)
}

/// Gets data of a single sentence in the Tatoeba corpus.
///
pub fn get(id id: Int) -> Result(Option(Sentence), String) {
pub fn get(id id: SentenceId) -> Result(Option(Sentence), SentenceError) {
let request =
api.new_request_to("/sentence/" <> int.to_string(id))
api.new_request_to("/sentence/" <> int.to_string(id.value))
|> request.set_method(http.Get)

use response <- result.try(
httpc.send(request)
|> result.map_error(fn(_) { "Failed to send request to Tatoeba." }),
|> result.map_error(fn(error) { RequestError(error) }),
)

case response.body |> string.length() {
0 -> Ok(None)
_ -> {
use sentence <- result.try(
json.decode(response.body, sentence)
|> result.map_error(fn(error) {
"Failed to decode sentence data: "
<> dynamic.classify(dynamic.from(error))
}),
)

Ok(Some(sentence))
}
_ -> response.body |> decode_payload() |> result.map(Some)
}
}

/// Decodes the received sentence payload.
///
fn decode_payload(payload: String) -> Result(Sentence, SentenceError) {
use sentence <- result.try(
json.decode(payload, sentence)
|> result.map_error(fn(error) { DecodeError(error) }),
)

Ok(sentence)
}
96 changes: 96 additions & 0 deletions test/sentence_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import gleam/option.{None, Some}
import gleeunit
import gleeunit/should
import tatoeba/sentence

pub fn main() {
gleeunit.main()
}

pub fn new_id_test() {
sentence.new_id(1)
|> should.be_ok()

sentence.new_id(0)
|> should.be_error()
|> should.equal(sentence.InvalidValueError(0))

sentence.new_id(-1)
|> should.be_error()
|> should.equal(sentence.InvalidValueError(-1))
}

pub fn sentence_exists_test() {
let assert Ok(id) = sentence.new_id(12_212_258)
let result = sentence.get(id)

result |> should.be_ok()

let assert Ok(sentence) = result

sentence |> should.be_some()
}

pub fn failed_request_test() {
// TODO: Test this.

Nil
}

pub fn failed_decoding_test() {
// TODO: Test this.

Nil
}

pub fn sentence_removed_test() {
let assert Ok(id) = sentence.new_id(4_802_955)
let result = sentence.get(id)

result |> should.be_ok()

let assert Ok(sentence) = result

should.be_none(sentence)
}

pub fn sentence_test() {
let assert Ok(id) = sentence.new_id(12_212_258)
let assert Ok(Some(sentence)) = sentence.get(id)

sentence.id |> should.equal(12_212_258)
sentence.text |> should.equal("This work is free of charge.")
sentence.language |> should.equal(Some("eng"))
sentence.language_tag |> should.equal("en")
sentence.language_name |> should.equal("English")
sentence.script |> should.equal(None)
sentence.license |> should.equal("CC BY 2.0 FR")
sentence.based_on_id |> should.equal(Some(5_686_783))
sentence.correctness |> should.equal(0)
sentence.translations
|> should.equal([
sentence.Translation(
id: 5_686_783,
text: "Această lucrare nu se plătește.",
language: Some("ron"),
language_tag: "ro",
language_name: "Romanian",
correctness: 0,
script: None,
transcriptions: [],
audios: [],
),
])
sentence.user_sentences |> should.equal(None)
sentence.list_ids |> should.equal(None)
sentence.transcriptions |> should.equal([])
sentence.audios |> should.equal([])
sentence.owner
|> should.equal(Some(sentence.User(claimed_native: None, username: "vxern")))
sentence.writing_direction |> should.equal(sentence.LeftToRight)
sentence.is_favorite |> should.equal(None)
sentence.is_owned_by_current_user |> should.equal(False)
sentence.permissions |> should.equal(None)
sentence.max_visible_translations |> should.equal(5)
sentence.current_user_review |> should.equal(None)
}

0 comments on commit 6e7d970

Please sign in to comment.