Skip to content

Commit

Permalink
add insta snapshot tests
Browse files Browse the repository at this point in the history
  • Loading branch information
BenoitRanque committed Sep 30, 2024
1 parent d0faeaf commit 7e62a8e
Show file tree
Hide file tree
Showing 99 changed files with 6,921 additions and 67 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"
strum = { version = "0.26.3", features = ["derive"] }
tracing = "0.1.40"

[dev-dependencies]
insta = { version = "1.40.0", features = ["yaml", "glob", "json"] }
schemars = "0.8.16"
13 changes: 13 additions & 0 deletions crates/common/tests/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use common::{capabilities::capabilities_response, config_file::ServerConfigFile};
use insta::assert_yaml_snapshot;
use schemars::schema_for;

#[test]
fn test_capabilities() {
assert_yaml_snapshot!("Capabilities", capabilities_response())
}

#[test]
fn test_configuration_schema() {
assert_yaml_snapshot!("Server Configuration File", schema_for!(ServerConfigFile))
}
16 changes: 16 additions & 0 deletions crates/common/tests/snapshots/common__Capabilities.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: crates/common/tests/common.rs
expression: capabilities_response()
---
version: 0.1.6
capabilities:
query:
aggregates: {}
variables: {}
explain: {}
nested_fields: {}
exists: {}
mutation: {}
relationships:
relation_comparisons: {}
order_by_aggregate: {}
137 changes: 137 additions & 0 deletions crates/common/tests/snapshots/common__Server Configuration File.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
source: crates/common/tests/common.rs
expression: schema_for!(ServerConfigFile)
---
$schema: "http://json-schema.org/draft-07/schema#"
title: ServerConfigFile
description: the main configuration file
type: object
required:
- $schema
properties:
$schema:
type: string
tables:
description: "A list of tables available in this database\n\nThe map key is a unique table alias that defaults to defaults to \"<table_schema>_<table_name>\", except for tables in the \"default\" schema where the table name is used This is the name exposed to the engine, and may be configured by users. When the configuration is updated, the table is identified by name and schema, and changes to the alias are preserved."
type: object
additionalProperties:
$ref: "#/definitions/TableConfigFile"
queries:
description: Optionally define custom parameterized queries here Note the names must not match table names
type: object
additionalProperties:
$ref: "#/definitions/ParameterizedQueryConfigFile"
definitions:
TableConfigFile:
type: object
required:
- name
- return_type
- schema
properties:
name:
description: The table name
type: string
schema:
description: The table schema
type: string
comment:
description: Comments are sourced from the database table comment
type:
- string
- "null"
primary_key:
anyOf:
- $ref: "#/definitions/PrimaryKey"
- type: "null"
arguments:
type: object
additionalProperties:
type: string
return_type:
description: "The map key is a column alias identifying the table and may be customized. It defaults to the table name. When the configuration is updated, the column is identified by name, and changes to the alias are preserved."
allOf:
- $ref: "#/definitions/ReturnType"
PrimaryKey:
type: object
required:
- columns
- name
properties:
name:
type: string
columns:
description: The names of columns in this primary key
type: array
items:
type: string
ReturnType:
oneOf:
- description: "A custom return type definition The keys are column names, the values are parsable clichouse datatypes"
type: object
required:
- columns
- kind
properties:
kind:
type: string
enum:
- definition
columns:
type: object
additionalProperties:
type: string
- description: the same as the return type for another table
type: object
required:
- kind
- table_name
properties:
kind:
type: string
enum:
- table_reference
table_name:
description: "the table alias must match a key in `tables`, and the query must return the same type as that table alternatively, the alias may reference another parameterized query which has a return type definition,"
type: string
- description: The same as the return type for another query
type: object
required:
- kind
- query_name
properties:
kind:
type: string
enum:
- query_reference
query_name:
description: "the table alias must match a key in `tables`, and the query must return the same type as that table alternatively, the alias may reference another parameterized query which has a return type definition,"
type: string
ParameterizedQueryConfigFile:
type: object
required:
- exposed_as
- file
- return_type
properties:
exposed_as:
description: Whether this query should be exposed as a procedure (mutating) or collection (non-mutating)
allOf:
- $ref: "#/definitions/ParameterizedQueryExposedAs"
comment:
description: A comment that will be exposed in the schema
type:
- string
- "null"
file:
description: A relative path to a sql file
type: string
return_type:
description: "Either a type definition for the return type for this query, or a reference to another return type: either a table's alias, or another query's alias. If another query, that query must have a return type definition."
allOf:
- $ref: "#/definitions/ReturnType"
ParameterizedQueryExposedAs:
type: string
enum:
- collection
- procedure
42 changes: 0 additions & 42 deletions crates/ndc-clickhouse/tests/capabilities.rs

This file was deleted.

17 changes: 0 additions & 17 deletions crates/ndc-clickhouse/tests/capabilities/capabilities.json

This file was deleted.

115 changes: 107 additions & 8 deletions crates/ndc-clickhouse/tests/query_builder.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,110 @@
use common::config_file::ServerConfigFile;
use ndc_clickhouse::sql::QueryBuilderError;
use common::{config::ServerConfig, config_file::ServerConfigFile, schema::schema_response};
use insta::{assert_snapshot, assert_yaml_snapshot, glob};
use ndc_clickhouse::{
connector::setup::ClickhouseConnectorSetup,
sql::{QueryBuilder, QueryBuilderError},
};
use ndc_sdk::models;
use schemars::schema_for;
use std::error::Error;
use tokio::fs;
use std::{collections::HashMap, error::Error, fs, path::PathBuf};

fn base_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("query_builder")
}

async fn read_mock_configuration(schema_dir: &str) -> ServerConfig {
// set mock values for required env vars, we won't be reading these anyways
let env = HashMap::from_iter(vec![
("CLICKHOUSE_URL".to_owned(), "".to_owned()),
("CLICKHOUSE_USERNAME".to_owned(), "".to_owned()),
("CLICKHOUSE_PASSWORD".to_owned(), "".to_owned()),
]);
let setup = ClickhouseConnectorSetup::new_from_env(env);
let config_dir = base_path().join(schema_dir).join("_config");
setup
.read_server_config(config_dir)
.await
.expect("Should be able to read configuration")
}

fn pretty_print_sql(query: &str) -> String {
use sqlformat::{format, FormatOptions, Indent, QueryParams};
let params = QueryParams::None;
let options = FormatOptions {
indent: Indent::Spaces(2),
uppercase: false,
lines_between_queries: 1,
};

format(query, &params, options)
}

#[tokio::test]
async fn test_sql_generation() {
for schema_dir in ["chinook", "complex_columns", "star_schema"] {
let configuration = read_mock_configuration(schema_dir).await;

glob!(
base_path().join(schema_dir),
"*.request.json",
|file_path| {
let file = fs::read_to_string(file_path).expect("Should read request file");
let request: models::QueryRequest =
serde_json::from_str(&file).expect("File should be valid query request");

let inlined_sql = match QueryBuilder::new(&request, &configuration).build_inlined()
{
Err(err) => {
assert_snapshot!(format!("{schema_dir} Expected Error"), err);
return;
}
Ok(inlined_sql) => pretty_print_sql(&inlined_sql.to_string()),
};

assert_snapshot!(format!("{schema_dir} Inlined SQL"), inlined_sql);

let (parameterized_sql, parameters) = QueryBuilder::new(&request, &configuration)
.build_parameterized()
.expect("Should build parameterized SQL");
let parameterized_sql = pretty_print_sql(&parameterized_sql.to_string());

if parameters.is_empty() {
assert_eq!(
inlined_sql, parameterized_sql,
"If no parameters are present, parameterized sql should match inlined sql"
)
} else {
let printed_parameters =
parameters
.into_iter()
.fold(String::new(), |mut acc, (name, value)| {
acc.reserve(name.len() + value.len() + 2);
acc.push_str(&name);
acc.push('=');
acc.push_str(&value);
acc.push('\n');
acc
});

assert_snapshot!(format!("{schema_dir} Parameterized SQL"), parameterized_sql);
assert_snapshot!(format!("{schema_dir} Parameters"), printed_parameters);
}
}
)
}
}

#[tokio::test]
async fn test_schemas() {
for schema_dir in ["chinook", "complex_columns", "star_schema"] {
let configuration = read_mock_configuration(schema_dir).await;

let schema = schema_response(&configuration);
assert_yaml_snapshot!(format!("{schema_dir} Schema Response"), schema);
}
}

mod test_utils {
use common::{config::ServerConfig, schema::schema_response};
Expand Down Expand Up @@ -253,13 +354,11 @@ async fn update_json_schema() -> Result<(), Box<dyn Error>> {
fs::write(
"./tests/query_builder/request.schema.json",
serde_json::to_string_pretty(&schema_for!(models::QueryRequest))?,
)
.await?;
)?;
fs::write(
"./tests/query_builder/configuration.schema.json",
serde_json::to_string_pretty(&schema_for!(ServerConfigFile))?,
)
.await?;
)?;

Ok(())
}
Expand Down
Loading

0 comments on commit 7e62a8e

Please sign in to comment.