Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions example_with_targets/prepare.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
query Input {
id
}
17 changes: 17 additions & 0 deletions example_with_targets/run.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
query Input(
$selector: LineSelector!
$first: Int
$country: CountryCode
$minimumQuantity: Int! = 1
$tags: [String]
) {
matchingLines(
selector: $selector
first: $first
country: $country
minimumQuantity: $minimumQuantity
tags: $tags
) {
id
}
}
72 changes: 72 additions & 0 deletions example_with_targets/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ A void type that can be used to return a null value from a mutation.
"""
scalar Void

"""
Arbitrary JSON.
"""
scalar JSON

"""
A cart line representing an item in the cart.
"""
Expand All @@ -87,6 +92,17 @@ type Input {
optionalArrayOfArrays: [[String!]!]
optionalArrayOfOptionalArrays: [[String!]]
cartLines: [CartLine!] @restrictTarget(only: ["test.target-cart"])
"""
The cart lines that match a selector. Its arguments are what `test.target-run` takes as
variables from `test.target-prepare`.
"""
matchingLines(
selector: LineSelector!
first: Int
country: CountryCode
minimumQuantity: Int! = 1
tags: [String]
): [CartLine!]! @restrictTarget(only: ["test.target-run"])
}

"""
Expand Down Expand Up @@ -122,6 +138,26 @@ type MutationRoot {
"""
result: FunctionTargetCartResult!
): Void!

"""
The function for API target Prepare.
"""
targetPrepare(
"""
The result of calling the function for API target Prepare.
"""
result: FunctionTargetPrepareResult!
): Void!

"""
The function for API target Run.
"""
targetRun(
"""
The result of calling the function for API target Run.
"""
result: FunctionTargetRunResult!
): Void!
}

"""
Expand Down Expand Up @@ -152,6 +188,42 @@ input FunctionTargetCartResult {
totalQuantity: Int!
}

"""
The result of API target Prepare.
"""
input FunctionTargetPrepareResult {
"""
The variables for the input query of API target Run.
"""
variables: JSON!
}

"""
The result of API target Run.
"""
input FunctionTargetRunResult {
lineCount: Int!
}

"""
Selects cart lines by ID, or by a filter.
"""
input LineSelector @oneOf {
id: ID
filter: LineFilter
}

input LineFilter {
titles: [String!]
match: LineMatch! = ALL
minimumPrice: Decimal
}

enum LineMatch {
ALL
ANY
}

input Operation @oneOf {
doThis: This
doThat: That
Expand Down
8 changes: 8 additions & 0 deletions example_with_targets/shopify.function.extension.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@ input_query = "a.graphql"
target = "test.target-b"
export = "function_b"
input_query = "b.graphql"

[[targeting]]
target = "test.target-prepare"
input_query = "prepare.graphql"

[[targeting]]
target = "test.target-run"
input_query = "run.graphql"
37 changes: 36 additions & 1 deletion example_with_targets/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use std::process;

use shopify_function::prelude::*;
use shopify_function::scalars::Decimal;
use shopify_function::Result;

#[allow(dead_code)]
#[derive(Deserialize)]
#[shopify_function(rename_all = "camelCase")]
struct Configuration {}

#[typegen("./schema.graphql", enums_as_str = ["CountryCode"])]
#[typegen("./schema.graphql", enums_as_str = ["CountryCode"], custom_scalar_overrides = {
"FunctionTargetPrepareResult.variables" => target_run::InputVariables,
})]
mod schema {
#[query("./a.graphql")]
pub mod target_a {}
Expand All @@ -18,6 +21,12 @@ mod schema {

#[query("./cart.graphql")]
pub mod target_cart {}

#[query("./prepare.graphql")]
pub mod target_prepare {}

#[query("./run.graphql")]
pub mod target_run {}
}

#[shopify_function]
Expand Down Expand Up @@ -62,6 +71,32 @@ fn target_cart(input: schema::target_cart::Input) -> Result<schema::FunctionTarg
Ok(schema::FunctionTargetCartResult { total_quantity })
}

