Skip to content

Commit 18aae91

Browse files
authoredJul 20, 2021
Added Blogpost for Rider Language Injection (#3971)
1 parent 8a8c6aa commit 18aae91

File tree

6 files changed

+175
-0
lines changed

6 files changed

+175
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
---
2+
path: "/blog/2021/07/20/rider-language-injection"
3+
date: "2021-07-20"
4+
title: "Language Injection in Rider"
5+
tags:
6+
[
7+
"hotchocolate",
8+
"tooling",
9+
"graphql",
10+
"dotnet",
11+
"aspnetcore",
12+
"testing",
13+
"jetbrains",
14+
"rider",
15+
]
16+
featuredImage: "rider-language-injection.png"
17+
author: Pascal Senn
18+
authorUrl: https://github.com/pascal_senn
19+
authorImageUrl: https://avatars0.githubusercontent.com/u/14233220
20+
---
21+
22+
This post will show you how JetBrains Rider can make your life a little easier when working with GraphQL queries in string literals.
23+
![Syntax Highliting in String Literals](./header.png)
24+
25+
## Testing is hard
26+
27+
When writing integration tests for HotChocolate, you find yourself often writing GraphQL queries in string literals. The
28+
most challenging part of writing an integration test is to write the query correctly. You quickly forget a bracket, the
29+
name of a field or a required input field and you end up with an invalid query.
30+
31+
If you use JetBrains Rider, you can easily solve this problem and write integration tests with ease. Rider supports
32+
language injection in string literals.
33+
34+
## Getting Started
35+
36+
Rider has no support for the GraphQL language out of the box. You need to install the extension JS GraphQL
37+
from [Jim Kydne Meyer](https://github.com/jimkyndemeyer). You can install the extension from the marketplace or download
38+
it here [JS GraphQL](https://plugins.jetbrains.com/plugin/8097-js-graphql).
39+
40+
The extension needs to know your schema, but in exchange, you get syntax highlighting, linting and IntelliSense.
41+
42+
## Creating a schema file
43+
44+
When you use the annotation-based or the code-first approach of HotChocolate, a change on a domain model often results
45+
in a change in the schema. Even though this is in most cases wanted, it also happens that you change the schema by
46+
accident. It's recommended to have at least one snapshot test of your GraphQL schema to avoid accidental changes.
47+
48+
A snapshot test captures the schema, stores it in the project folder and from then on compares the stored schema against
49+
the schema from your server. In the HotChocolate code base, we make heavy use of snapshot testing. We can recommend the
50+
package [Snapshooter](https://swisslife-oss.github.io/snapshooter/docs/get-started). With Snapshooter you can create snapshot tests for any object.
51+
52+
```csharp
53+
[Fact]
54+
public void ExampleUseOfSnapshooter()
55+
{
56+
// arrange
57+
var serviceToTest = new ServiceToTest();
58+
59+
// act
60+
List<string> result = serviceToTest.GetSomeStrings();
61+
62+
// assert
63+
result.MatchSnapshot();
64+
}
65+
```
66+
67+
A HotChocolate schema, can be printed into a string and this string can then be used in a snapshot test. This schema
68+
snapshot can also be used as the source for the GraphQL extension. The JS GraphQL extension requires a schema file with
69+
the name `schema.graphql`. You can configure the extension in a `.graphqlconfig` file
70+
71+
The snapshot test to capture the schema could look like this:
72+
73+
*/test/ExampleProject.Tests/SchemaTests.cs*
74+
75+
```csharp
76+
public class SchemaTests
77+
{
78+
[Fact]
79+
public async Task SchemaShouldNotChange()
80+
{
81+
// arrange
82+
SnapshotFullName fullName = new XunitSnapshotFullNameReader().ReadSnapshotFullName();
83+
IServiceCollection services = ConfigureTestServices();
84+
IRequestExecutor executor = await services
85+
.AddGraphQLServer()
86+
.BuildRequestExecutorAsync();
87+
88+
// act
89+
string schema = executor.Schema.Print();
90+
91+
// assert
92+
schema.MatchSnapshot(new SnapshotFullName("schema.graphql", fullName.FolderPath));
93+
}
94+
}
95+
```
96+
97+
The example from above creates a snapshot of the schema in `/test/ExampleProject.Tests/__snapshots__/schema.graphql`. You now
98+
have to make the GraphQL extension aware of this schema by creating a .graphqlconfig
99+
100+
*/test/ExampleProject.TestsYourProject.Tests/.graphqlconfig*
101+
102+
```json
103+
{
104+
"name": "example-project",
105+
"schemaPath": "./__snapshots__/schema.graphql"
106+
}
107+
```
108+
109+
Now all *.gql and *.graphql files in your project will have proper syntax highlighting, IntelliSense and linting.
110+
111+
## Inject GraphQL into strings
112+
113+
If you write integration tests for your GraphQL server, your tests probably look similar to this:
114+
115+
```csharp
116+
public class PersonsIntegrationTests
117+
{
118+
[Fact]
119+
public async Task GetPersons_Should_ReturnPagesPersons()
120+
{
121+
// arrange
122+
IServiceCollection services = ConfigureTestServices();
123+
IRequestExecutor executor = await services
124+
.AddGraphQLServer()
125+
.BuildRequestExecutorAsync();
126+
127+
string query =
128+
@"query getPersons {
129+
persons {
130+
nodes {
131+
name
132+
}
133+
}
134+
}";
135+
136+
IReadOnlyQueryRequest request =
137+
QueryRequestBuilder.New().SetQuery(query).Create();
138+
139+
// act
140+
IExecutionResult result = await executor.ExecuteAsync(request);
141+
142+
// assert
143+
result.ToJson().MatchSnapshot();
144+
}
145+
}
146+
```
147+
148+
The GraphQL extension now knows the schema, but Rider does not understand that the string contains a GraphQL query.
149+
To make Rider aware of string literals that contain GraphQL queries, you have to add a new language injection provider.
150+
151+
1. Go To 'Preferences' and search for 'Language Injection'
152+
![Rider Preferences Window](./preferences.png)
153+
2. Add a new 'Generic Csharp' Language Injection
154+
3. Select GraphQL in the Dropdown ID
155+
4. Add the following pattern
156+
157+
```text
158+
- csharpLiteralExpression().withText(string().matchesBrics("@?[\"'] *((query|mutation|subscription) .*) .*[\"']?"))
159+
```
160+
![Rider language injection-settings](./language-injection-settings.png)
161+
162+
Now every string in C# that starts with either `query`, `mutation`, or `subscription` will be interpreted by Rider as a GraphQL Query.
163+
164+
![Rider Look and Feel with the working extensions](./lookandfeel.png)
165+
166+
You can find an example project here [rider-language-injection-example](https://github.com/PascalSenn/rider-language-injection-example)
167+
168+
169+
170+
In case you have questions, [Join our Slack Channel](https://bit.ly/joinchilli). We have a very welcoming and helpful community that is waiting for you.
171+
172+
If you like what we are doing at ChilliCream, head over to the [HotChocolate repository and **give us a star**](https://github.com/ChilliCream/hotchocolate).
173+
It helps us to gain visibility and grow our already awesome community!
174+
175+
Thank you!

Error rendering embedded code

Invalid image source.

Error rendering embedded code

Invalid image source.

Error rendering embedded code

Invalid image source.

Error rendering embedded code

Invalid image source.

Error rendering embedded code

Invalid image source.

0 commit comments

Comments
 (0)
Please sign in to comment.