Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions e2e/grpc-example/__snapshots__/grpc-example.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,16 @@ input SearchByCastRequest_Input @join__type(graph: MOVIES) {
"
`;

exports[`gRPC Example gets empty movies correctly: get-empty-movies-grpc-example-result 1`] = `
{
"data": {
"exampleGetMovies": {
"result": [],
},
},
}
`;

exports[`gRPC Example gets movies correctly: get-movies-grpc-example-result 1`] = `
{
"data": {
Expand Down
23 changes: 23 additions & 0 deletions e2e/grpc-example/grpc-example.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,29 @@ describe('gRPC Example', () => {
const { result } = await compose({ services: [movies], maskServicePorts: true });
expect(result).toMatchSnapshot();
});
it('gets empty movies correctly', async () => {
const { output } = await compose({ services: [movies], output: 'graphql' });
const { execute } = await serve({ supergraph: output });
// Genre HORROR does not exist in mock data
const query = /* GraphQL */ `
query GetMovies {
exampleGetMovies(input: { movie: { genre: HORROR, year: 2015 } }) {
result {
name
year
rating
cast
time {
seconds
}
}
}
}
`;
await expect(execute({ query })).resolves.toMatchSnapshot(
'get-empty-movies-grpc-example-result',
);
});
Comment on lines +18 to +40
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Test scenario may not effectively demonstrate the defaults issue.

The test queries with genre: HORROR, which doesn't exist in the mock data, and expects an empty result. However, issue #5277 describes a bug where fields within returned objects have null values instead of their protobuf default values (e.g., an enum defaulting to ENUM_ZERO). An empty result set won't demonstrate this issue.

To properly test the defaults behavior, consider:

  1. Query data that exists in the mock (e.g., use genre: DRAMA like in the next test)
  2. Include fields that have protobuf defaults (especially enum fields)
  3. Assert that those fields are populated with their default values, not null

This would create a test that fails in a way that clearly demonstrates the missing defaults functionality described in the issue.

Example revision:

- it('gets empty movies correctly', async () => {
+ it('populates protobuf default values correctly', async () => {
    const { output } = await compose({ services: [movies], output: 'graphql' });
    const { execute } = await serve({ supergraph: output });
-   // Genre HORROR does not exist in mock data
+   // Query existing data to check if fields with defaults are populated
    const query = /* GraphQL */ `
      query GetMovies {
-       exampleGetMovies(input: { movie: { genre: HORROR, year: 2015 } }) {
+       exampleGetMovies(input: { movie: { genre: DRAMA, year: 2015 } }) {
          result {
            name
            year
            rating
            cast
+           genre
            time {
              seconds
            }
          }
        }
      }
    `;
    await expect(execute({ query })).resolves.toMatchSnapshot(
-     'get-empty-movies-grpc-example-result',
+     'get-movies-with-defaults-result',
    );
  });

This way, when the test snapshot is generated, you can verify whether enum fields (like genre) are set to their protobuf default values or null, directly demonstrating the issue.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('gets empty movies correctly', async () => {
const { output } = await compose({ services: [movies], output: 'graphql' });
const { execute } = await serve({ supergraph: output });
// Genre HORROR does not exist in mock data
const query = /* GraphQL */ `
query GetMovies {
exampleGetMovies(input: { movie: { genre: HORROR, year: 2015 } }) {
result {
name
year
rating
cast
time {
seconds
}
}
}
}
`;
await expect(execute({ query })).resolves.toMatchSnapshot(
'get-empty-movies-grpc-example-result',
);
});
it('populates protobuf default values correctly', async () => {
const { output } = await compose({ services: [movies], output: 'graphql' });
const { execute } = await serve({ supergraph: output });
// Query existing data to check if fields with defaults are populated
const query = /* GraphQL */ `
query GetMovies {
exampleGetMovies(input: { movie: { genre: DRAMA, year: 2015 } }) {
result {
name
year
rating
cast
genre
time {
seconds
}
}
}
}
`;
await expect(execute({ query })).resolves.toMatchSnapshot(
'get-movies-with-defaults-result',
);
});
🤖 Prompt for AI Agents
In e2e/grpc-example/grpc-example.test.ts around lines 18 to 40, the test queries
for a non-existent genre (HORROR) which returns an empty result and therefore
cannot reveal the protobuf-defaults bug; change the test to query existing mock
data (e.g., use genre: DRAMA as in the next test), include fields that have
protobuf defaults (especially enum fields and nested scalar fields), and assert
(or snapshot) that those fields are populated with their protobuf default values
instead of null so the test fails when defaults are missing.

it('gets movies correctly', async () => {
const { output } = await compose({ services: [movies], output: 'graphql' });
const { execute } = await serve({ supergraph: output });
Expand Down
7 changes: 6 additions & 1 deletion e2e/grpc-example/mesh.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ export const composeConfig = defineComposeConfig({
someKey: 'someValue',
connection_type: '{context.headers.connection}',
},
source: './services/movies/proto/service.proto',
source: {
file: './services/movies/proto/service.proto',
load: {
defaults: true,
},
},
}),
transforms: [
createNamingConventionTransform({
Expand Down
Loading