#[shopify_function]
fn target_prepare(
input: schema::target_prepare::Input,
) -> Result<schema::FunctionTargetPrepareResult> {
let variables = schema::target_run::InputVariables {
selector: schema::LineSelector::Filter(schema::LineFilter {
titles: Some(vec![input.id().clone()]),
r#match: Some(schema::LineMatch::Any),
minimum_price: Some(Decimal(1.5)),
}),
first: Some(10),
country: None,
minimum_quantity: None,
tags: Some(vec![Some("sale".to_string()), None]),
};

Ok(schema::FunctionTargetPrepareResult { variables })
}

#[shopify_function]
fn target_run(input: schema::target_run::Input) -> Result<schema::FunctionTargetRunResult> {
Ok(schema::FunctionTargetRunResult {
line_count: input.matching_lines().len() as i32,
})
}

fn main() {
log!("Invoke a named export");
process::abort()
Expand Down
73 changes: 73 additions & 0 deletions example_with_targets/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,79 @@ fn test_one_of_input_object_serialization_writes_active_variant() -> Result<()>
Ok(())
}

#[test]
fn test_target_prepare_returns_the_variables_run_declares() -> Result<()> {
let result = run_function_with_input(
target_prepare,
r#"
{
"id": "gid://shopify/CartLine/1"
}
"#,
)?;

// `None` omits `country` and `minimumQuantity`.
assert_eq!(
serde_json::json!({
"variables": {
"selector": {
"filter": {
"titles": ["gid://shopify/CartLine/1"],
"match": "ANY",
"minimumPrice": "1.5"
}
},
"first": 10,
"tags": ["sale", null]
}
}),
serialize_to_json(&result)?
);
Ok(())
}

#[test]
fn test_variables_serialization_omits_none_variables() -> Result<()> {
let variables = crate::schema::target_run::InputVariables {
selector: crate::schema::LineSelector::Id("gid://shopify/CartLine/1".to_string()),
first: None,
country: Some("CA".to_string()),
minimum_quantity: Some(2),
tags: None,
};

assert_eq!(
serde_json::json!({
"selector": { "id": "gid://shopify/CartLine/1" },
"country": "CA",
"minimumQuantity": 2
}),
serialize_to_json(&variables)?
);
Ok(())
}

#[test]
fn test_target_run_counts_matching_lines() -> Result<()> {
let result = run_function_with_input(
target_run,
r#"
{
"matchingLines": [
{ "id": "gid://shopify/CartLine/1" },
{ "id": "gid://shopify/CartLine/2" }
]
}
"#,
)?;

assert_eq!(
crate::schema::FunctionTargetRunResult { line_count: 2 },
result
);
Ok(())
}

fn serialize_to_json<T: Serialize + ?Sized>(value: &T) -> Result<serde_json::Value> {
let mut context = Context::new_with_input(serde_json::json!({}));
value.serialize(&mut context)?;
Expand Down
30 changes: 29 additions & 1 deletion integration_tests/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,34 @@ fn test_example_with_targets_target_b() -> Result<()> {
Ok(())
}

#[test]
fn test_example_with_targets_target_prepare() -> Result<()> {
let path = EXAMPLE_WITH_TARGETS_RESULT
.as_ref()
.map_err(|e| anyhow::anyhow!("Failed to prepare example: {}", e))?;
let input = serde_json::json!({
"id": "gid://shopify/CartLine/1"
});
let result = run_example(path.clone(), "target_prepare", input)?;
assert_eq!(
result.output,
serde_json::json!({
"variables": {
"selector": {
"filter": {
"titles": ["gid://shopify/CartLine/1"],
"match": "ANY",
"minimumPrice": "1.5"
}
},
"first": 10,
"tags": ["sale", null]
}
})
);
Ok(())
}

#[test]
fn test_example_with_panic() -> Result<()> {
let path = EXAMPLE_WITH_TARGETS_RESULT
Expand All @@ -80,7 +108,7 @@ fn test_example_with_panic() -> Result<()> {
.unwrap_err()
.to_string();
let expected_err =
"Function runner returned non-zero exit code: exit status: 1, logs: panicked at example_with_targets/src/main.rs:48:5:\nSomething went wrong\nerror while executing at wasm backtrace:";
"Function runner returned non-zero exit code: exit status: 1, logs: panicked at example_with_targets/src/main.rs:57:5:\nSomething went wrong\nerror while executing at wasm backtrace:";
assert!(
err.contains(expected_err),
"Expected error message to contain:\n`{expected_err}`\nbut was:\n`{err}`"
Expand Down
Loading
Loading