#![cfg(test)]
use std::fs;
use std::path::PathBuf;
use tempfile::TempDir;
use super::{handle_check, handle_print_ir};
use crate::cli_types::OutputFormat;
const SCHEMA_WITH_QUERY: &str = r#"
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
type Totals {
total Int
thisMonth Int
}
query loyaltyFeeSummary(userId: String, cutoff: DateTime): Totals
@@sql("""
SELECT
COALESCE(SUM(discount), 0)::bigint AS "total",
COALESCE(SUM(discount) FILTER (WHERE created_at >= $2), 0)::bigint AS "thisMonth"
FROM loyalty_fee_events
WHERE user_id = $1
""")
@allow(auth() != null)
"#;
const SCHEMA_WITH_BAD_PLACEHOLDER: &str = r#"
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
type Totals {
total Int
}
query totals(userId: String): Totals
@@sql("SELECT 1 AS total WHERE a = $2")
@allow(auth() != null)
"#;
fn write_schema(dir: &TempDir, source: &str) -> PathBuf {
let path = dir.path().join("schema.cstack");
fs::write(&path, source).expect("write schema");
path
}
#[test]
fn check_accepts_a_schema_declaring_a_query() {
let dir = TempDir::new().expect("temp dir");
let path = write_schema(&dir, SCHEMA_WITH_QUERY);
handle_check(path, OutputFormat::Human).expect("check should accept a query block");
}
#[test]
fn check_rejects_an_out_of_range_placeholder() {
let dir = TempDir::new().expect("temp dir");
let path = write_schema(&dir, SCHEMA_WITH_BAD_PLACEHOLDER);
let error = handle_check(path, OutputFormat::Human)
.expect_err("check should reject a `$2` with one declared parameter");
let message = error.to_string();
assert!(message.contains("references parameter `$2`"), "{message}");
}
#[test]
fn print_ir_accepts_a_schema_declaring_a_query() {
let dir = TempDir::new().expect("temp dir");
let path = write_schema(&dir, SCHEMA_WITH_QUERY);
handle_print_ir(path.clone()).expect("print-ir should accept a query block");
let schema = cratestack_parser::parse_schema_file(&path).expect("schema should parse");
let query = schema
.queries
.first()
.expect("the query should be present in the IR print-ir renders");
assert_eq!(query.name, "loyaltyFeeSummary");
assert_eq!(query.result_type.name, "Totals");
assert!(
query
.sql()
.expect("query should carry a SQL body")
.contains("FILTER (WHERE created_at >= $2)"),
);
}