Skip to content

Commit

Permalink
modifying directive to allow for client fields
Browse files Browse the repository at this point in the history
  • Loading branch information
stewartavery committed Sep 9, 2022
1 parent 913d556 commit a47df41
Show file tree
Hide file tree
Showing 17 changed files with 243 additions and 17 deletions.
4 changes: 4 additions & 0 deletions compiler/crates/common/src/feature_flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ pub struct FeatureFlags {
/// Enable support for the experimental `@alias` directive on fragment spreads.
#[serde(default)]
pub enable_fragment_aliases: FeatureFlag,

// Enables @relay_test_operation support for client data.
#[serde(default)]
pub enable_mock_client_data_metadata: FeatureFlag,
}

#[derive(Debug, Deserialize, Clone, Serialize)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
enable_client_edges: FeatureFlag::Enabled,
skip_printing_nulls: FeatureFlag::Disabled,
enable_fragment_aliases: FeatureFlag::Enabled,
enable_mock_client_data_metadata: FeatureFlag::Disabled,
};

let default_project_config = ProjectConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
enable_client_edges: FeatureFlag::Enabled,
skip_printing_nulls: FeatureFlag::Disabled,
enable_fragment_aliases: FeatureFlag::Enabled,
enable_mock_client_data_metadata: FeatureFlag::Disabled,
};

