Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix printed schema descriptions that end with a double quote (") #1205

Closed
wants to merge 4 commits into from

Conversation

sethtippetts
Copy link

Schemas printed with printSchema that contain descriptions ending with a double-quote character are not parseable and throw a GraphQLError: Syntax Error: Unterminated string because the SDL description ends with 4 contiguous double-quotes

I've included a failing test case:

const Root = new GraphQLObjectType({
      name: 'Root',
      fields: {
        onlyField: {
          type: GraphQLString,
          description: 'This field is "awesome"',
        },
      },
    });
    const Schema = new GraphQLSchema({ query: Root });
    const output = printSchema(Schema);
    expect(() => parse(output)).not.to.throw(GraphQLError);

@leebyron
Copy link
Contributor

cc @IvanGoncharov - I know you had a similar fix land earlier. Care to review this?

@IvanGoncharov
Copy link
Member

IvanGoncharov commented Jan 19, 2018

cc @IvanGoncharov - I know you had a similar fix land earlier. Care to review this?

@leebyron @mostcowbell Yes I fixed similar issue with print function in #1190

Adding space changes description string and if we want to omit it than possible solution would be:

"""
This field is "awesome"
"""

Or:

"""This field is "awesome"
"""

Also, you need to handle the same edge case as print function:

"""    space-led value "quoted string"
"""

On the other hand descriptionLines already changes description string.
Moreover, all description values are in Markdown format so trailing spaces are ignored.

Personally, I think print should try to produce an output as close as possible to original but printSchema output should be readable and less-surprising. So I think @mostcowbell solution is better but it should be explicitly documented in the tests.

@sethtippetts
Copy link
Author

@IvanGoncharov so I should add another assertion to my test?

expect(output).to.equal(`
  schema {
    query: Root
  }
  
  type Root {
    """This field is "awesome" """
    onlyField: String
  }
`);

or just a comment about the output of a description ending in a double-quote?

// Will be printed as `"""This field is "awesome" """` to avoid parsing issues

@IvanGoncharov
Copy link
Member

IvanGoncharov commented Jan 19, 2018

@mostcowbell I would suggest being as explicit as possible:

    const description = 'This field is "awesome"';
    const output = printSingleFieldSchema({ type: GraphQLString, description });
    expect(output).to.equal(`
      ...
    `);

    const recreatedRoot = buildSchema(output).getTypeMap()['Root'];
    const recreatedField = recreatedRoot.getFields()['singleField'];

    /* Note: Additional space added to prevent parser confusing trailing double
     * quote inside description with the end of the block string. It shouldn't
     * affect result since descriptions are interpreted as Markdown so trailing
     * spaces are ignored.
     */
    expect(recreatedField.description).to.equal(description + ' ');

Disclaimer: I'm not a native speaker :)

Prints a parseable schema when a comment ends with a doublequote (")s

And change test description to something like: Prints a field description that ends with a doublequote (")s

@sethtippetts
Copy link
Author

@IvanGoncharov I've updated my test and removed the extra dependencies I was importing into that file

const Schema = new GraphQLSchema({ query: Root });
const output = printSchema(Schema);
expect(() => parse(output)).not.to.throw(GraphQLError);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mostcowbell It's better to reuse printSingleFieldSchema similar to other tests since it allows you test that printSchema output not only parse-ready but you can recreate schema based on it. I also think it's important to have the output of printSchema inside test so you would see how doublequote is escaped. So I suggest to change it like this:

    const description = 'This field is "awesome"';
    const output = printSingleFieldSchema({ type: GraphQLString, description });
    expect(output).to.equal(dedent`
      schema {
        query: Root
      }

      type Root {
        """This field is "awesome" """
        singleField: String
      }
    `);

I experiment a bit and expend test to ensure that description stays unchanged:

    const recreatedDescription = buildSchema(output)
      .getTypeMap()['Root']
      .getFields()['singleField']
      .description;
    expect(recreatedDescription).to.equal(description);

And it fails 😞

AssertionError: expected 'This field is "awesome" ' to equal 'This field is "awesome"'
                                                 ^ Note space here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After giving it a thought I don't think that adding space to a description is such a big issue but it should be explicitly documented in the test, like:

expect(recreatedDescription).to.equal(description + ' ');

And since it's not so obvious issue, both test and implementation should contain a comment with an explanation for why it's needed.

@leebyron
Copy link
Contributor

I'd like to see a solution that also handles the edge cases you referenced, @IvanGoncharov - I'll pull in these test cases and ensure the solution accounts for them.

leebyron added a commit that referenced this pull request Jan 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants