use crate::SourceMap;
use crate::ast;
use crate::tests::utils::parse_executable;
use crate::tests::utils::parse_schema;
fn resolve(source: &str, byte_offset: u32) -> (usize, usize) {
let sm = SourceMap::new_with_source(source, None);
let pos = sm.resolve_offset(byte_offset)
.expect("byte offset should be resolvable");
(pos.line(), pos.col_utf8())
}
#[test]
fn position_query_keyword() {
let source = "query { field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
assert_eq!(doc.definitions.len(), 1);
assert_eq!(doc.span.start as usize, 0);
assert_eq!(doc.span.end as usize, source.len());
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.operation_kind, ast::OperationKind::Query);
assert!(!op.shorthand);
assert_eq!(resolve(source, doc.span.start).0, 0);
assert_eq!(resolve(source, op.span.start).1, 0);
assert_eq!(op.span.start as usize, 0);
assert_eq!(resolve(source, op.span.end).0, 0);
assert_eq!(resolve(source, op.span.end).1, 15);
assert_eq!(op.span.end as usize, 15);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_mutation_keyword() {
let source = "mutation { doThing }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
assert_eq!(doc.definitions.len(), 1);
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.operation_kind, ast::OperationKind::Mutation);
assert!(!op.shorthand);
assert_eq!(resolve(source, op.span.start).0, 0);
assert_eq!(resolve(source, op.span.start).1, 0);
assert_eq!(op.span.start as usize, 0);
assert_eq!(resolve(source, op.span.end).0, 0);
assert_eq!(resolve(source, op.span.end).1, 20);
assert_eq!(op.span.end as usize, 20);
} else {
panic!("Expected a Mutation definition");
}
}
#[test]
fn position_subscription_keyword() {
let source = "subscription { onEvent }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
assert_eq!(doc.definitions.len(), 1);
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.operation_kind, ast::OperationKind::Subscription);
assert!(!op.shorthand);
assert_eq!(resolve(source, op.span.start).0, 0);
assert_eq!(resolve(source, op.span.start).1, 0);
assert_eq!(op.span.start as usize, 0);
assert_eq!(resolve(source, op.span.end).0, 0);
assert_eq!(resolve(source, op.span.end).1, 24);
assert_eq!(op.span.end as usize, 24);
} else {
panic!("Expected a Subscription definition");
}
}
#[test]
fn position_field_simple() {
let source = "query { myField }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.selection_set.selections.len(), 1);
if let ast::Selection::Field(field) = &op.selection_set.selections[0] {
assert_eq!(resolve(source, field.span.start).0, 0);
assert_eq!(resolve(source, field.span.start).1, 8);
assert_eq!(field.span.start as usize, 8);
assert_eq!(resolve(source, field.name.span.start).0, 0);
assert_eq!(resolve(source, field.name.span.start).1, 8);
assert_eq!(field.name.span.start as usize, 8);
assert_eq!(resolve(source, field.name.span.end).0, 0);
assert_eq!(resolve(source, field.name.span.end).1, 15);
assert_eq!(field.name.span.end as usize, 15);
} else {
panic!("Expected a Field selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_field_with_alias() {
let source = "query { alias: realField }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::Field(field) = &op.selection_set.selections[0] {
assert_eq!(resolve(source, field.span.start).0, 0);
assert_eq!(resolve(source, field.span.start).1, 8);
assert_eq!(field.span.start as usize, 8);
assert_eq!(
field.alias.as_ref().map(|a| &*a.value),
Some("alias"),
);
assert_eq!(field.name.value, "realField");
let alias = field.alias.as_ref().unwrap();
assert_eq!(resolve(source, alias.span.start).1, 8);
assert_eq!(alias.span.start as usize, 8);
assert_eq!(resolve(source, alias.span.end).1, 13);
assert_eq!(alias.span.end as usize, 13);
assert_eq!(resolve(source, field.name.span.start).1, 15);
assert_eq!(field.name.span.start as usize, 15);
assert_eq!(resolve(source, field.name.span.end).1, 24);
assert_eq!(field.name.span.end as usize, 24);
} else {
panic!("Expected a Field selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_directive_at_symbol() {
let source = "query @skip(if: true) { field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.directives.len(), 1);
let directive = &op.directives[0];
assert_eq!(resolve(source, directive.span.start).0, 0);
assert_eq!(resolve(source, directive.span.start).1, 6);
assert_eq!(directive.span.start as usize, 6);
assert_eq!(directive.name.value, "skip");
assert_eq!(resolve(source, directive.name.span.start).1, 7);
assert_eq!(directive.name.span.start as usize, 7);
assert_eq!(resolve(source, directive.name.span.end).1, 11);
assert_eq!(directive.name.span.end as usize, 11);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_variable_dollar() {
let source = "query ($id: ID!) { field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.variable_definitions.len(), 1);
let var_def = &op.variable_definitions[0];
assert_eq!(resolve(source, var_def.span.start).0, 0);
assert_eq!(resolve(source, var_def.span.start).1, 7);
assert_eq!(var_def.span.start as usize, 7);
assert_eq!(var_def.variable.value, "id");
assert_eq!(resolve(source, var_def.variable.span.start).1, 8);
assert_eq!(var_def.variable.span.start as usize, 8);
assert_eq!(resolve(source, var_def.variable.span.end).1, 10);
assert_eq!(var_def.variable.span.end as usize, 10);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_fragment_definition() {
let source = "fragment MyFragment on User { name }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::FragmentDefinition(frag) = &doc.definitions[0] {
assert_eq!(resolve(source, frag.span.start).0, 0);
assert_eq!(resolve(source, frag.span.start).1, 0);
assert_eq!(frag.span.start as usize, 0);
assert_eq!(frag.name.value, "MyFragment");
assert_eq!(resolve(source, frag.name.span.start).1, 9);
assert_eq!(frag.name.span.start as usize, 9);
assert_eq!(resolve(source, frag.name.span.end).1, 19);
assert_eq!(frag.name.span.end as usize, 19);
assert_eq!(resolve(source, frag.type_condition.span.start).1, 20);
assert_eq!(frag.type_condition.span.start as usize, 20);
assert_eq!(resolve(source, frag.type_condition.span.end).1, 27);
assert_eq!(frag.type_condition.span.end as usize, 27);
assert_eq!(
resolve(source, frag.type_condition.named_type.span.start).1, 23,
);
assert_eq!(
resolve(source, frag.type_condition.named_type.span.end).1, 27,
);
} else {
panic!("Expected a Fragment definition");
}
}
#[test]
fn position_fragment_spread() {
let source = "query { ...MyFragment }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::FragmentSpread(spread) =
&op.selection_set.selections[0] {
assert_eq!(resolve(source, spread.span.start).0, 0);
assert_eq!(resolve(source, spread.span.start).1, 8);
assert_eq!(spread.span.start as usize, 8);
assert_eq!(spread.name.value, "MyFragment");
assert_eq!(resolve(source, spread.name.span.start).1, 11);
assert_eq!(spread.name.span.start as usize, 11);
assert_eq!(resolve(source, spread.name.span.end).1, 21);
assert_eq!(spread.name.span.end as usize, 21);
} else {
panic!("Expected a FragmentSpread selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_inline_fragment() {
let source = "query { ... on User { name } }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::InlineFragment(inline) =
&op.selection_set.selections[0] {
assert_eq!(resolve(source, inline.span.start).0, 0);
assert_eq!(resolve(source, inline.span.start).1, 8);
assert_eq!(inline.span.start as usize, 8);
let tc = inline.type_condition.as_ref().unwrap();
assert_eq!(resolve(source, tc.span.start).1, 12);
assert_eq!(tc.span.start as usize, 12);
assert_eq!(resolve(source, tc.span.end).1, 19);
assert_eq!(tc.span.end as usize, 19);
} else {
panic!("Expected an InlineFragment selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_inline_fragment_no_type() {
let source = "query { ... { name } }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::InlineFragment(inline) =
&op.selection_set.selections[0] {
assert_eq!(resolve(source, inline.span.start).0, 0);
assert_eq!(resolve(source, inline.span.start).1, 8);
assert!(inline.type_condition.is_none());
} else {
panic!("Expected an InlineFragment selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_selection_set_span() {
let source = "query { field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(resolve(source, op.selection_set.span.start).0, 0);
assert_eq!(resolve(source, op.selection_set.span.start).1, 6);
assert_eq!(op.selection_set.span.start as usize, 6);
assert_eq!(resolve(source, op.selection_set.span.end).0, 0);
assert_eq!(resolve(source, op.selection_set.span.end).1, 15);
assert_eq!(op.selection_set.span.end as usize, 15);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_selection_set_multiline() {
let source = "query {\n field\n}";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(resolve(source, op.selection_set.span.start).0, 0);
assert_eq!(resolve(source, op.selection_set.span.start).1, 6);
assert_eq!(resolve(source, op.selection_set.span.end).0, 2);
assert_eq!(resolve(source, op.selection_set.span.end).1, 1);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_empty_selection_set_simple_field() {
let source = "query { myField }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::Field(field) = &op.selection_set.selections[0] {
assert!(field.selection_set.is_none());
} else {
panic!("Expected a Field selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_empty_selection_set_field_with_args() {
let source = "query { myField(id: 123) }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::Field(field) = &op.selection_set.selections[0] {
assert!(!field.arguments.is_empty());
assert!(field.selection_set.is_none());
} else {
panic!("Expected a Field selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_empty_selection_set_field_with_directive() {
let source = "query { myField @skip(if: true) }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::Field(field) = &op.selection_set.selections[0] {
assert!(!field.directives.is_empty());
assert!(field.selection_set.is_none());
} else {
panic!("Expected a Field selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_empty_selection_set_aliased_field() {
let source = "query { alias: realField }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::Field(field) = &op.selection_set.selections[0] {
assert_eq!(
field.alias.as_ref().map(|a| &*a.value),
Some("alias"),
);
assert!(field.selection_set.is_none());
} else {
panic!("Expected a Field selection");
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_schema_definition() {
let source = "schema { query: Query }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::SchemaDefinition(schema_def) = &doc.definitions[0] {
assert_eq!(resolve(source, schema_def.span.start).0, 0);
assert_eq!(resolve(source, schema_def.span.start).1, 0);
assert_eq!(schema_def.span.start as usize, 0);
assert_eq!(resolve(source, schema_def.span.end).0, 0);
assert_eq!(resolve(source, schema_def.span.end).1, 23);
assert_eq!(schema_def.span.end as usize, 23);
} else {
panic!("Expected a SchemaDefinition");
}
}
#[test]
fn position_scalar_type_definition() {
let source = "scalar DateTime";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::Scalar(scalar),
) = &doc.definitions[0] {
assert_eq!(resolve(source, scalar.span.start).0, 0);
assert_eq!(resolve(source, scalar.span.start).1, 0);
assert_eq!(scalar.name.value, "DateTime");
} else {
panic!("Expected a Scalar type definition");
}
}
#[test]
fn position_object_type_definition() {
let source = "type User { id: ID! }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::Object(obj),
) = &doc.definitions[0] {
assert_eq!(resolve(source, obj.span.start).0, 0);
assert_eq!(resolve(source, obj.span.start).1, 0);
assert_eq!(obj.span.start as usize, 0);
assert_eq!(obj.name.value, "User");
assert_eq!(resolve(source, obj.name.span.start).1, 5);
assert_eq!(obj.name.span.start as usize, 5);
assert_eq!(resolve(source, obj.name.span.end).1, 9);
assert_eq!(obj.name.span.end as usize, 9);
} else {
panic!("Expected an Object type definition");
}
}
#[test]
fn position_interface_type_definition() {
let source = "interface Node { id: ID! }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::Interface(iface),
) = &doc.definitions[0] {
assert_eq!(resolve(source, iface.span.start).0, 0);
assert_eq!(resolve(source, iface.span.start).1, 0);
assert_eq!(iface.name.value, "Node");
} else {
panic!("Expected an Interface type definition");
}
}
#[test]
fn position_union_type_definition() {
let source = "union SearchResult = User | Post";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::Union(union_type),
) = &doc.definitions[0] {
assert_eq!(resolve(source, union_type.span.start).0, 0);
assert_eq!(resolve(source, union_type.span.start).1, 0);
assert_eq!(union_type.name.value, "SearchResult");
} else {
panic!("Expected a Union type definition");
}
}
#[test]
fn position_enum_type_definition() {
let source = "enum Status { ACTIVE INACTIVE }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::Enum(enum_type),
) = &doc.definitions[0] {
assert_eq!(resolve(source, enum_type.span.start).0, 0);
assert_eq!(resolve(source, enum_type.span.start).1, 0);
assert_eq!(enum_type.name.value, "Status");
} else {
panic!("Expected an Enum type definition");
}
}
#[test]
fn position_input_object_type_definition() {
let source = "input CreateUserInput { name: String! }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::InputObject(input_obj),
) = &doc.definitions[0] {
assert_eq!(resolve(source, input_obj.span.start).0, 0);
assert_eq!(resolve(source, input_obj.span.start).1, 0);
assert_eq!(input_obj.name.value, "CreateUserInput");
} else {
panic!("Expected an InputObject type definition");
}
}
#[test]
fn position_directive_definition() {
let source = "directive @myDirective on FIELD";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::DirectiveDefinition(dir_def) = &doc.definitions[0] {
assert_eq!(resolve(source, dir_def.span.start).0, 0);
assert_eq!(resolve(source, dir_def.span.start).1, 0);
assert_eq!(dir_def.name.value, "myDirective");
} else {
panic!("Expected a DirectiveDefinition");
}
}
#[test]
fn position_field_definition() {
let source = "type User { name: String }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::Object(obj),
) = &doc.definitions[0] {
assert_eq!(obj.fields.len(), 1);
let field = &obj.fields[0];
assert_eq!(resolve(source, field.span.start).0, 0);
assert_eq!(resolve(source, field.span.start).1, 12);
assert_eq!(field.span.start as usize, 12);
assert_eq!(field.name.value, "name");
assert_eq!(resolve(source, field.name.span.start).1, 12);
assert_eq!(field.name.span.start as usize, 12);
assert_eq!(resolve(source, field.name.span.end).1, 16);
assert_eq!(field.name.span.end as usize, 16);
if let ast::TypeAnnotation::Named(named) = &field.field_type {
assert_eq!(resolve(source, named.span.start).1, 18);
assert_eq!(named.span.start as usize, 18);
assert_eq!(resolve(source, named.span.end).1, 24);
assert_eq!(named.span.end as usize, 24);
} else {
panic!("Expected a Named type annotation");
}
} else {
panic!("Expected an Object type definition");
}
}
#[test]
fn position_input_value_definition() {
let source = "input CreateUserInput { name: String! }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::InputObject(input_obj),
) = &doc.definitions[0] {
assert_eq!(input_obj.fields.len(), 1);
let field = &input_obj.fields[0];
assert_eq!(resolve(source, field.span.start).0, 0);
assert_eq!(resolve(source, field.span.start).1, 24);
assert_eq!(field.span.start as usize, 24);
assert_eq!(field.name.value, "name");
assert_eq!(resolve(source, field.name.span.start).1, 24);
assert_eq!(field.name.span.start as usize, 24);
assert_eq!(resolve(source, field.name.span.end).1, 28);
assert_eq!(field.name.span.end as usize, 28);
} else {
panic!("Expected an InputObject type definition");
}
}
#[test]
fn position_enum_value_definition() {
let source = "enum Status { ACTIVE }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeDefinition(
ast::TypeDefinition::Enum(enum_type),
) = &doc.definitions[0] {
assert_eq!(enum_type.values.len(), 1);
let value = &enum_type.values[0];
assert_eq!(resolve(source, value.span.start).0, 0);
assert_eq!(resolve(source, value.span.start).1, 14);
assert_eq!(value.span.start as usize, 14);
assert_eq!(value.name.value, "ACTIVE");
assert_eq!(resolve(source, value.name.span.start).1, 14);
assert_eq!(value.name.span.start as usize, 14);
assert_eq!(resolve(source, value.name.span.end).1, 20);
assert_eq!(value.name.span.end as usize, 20);
} else {
panic!("Expected an Enum type definition");
}
}
#[test]
fn position_scalar_type_extension() {
let source = "extend scalar DateTime @deprecated";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeExtension(
ast::TypeExtension::Scalar(ext),
) = &doc.definitions[0] {
assert_eq!(resolve(source, ext.span.start).0, 0);
assert_eq!(resolve(source, ext.span.start).1, 0);
assert_eq!(ext.name.value, "DateTime");
} else {
panic!("Expected a Scalar type extension");
}
}
#[test]
fn position_object_type_extension() {
let source = "extend type User { email: String }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeExtension(
ast::TypeExtension::Object(ext),
) = &doc.definitions[0] {
assert_eq!(resolve(source, ext.span.start).0, 0);
assert_eq!(resolve(source, ext.span.start).1, 0);
assert_eq!(ext.name.value, "User");
} else {
panic!("Expected an Object type extension");
}
}
#[test]
fn position_interface_type_extension() {
let source = "extend interface Node { createdAt: DateTime }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeExtension(
ast::TypeExtension::Interface(ext),
) = &doc.definitions[0] {
assert_eq!(resolve(source, ext.span.start).0, 0);
assert_eq!(resolve(source, ext.span.start).1, 0);
assert_eq!(ext.name.value, "Node");
} else {
panic!("Expected an Interface type extension");
}
}
#[test]
fn position_union_type_extension() {
let source = "extend union SearchResult = Comment";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeExtension(
ast::TypeExtension::Union(ext),
) = &doc.definitions[0] {
assert_eq!(resolve(source, ext.span.start).0, 0);
assert_eq!(resolve(source, ext.span.start).1, 0);
assert_eq!(ext.name.value, "SearchResult");
} else {
panic!("Expected a Union type extension");
}
}
#[test]
fn position_enum_type_extension() {
let source = "extend enum Status { PENDING }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeExtension(
ast::TypeExtension::Enum(ext),
) = &doc.definitions[0] {
assert_eq!(resolve(source, ext.span.start).0, 0);
assert_eq!(resolve(source, ext.span.start).1, 0);
assert_eq!(ext.name.value, "Status");
} else {
panic!("Expected an Enum type extension");
}
}
#[test]
fn position_input_object_type_extension() {
let source = "extend input CreateUserInput { email: String }";
let result = parse_schema(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::TypeExtension(
ast::TypeExtension::InputObject(ext),
) = &doc.definitions[0] {
assert_eq!(resolve(source, ext.span.start).0, 0);
assert_eq!(resolve(source, ext.span.start).1, 0);
assert_eq!(ext.name.value, "CreateUserInput");
} else {
panic!("Expected an InputObject type extension");
}
}
#[test]
fn position_shorthand_query() {
let source = "{ field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert!(op.shorthand);
assert_eq!(resolve(source, op.span.start).0, 0);
assert_eq!(resolve(source, op.span.start).1, 0);
assert_eq!(op.span.start as usize, 0);
assert_eq!(resolve(source, op.span.end).0, 0);
assert_eq!(resolve(source, op.span.end).1, 9);
assert_eq!(op.span.end as usize, 9);
assert_eq!(resolve(source, op.span.start).0, 0);
assert_eq!(resolve(source, op.selection_set.span.start).1, 0);
assert_eq!(op.selection_set.span.start as usize, 0);
assert_eq!(resolve(source, op.selection_set.span.end).0, 0);
assert_eq!(resolve(source, op.selection_set.span.end).1, 9);
assert_eq!(op.selection_set.span.end as usize, 9);
} else {
panic!("Expected an OperationDefinition");
}
}
#[test]
fn position_with_leading_whitespace() {
let source = "\n\nquery { field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(resolve(source, op.span.start).0, 2);
assert_eq!(resolve(source, op.span.start).1, 0);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_with_leading_comments() {
let source = "# This is a comment\nquery { field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(resolve(source, op.span.start).0, 1);
assert_eq!(resolve(source, op.span.start).1, 0);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_multiline_selections() {
let source = "query {\n field1\n field2\n}";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.selection_set.selections.len(), 2);
if let ast::Selection::Field(field1) =
&op.selection_set.selections[0] {
assert_eq!(resolve(source, field1.span.start).0, 1);
assert_eq!(resolve(source, field1.span.start).1, 2);
}
if let ast::Selection::Field(field2) =
&op.selection_set.selections[1] {
assert_eq!(resolve(source, field2.span.start).0, 2);
assert_eq!(resolve(source, field2.span.start).1, 2);
}
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_deeply_nested() {
let source = "query { a { b { c { d } } } }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
if let ast::Selection::Field(field_a) =
&op.selection_set.selections[0] {
assert_eq!(resolve(source, field_a.span.start).0, 0);
assert_eq!(resolve(source, field_a.span.start).1, 8);
assert_eq!(field_a.span.start as usize, 8);
assert_eq!(field_a.name.value, "a");
let ss_a = field_a.selection_set.as_ref().unwrap();
assert_eq!(resolve(source, ss_a.span.start).1, 10);
assert_eq!(ss_a.span.start as usize, 10);
assert_eq!(resolve(source, ss_a.span.end).1, 27);
assert_eq!(ss_a.span.end as usize, 27);
let ss_a = field_a.selection_set.as_ref().unwrap();
if let ast::Selection::Field(field_b) = &ss_a.selections[0] {
assert_eq!(resolve(source, ss_a.span.start).0, 0);
assert_eq!(resolve(source, field_b.span.start).1, 12);
assert_eq!(field_b.name.value, "b");
let ss_b = field_b.selection_set.as_ref().unwrap();
if let ast::Selection::Field(field_c) = &ss_b.selections[0] {
assert_eq!(resolve(source, field_c.span.start).0, 0);
assert_eq!(resolve(source, field_c.span.start).1, 16);
assert_eq!(field_c.name.value, "c");
let ss_c = field_c.selection_set.as_ref().unwrap();
if let ast::Selection::Field(field_d) =
&ss_c.selections[0] {
assert_eq!(resolve(source, field_d.span.start).0, 0);
assert_eq!(
resolve(source, field_d.span.start).1, 20,
);
assert_eq!(field_d.name.value, "d");
}
}
}
}
}
}
#[test]
fn position_long_lines() {
let padding = " ".repeat(95);
let source = format!("query {{{padding}field }}");
let result = parse_executable(&source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0]
&& let ast::Selection::Field(field) =
&op.selection_set.selections[0] {
assert_eq!(resolve(&source, field.span.start).0, 0);
assert_eq!(resolve(&source, field.span.start).1, 102);
}
}
#[test]
fn position_multiple_operations() {
let source = "query A { a }\nmutation B { b }\nsubscription C { c }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
assert_eq!(doc.definitions.len(), 3);
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.operation_kind, ast::OperationKind::Query);
assert_eq!(resolve(source, op.span.start).0, 0);
assert_eq!(resolve(source, op.span.start).1, 0);
}
if let ast::Definition::OperationDefinition(op) = &doc.definitions[1] {
assert_eq!(op.operation_kind, ast::OperationKind::Mutation);
assert_eq!(resolve(source, op.span.start).0, 1);
assert_eq!(resolve(source, op.span.start).1, 0);
}
if let ast::Definition::OperationDefinition(op) = &doc.definitions[2] {
assert_eq!(op.operation_kind, ast::OperationKind::Subscription);
assert_eq!(resolve(source, op.span.start).0, 2);
assert_eq!(resolve(source, op.span.start).1, 0);
}
}
#[test]
fn position_after_unicode_comment() {
let source = "# Hello world! \u{1F389}\nquery { field }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(resolve(source, op.span.start).0, 1);
assert_eq!(resolve(source, op.span.start).1, 0);
} else {
panic!("Expected a Query definition");
}
}
#[test]
fn position_unicode_in_string() {
let source = "query { field(arg: \"\u{1F389}\") other }";
let result = parse_executable(source);
assert!(!result.has_errors());
let (doc, _) = result.into_valid().unwrap();
if let ast::Definition::OperationDefinition(op) = &doc.definitions[0] {
assert_eq!(op.selection_set.selections.len(), 2);
if let ast::Selection::Field(other_field) =
&op.selection_set.selections[1] {
assert_eq!(other_field.name.value, "other");
assert_eq!(resolve(source, other_field.span.start).0, 0);
assert_eq!(resolve(source, other_field.span.start).1, 24);
}
}
}