|
| 1 | +//! An example using the GitHub API |
| 2 | +//! |
| 3 | +//! Note that this example pulls a schema from the `github_schema` crate. |
| 4 | +//! This is because the github schema is massive and compiling the output |
| 5 | +//! of `use_schema` is quite slow. Moving this into a separate crate |
| 6 | +//! means we won't have to recompile it every time this file changes |
| 7 | +//! and we'll only need to do so once per full build of cynic. |
| 8 | +//! |
| 9 | +//! You may want to do similar if you're also working with cynic & the |
| 10 | +//! github API. |
| 11 | +//! |
| 12 | +//! This example requires the `reqwest-blocking` feature to be active. |
| 13 | +
|
| 14 | +fn main() { |
| 15 | + let result = run_query(); |
| 16 | + println!("{:?}", result); |
| 17 | +} |
| 18 | + |
| 19 | +fn run_query() -> cynic::GraphQlResponse<PullRequestTitles> { |
| 20 | + use cynic::http::ReqwestBlockingExt; |
| 21 | + |
| 22 | + let query = build_query(); |
| 23 | + |
| 24 | + let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env var must be set"); |
| 25 | + |
| 26 | + reqwest::blocking::Client::new() |
| 27 | + .post("https://api.github.com/graphql") |
| 28 | + .header("Authorization", format!("Bearer {}", token)) |
| 29 | + .header("User-Agent", "obmarg") |
| 30 | + .run_graphql(query) |
| 31 | + .unwrap() |
| 32 | +} |
| 33 | + |
| 34 | +fn build_query() -> cynic::Operation<PullRequestTitles, PullRequestTitlesArguments> { |
| 35 | + use cynic::QueryBuilder; |
| 36 | + |
| 37 | + PullRequestTitles::build(PullRequestTitlesArguments { |
| 38 | + pr_order: IssueOrder { |
| 39 | + direction: OrderDirection::Asc, |
| 40 | + field: IssueOrderField::CreatedAt, |
| 41 | + }, |
| 42 | + }) |
| 43 | +} |
| 44 | + |
| 45 | +use github_schema as schema; |
| 46 | + |
| 47 | +pub type DateTime = chrono::DateTime<chrono::Utc>; |
| 48 | + |
| 49 | +#[derive(cynic::QueryVariables, Debug)] |
| 50 | +pub struct PullRequestTitlesArguments { |
| 51 | + pub pr_order: IssueOrder, |
| 52 | +} |
| 53 | + |
| 54 | +#[derive(cynic::InputObject, Clone, Debug)] |
| 55 | +#[cynic(schema = "github", rename_all = "camelCase")] |
| 56 | +pub struct IssueOrder { |
| 57 | + pub direction: OrderDirection, |
| 58 | + pub field: IssueOrderField, |
| 59 | +} |
| 60 | + |
| 61 | +#[derive(cynic::Enum, Clone, Copy, Debug)] |
| 62 | +#[cynic(schema = "github", rename_all = "SCREAMING_SNAKE_CASE")] |
| 63 | +pub enum OrderDirection { |
| 64 | + Asc, |
| 65 | + Desc, |
| 66 | +} |
| 67 | + |
| 68 | +#[derive(cynic::Enum, Clone, Copy, Debug)] |
| 69 | +#[cynic(schema = "github", rename_all = "SCREAMING_SNAKE_CASE")] |
| 70 | +pub enum IssueOrderField { |
| 71 | + Comments, |
| 72 | + CreatedAt, |
| 73 | + UpdatedAt, |
| 74 | +} |
| 75 | + |
| 76 | +#[derive(cynic::QueryFragment, Debug)] |
| 77 | +#[cynic( |
| 78 | + graphql_type = "Query", |
| 79 | + schema = "github", |
| 80 | + variables = "PullRequestTitlesArguments" |
| 81 | +)] |
| 82 | +pub struct PullRequestTitles { |
| 83 | + #[arguments(name = "cynic".to_string(), owner = "obmarg".to_string())] |
| 84 | + pub repository: Option<Repository>, |
| 85 | +} |
| 86 | + |
| 87 | +#[derive(cynic::QueryFragment, Debug)] |
| 88 | +#[cynic(schema = "github", variables = "PullRequestTitlesArguments")] |
| 89 | +pub struct Repository { |
| 90 | + #[arguments(orderBy: $pr_order, first: 10)] |
| 91 | + pub pull_requests: PullRequestConnection, |
| 92 | +} |
| 93 | + |
| 94 | +#[derive(cynic::QueryFragment, Debug)] |
| 95 | +#[cynic(schema = "github")] |
| 96 | +pub struct PullRequestConnection { |
| 97 | + #[cynic(flatten)] |
| 98 | + pub nodes: Vec<PullRequest>, |
| 99 | +} |
| 100 | + |
| 101 | +#[derive(cynic::QueryFragment, Debug)] |
| 102 | +#[cynic(schema = "github")] |
| 103 | +pub struct PullRequest { |
| 104 | + pub title: String, |
| 105 | + pub created_at: DateTime, |
| 106 | +} |
| 107 | + |
| 108 | +#[cfg(test)] |
| 109 | +mod test { |
| 110 | + use super::*; |
| 111 | + |
| 112 | + #[test] |
| 113 | + fn snapshot_test_query() { |
| 114 | + // Running a snapshot test of the query building functionality as that gives us |
| 115 | + // a place to copy and paste the actual GQL we're using for running elsewhere, |
| 116 | + // and also helps ensure we don't change queries by mistake |
| 117 | + |
| 118 | + let query = build_query(); |
| 119 | + |
| 120 | + insta::assert_snapshot!(query.query); |
| 121 | + } |
| 122 | + |
| 123 | + #[test] |
| 124 | + #[ignore] |
| 125 | + fn test_running_query() { |
| 126 | + let result = run_query(); |
| 127 | + if result.errors.is_some() { |
| 128 | + assert_eq!(result.errors.unwrap().len(), 0); |
| 129 | + } |
| 130 | + assert_eq!( |
| 131 | + result |
| 132 | + .data |
| 133 | + .as_ref() |
| 134 | + .unwrap() |
| 135 | + .repository |
| 136 | + .as_ref() |
| 137 | + .unwrap() |
| 138 | + .pull_requests |
| 139 | + .nodes |
| 140 | + .len(), |
| 141 | + 10 |
| 142 | + ); |
| 143 | + insta::assert_debug_snapshot!(result.data); |
| 144 | + } |
| 145 | +} |
0 commit comments