let project_config = ProjectConfig {
Expand Down
8 changes: 7 additions & 1 deletion compiler/crates/relay-transforms/src/apply_transforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,13 @@ fn apply_normalization_transforms(
}

program = log_event.time("generate_test_operation_metadata", || {
generate_test_operation_metadata(&program, &project_config.test_path_regex)
generate_test_operation_metadata(
&program,
&project_config.test_path_regex,
&project_config
.feature_flags
.enable_mock_client_data_metadata,
)
})?;
if let Some(print_stats) = maybe_print_stats {
print_stats("generate_test_operation_metadata", &program);
Expand Down
35 changes: 25 additions & 10 deletions compiler/crates/relay-transforms/src/test_operation_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use common::ArgumentName;
use common::Diagnostic;
use common::DiagnosticsResult;
use common::DirectiveName;
use common::FeatureFlag;
use common::NamedItem;
use common::WithLocation;
use graphql_ir::ConstantArgument;
Expand Down Expand Up @@ -44,6 +45,7 @@ lazy_static! {
static ref NULLABLE_KEY: StringKey = "nullable".intern();
static ref PLURAL_KEY: StringKey = "plural".intern();
static ref TYPE_KEY: StringKey = "type".intern();
static ref MOCK_CLIENT_DATA: ArgumentName = ArgumentName("mock_client_data".intern());
}

/// Transforms the @relay_test_operation directive to @__metadata thats printed
Expand All @@ -53,8 +55,13 @@ lazy_static! {
pub fn generate_test_operation_metadata(
program: &Program,
test_path_regex: &Option<Regex>,
enable_mock_client_data_metadata_flag: &FeatureFlag,
) -> DiagnosticsResult<Program> {
let mut transformer = GenerateTestOperationMetadata::new(program, test_path_regex);
let mut transformer = GenerateTestOperationMetadata::new(
program,
test_path_regex,
enable_mock_client_data_metadata_flag,
);
let next_program = transformer
.transform_program(program)
.replace_or_else(|| program.clone());
Expand All @@ -66,23 +73,29 @@ pub fn generate_test_operation_metadata(
}
}

struct GenerateTestOperationMetadata<'a> {
program: &'a Program,
test_path_regex: &'a Option<Regex>,
struct GenerateTestOperationMetadata<'program, 'flag> {
program: &'program Program,
test_path_regex: &'program Option<Regex>,
errors: Vec<Diagnostic>,
enable_mock_client_data_metadata_flag: &'flag FeatureFlag,
}

impl<'a> GenerateTestOperationMetadata<'a> {
fn new(program: &'a Program, test_path_regex: &'a Option<Regex>) -> Self {
impl<'program, 'flag> GenerateTestOperationMetadata<'program, 'flag> {
fn new(
program: &'program Program,
test_path_regex: &'program Option<Regex>,
enable_mock_client_data_metadata_flag: &'flag FeatureFlag,
) -> Self {
GenerateTestOperationMetadata {
program,
test_path_regex,
errors: Vec::new(),
enable_mock_client_data_metadata_flag: &enable_mock_client_data_metadata_flag,
}
}
}

impl<'a> Transformer for GenerateTestOperationMetadata<'a> {
impl<'program, 'flag> Transformer for GenerateTestOperationMetadata<'program, 'flag> {
const NAME: &'static str = "GenerateTestOperationMetadata";
const VISIT_ARGUMENTS: bool = false;
const VISIT_DIRECTIVES: bool = false;
Expand Down Expand Up @@ -115,6 +128,8 @@ impl<'a> Transformer for GenerateTestOperationMetadata<'a> {
ConstantValue::Object(From::from(RelayTestOperationMetadata::new(
self.program,
&operation.selections,
self.enable_mock_client_data_metadata_flag
.is_fully_enabled(),
))),
));
} else {
Expand Down Expand Up @@ -210,7 +225,7 @@ pub struct RelayTestOperationMetadata {
}

impl RelayTestOperationMetadata {
pub fn new(program: &Program, selections: &[Selection]) -> Self {
pub fn new(program: &Program, selections: &[Selection], mock_client_data: bool) -> Self {
let schema = program.schema.as_ref();
let mut selection_type_info: IndexMap<StringKey, RelayTestOperationSelectionTypeInfo> =
Default::default();
Expand All @@ -223,7 +238,7 @@ impl RelayTestOperationMetadata {
match selection {
Selection::ScalarField(scalar_field) => {
let field = schema.field(scalar_field.definition.item);
if !field.is_extension {
if !field.is_extension || mock_client_data {
let alias_or_name = scalar_field.alias_or_name(schema);
let next_path = next_path(path, alias_or_name);
selection_type_info.insert(
Expand All @@ -234,7 +249,7 @@ impl RelayTestOperationMetadata {
}
Selection::LinkedField(linked_field) => {
let field = schema.field(linked_field.definition.item);
if !field.is_extension {
if !field.is_extension || mock_client_data {
let alias_or_name = linked_field.alias_or_name(schema);
let next_path = next_path(path, alias_or_name);
selection_type_info.insert(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ query ProdQuery @relay_test_operation {
id
}
}
# %extensions%
==================================== ERROR ====================================
✖︎ The `@relay_test_operation` directive is only allowed within test files because it creates larger generated files we don't want to include in production. File does not match test regex: ^test

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ query ProdQuery @relay_test_operation {
id
}
}
# %extensions%
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
==================================== INPUT ====================================
query ClientFieldsQuery @relay_test_operation {
node(id: "test-id") {
id
... on User {
name
client_info {
name
description
}
}
}
}

# %extensions%

extend type User {
client_info: ClientInfo
}

type ClientInfo {
name: String
description: String
}
==================================== OUTPUT ===================================
query ClientFieldsQuery @__metadata(relayTestingSelectionTypeInfo: {node: {enumValues: null, nullable: true, plural: false, type: "Node"}, node.id: {enumValues: null, nullable: false, plural: false, type: "ID"}, node.name: {enumValues: null, nullable: true, plural: false, type: "String"}}) {
node(id: "test-id") {
id
... on User {
name
client_info {
name
description
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
query ClientFieldsQuery @relay_test_operation {
node(id: "test-id") {
id
... on User {
name
client_info {
name
description
}
}
}
}

# %extensions%

extend type User {
client_info: ClientInfo
}

type ClientInfo {
name: String
description: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
==================================== INPUT ====================================
query ClientFieldsQuery @relay_test_operation {
node(id: "test-id") {
id
... on User {
name
client_info {
name
description
}
}
}
}

# %extensions%

extend type User {
client_info: ClientInfo
}

type ClientInfo {
name: String
description: String
}
==================================== OUTPUT ===================================
query ClientFieldsQuery @__metadata(relayTestingSelectionTypeInfo: {node: {enumValues: null, nullable: true, plural: false, type: "Node"}, node.id: {enumValues: null, nullable: false, plural: false, type: "ID"}, node.name: {enumValues: null, nullable: true, plural: false, type: "String"}, node.client_info: {enumValues: null, nullable: true, plural: false, type: "ClientInfo"}, node.client_info.name: {enumValues: null, nullable: true, plural: false, type: "String"}, node.client_info.description: {enumValues: null, nullable: true, plural: false, type: "String"}}) {
node(id: "test-id") {
id
... on User {
name
client_info {
name
description
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
query ClientFieldsQuery @relay_test_operation {
node(id: "test-id") {
id
... on User {
name
client_info {
name
description
}
}
}
}

# %extensions%

extend type User {
client_info: ClientInfo
}

type ClientInfo {
name: String
description: String
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ query QueryWitEnums @relay_test_operation {
}
}
}
# %extensions%
==================================== OUTPUT ===================================
query QueryWitEnums @__metadata(relayTestingSelectionTypeInfo: {node: {enumValues: null, nullable: true, plural: false, type: "Node"}, node.id: {enumValues: null, nullable: false, plural: false, type: "ID"}, node.name: {enumValues: null, nullable: true, plural: false, type: "String"}, node.environment: {enumValues: ["WEB", "MOBILE"], nullable: true, plural: false, type: "Environment"}}) {
node(id: "test-id") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ query QueryWitEnums @relay_test_operation {
}
}
}
# %extensions%
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ query SimpleQuery @relay_test_operation {
}
}
}
# %extensions%
==================================== OUTPUT ===================================
query SimpleQuery @__metadata(relayTestingSelectionTypeInfo: {node: {enumValues: null, nullable: true, plural: false, type: "Node"}, node.id: {enumValues: null, nullable: false, plural: false, type: "ID"}, node.name: {enumValues: null, nullable: true, plural: false, type: "String"}}) {
node(id: "test-id") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ query SimpleQuery @relay_test_operation {
}
}
}
# %extensions%
68 changes: 63 additions & 5 deletions compiler/crates/relay-transforms/tests/relay_test_operation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,72 @@
* LICENSE file in the root directory of this source tree.
*/

use std::sync::Arc;

use common::FeatureFlag;
use common::SourceLocationKey;
use fixture_tests::Fixture;
use graphql_test_helpers::apply_transform_for_test;
use graphql_ir::build;
use graphql_ir::Program;
use graphql_syntax::parse_executable;
use graphql_test_helpers::diagnostics_to_sorted_string;
use graphql_text_printer::print_fragment;
use graphql_text_printer::print_operation;
use graphql_text_printer::PrinterOptions;
use regex::Regex;
use relay_test_schema::get_test_schema_with_extensions;
use relay_transforms::generate_test_operation_metadata;

fn transform_fixture_inner(
fixture: &Fixture<'_>,
enable_mock_client_data_metadata_flag: &FeatureFlag,
) -> Result<String, String> {
let parts: Vec<_> = fixture.content.split("%extensions%").collect();

if let [base, extensions] = parts.as_slice() {
let source_location = SourceLocationKey::standalone(fixture.file_name);
let ast = parse_executable(base, source_location).unwrap();
let schema = get_test_schema_with_extensions(extensions);

let ir = build(&schema, &ast.definitions).unwrap();
let program = Program::from_definitions(Arc::clone(&schema), ir);

let test_path_regex = Some(Regex::new(r#"^test"#).unwrap());

let next_program = generate_test_operation_metadata(
&program,
&test_path_regex,
enable_mock_client_data_metadata_flag,
)
.map_err(|diagnostics| diagnostics_to_sorted_string(fixture.content, &diagnostics))?;

let printer_options = PrinterOptions {
debug_directive_data: true,
..Default::default()
};

let mut printed = next_program
.operations()
.map(|def| print_operation(&schema, def, printer_options.clone()))
.chain(
next_program
.fragments()
.map(|def| print_fragment(&schema, def, printer_options.clone())),
)
.collect::<Vec<_>>();
printed.sort();
Ok(printed.join("\n\n"))
} else {
panic!("Expected exactly one %extensions% section marker.")
}
}

pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
let test_path_regex = Some(Regex::new(r#"^test"#).unwrap());
apply_transform_for_test(fixture, |program| {
generate_test_operation_metadata(program, &test_path_regex)
})
transform_fixture_inner(fixture, &FeatureFlag::Disabled)
}

pub fn transform_fixture_with_mock_client_data_enabled(
fixture: &Fixture<'_>,
) -> Result<String, String> {
transform_fixture_inner(fixture, &FeatureFlag::Enabled)
}
Loading

0 comments on commit a47df41

Please sign in to comment.