Skip to content

Add integration test suite for GraphQL emitter#85

Open
FionaBronwen wants to merge 32 commits into
feature/graphqlfrom
fionabronwen/graphql-components-test-suite
Open

Add integration test suite for GraphQL emitter#85
FionaBronwen wants to merge 32 commits into
feature/graphqlfrom
fionabronwen/graphql-components-test-suite

Conversation

@FionaBronwen

@FionaBronwen FionaBronwen commented Apr 21, 2026

Copy link
Copy Markdown

Summary

Adds a comprehensive test suite for the GraphQL emitter.
Test coverage: 288 tests across 29 test files

Integration Tests

Test File Tests Coverage
e2e.test.ts 6 End-to-end schema generation with comprehensive TypeSpec features
scalars.test.ts 9 Custom scalars, built-in mappings (int64→Long, decimal→BigDecimal, url→URL), @specifiedBy directives
enums.test.ts 3 Enum type generation and CONSTANT_CASE conversion
unions.test.ts 5 Named unions, anonymous unions, scalar wrapping, nested union flattening
nullability.test.ts 28 Optional vs nullable semantics in input/output contexts
input-output-splitting.test.ts 9 Model splitting when used as both input and output
doc-comments.test.ts 3 Doc comment propagation to GraphQL descriptions
subscriptions.test.ts 5 Subscription operations with arguments and complex types
interfaces-sdl.test.ts 6 Interface declarations, multiple implementations, inheritance
operation-fields-sdl.test.ts 5 @operationFields decorator output
diagnostics.test.ts 12 Emitter diagnostics (empty-schema, void-return, interface validation)

Component Unit Tests

Test File Tests Coverage
scalar-type.test.tsx 5 ScalarType component rendering
enum-type.test.tsx 5 EnumType component rendering
union-type.test.tsx 4 UnionType component rendering
object-type.test.tsx 10 ObjectType component (fields, interfaces, operation fields)
interface-type.test.tsx 5 InterfaceType component rendering
input-type.test.tsx 5 InputType component rendering
operation-types.test.tsx 10 Query/Mutation/Subscription type components

Other Tests

  • graphql-mutation-engine.test.ts (80 tests) - Mutation engine transformations
  • Decorator tests, type-utils tests, type-usage analysis tests

Test plan

  • All 288 tests pass
  • Inline snapshots capture generated SDL for regression detection
  • Component tests verify individual type rendering
  • Diagnostic tests verify appropriate warnings/errors are reported

@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from 0b4cb8e to 3387127 Compare April 21, 2026 20:25
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch 2 times, most recently from 157c423 to 6574167 Compare April 21, 2026 20:33
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from 3387127 to 1a5163c Compare April 21, 2026 20:33
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch from 6574167 to f3179e4 Compare April 21, 2026 20:43
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch 2 times, most recently from 9e90b36 to ffc3f0f Compare April 22, 2026 17:09
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch 2 times, most recently from cda60b4 to 6211400 Compare April 28, 2026 15:13
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from ffc3f0f to 2763d30 Compare April 28, 2026 15:13
Introduce the foundation for the component-based GraphQL emitter:

- Build/config: Add @alloy-js/core, @alloy-js/graphql dependencies,
  configure JSX transpilation (tsconfig, vitest)
- Context system: GraphQLSchemaContext with ClassifiedTypes,
  ModelVariants, and ScalarVariant interfaces
- Field components: Field, OperationField, and GraphQLTypeExpression
  for rendering model properties and operations as GraphQL SDL
- Type resolution: GraphQLTypeExpression handles scalars, models,
  enums, unions, arrays, and nullability using an isInput prop to
  distinguish input vs output context
- Scalar mappings: Add getGraphQLBuiltinName() for built-in scalar
  identity checks
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from 2763d30 to f73791c Compare April 28, 2026 15:28
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch from 6211400 to 159673e Compare April 28, 2026 15:28
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from f73791c to ce4affb Compare April 28, 2026 15:55
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch 2 times, most recently from 3f5da2b to 7db97d1 Compare April 28, 2026 21:21
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch 2 times, most recently from 98fb4f4 to eb57da4 Compare April 30, 2026 21:10
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch from 7db97d1 to 0fa84c0 Compare April 30, 2026 21:10
The ModelVariants lookup structure was originally designed to help
components decide when to append "Input" suffix to model names.
However, the mutation engine now fully handles this:
- Input models are mutated with the "Input" suffix already applied
- Property type references are rewired to point to the correct variants

This commit removes the unused ModelVariants interface and the lookup
logic from GraphQLTypeExpression, simplifying the component to just
use the model's name directly.

Also adds unionMembers to context (needed for union rendering).
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from eb57da4 to 2be2c50 Compare May 1, 2026 15:17
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch from 0fa84c0 to ff55993 Compare May 1, 2026 15:17
Remove unused utility functions that were superseded by the mutation engine:
- getTemplatedModelName (mutation engine handles template naming)
- getSingleNameWithNamespace (never used in production)
- isArray, isRecordType, isScalarOrEnumArray, isUnionArray (use compiler's isArrayModelType)
- unwrapModel, unwrapType (never imported)
- isTrueModel (never imported)

Also removes the corresponding test for getSingleNameWithNamespace.
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from 2be2c50 to c975212 Compare May 1, 2026 15:33
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch from ff55993 to e106d87 Compare May 1, 2026 15:33
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch 2 times, most recently from 918f6cc to cf1eb14 Compare May 1, 2026 20:04
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch from e106d87 to bc9c39c Compare May 5, 2026 15:40
Add the first set of Alloy JSX components for GraphQL type emission:
- EnumType: renders GraphQL enum definitions with member descriptions and deprecation
- ScalarType: renders custom scalar definitions with @specifiedBy support
- UnionType: renders union type definitions with model and scalar variant members
- GraphQLSchema: root context wrapper providing TspContext and GraphQLSchemaContext

Add component-level tests using renderSchema + printSchema to exercise the
real Alloy rendering pipeline. Each component is tested in isolation with a
lightweight test helper (renderComponentToSDL) that provides minimal context.

14 new tests covering: basic rendering, doc comments, deprecation, name
sanitization, @specifiedBy, union member registration, and scalar wrappers.
- Extract isScalarLikeType() to type-utils.ts shared utility, replacing
  duplicated inline check in union-type.tsx
- Replace unsafe `as Union` casts in union-type tests with assertUnionResult()
  helper that provides a clear error if the mutation returns a Model
Replace fragile .toContain() assertions with inline snapshots to match
TSP ecosystem best practices. This makes test output more readable and
maintainable by showing the complete expected SDL in one place.
The function was extracted from union-type.tsx in commit 6d47132e4
but the type-utils.ts hunk was dropped during the rebase due to
conflicts with 'Remove dead code from type-utils.ts' in the base.
- ScalarType: take specificationUrl as prop instead of from context
- component-test-utils: use minimal TypeGraph context
- scalar-type.test: pass specificationUrl as prop
- Mutate operations in schema-mutator so type references point to
  correctly mutated types (input params → mutated input models,
  return types → mutated output models)
- Fix nullable union replacement to mutate inner type with context
  (Address | null → AddressInput in input context)
- Add Input suffix to models in input context with double-suffix
  prevention (BookInput stays BookInput, not BookInputInput)
- Add comprehensive tests for input suffix, nullable union
  replacement, and operation type references
Models used as both input and output must be mutated separately:
- Output context produces 'Foo'
- Input context produces 'FooInput'

Previously, all models were mutated with Output context only, causing
duplicate type names when rendering both variants.
- Add withInputSuffix helper to prevent "PetInput" → "PetInputInput"
- Fix oneOf input unions to mutate variant types with input context
  (model variants now correctly get their Input suffix, e.g. Cat → CatInput)
- Refactor model.ts to use shared withInputSuffix helper
Add field-bearing type components that use the Field infrastructure
(already present from the parent branch):
- ObjectType: renders object types with fields, @compose interfaces,
  and @operationFields support
- InterfaceType: renders interface type definitions with fields
- InputType: renders input types with automatic Input suffix when a
  model appears in both input and output positions

17 new component tests covering: basic field rendering, doc comments,
optional/nullable fields, array/list types, deprecated fields,
interface implementation via @compose, and Input suffix logic.
…ed imports

- Add explanatory comment on getComposition/iface.name in object-type.tsx
  clarifying that pre-mutation names match post-mutation names (mutation
  engine doesn't rename models)
- Remove unused `type Model` import from all G2 test files
- Add @operationFields test to ObjectType (verifies operation field rendering)
- Add nested model reference test to ObjectType (verifies type references)
- Add empty model tests to ObjectType, InputType, InterfaceType
  (documents that GraphQL requires at least one field per type)
The mutation engine now handles all input/output type naming, so components
can use type.name directly without looking up whether a model has both
input and output variants.
- Remove implementation detail comments about mutation engine
- Remove redundant tests that were testing non-responsibility of the component
  (InputType doesn't add suffixes - that's not its job)
Replace fragile .toContain() assertions with inline snapshots to match
TSP ecosystem best practices. This makes test output more readable and
maintainable by showing the complete expected SDL in one place.
Brings the component-based GraphQL emitter online by wiring the data
pipeline from the foundation skeleton into Alloy JSX rendering.

New components:
- components/operations/query-type.tsx, mutation-type.tsx, subscription-type.tsx:
  render the three GraphQL root operation types
- components/operations/index.ts: barrel export
- components/type-collections.tsx: orchestrator that dispatches each
  classified-type bucket (scalars, enums, unions, interfaces, objects, inputs)
  into the appropriate leaf-type component

Emitter wiring:
- Rename src/emitter.ts → src/emitter.tsx
- Phase 5 now renders via Alloy's renderSchema, converts to SDL with
  graphql-js printSchema, and writes the output via emitFile
- Adds output-file option handling with interpolatePath

Testing:
- test/e2e.test.ts: single happy-path smoke test proving the full
  TypeSpec → mutation → classification → rendering → SDL pipeline works
- Update the existing test/emitter.test.ts data-pipeline test to now
  assert that SDL output is produced (Phase 5 is wired up)

Broader integration coverage (nullability, input/output splitting,
unions, enums, arrays, circular refs, deprecation, doc comments) lands
in a follow-up PR focused on tests.
Adds component tests for QueryType, MutationType, and SubscriptionType
using inline snapshots. Tests cover rendering with scalar return types,
model return types (with stub type registration), parameters, and empty
operation lists.

Updates renderComponentToSDL utility to support skipPlaceholderQuery
option for testing QueryType, while maintaining backwards compatibility
with existing tests that pass context overrides directly.

Also cleans up e2e and emitter tests to use consistent vitest expect()
assertions with toMatchInlineSnapshot() instead of mixed strictEqual
and .includes() checks.
- type-collections: components take data via props instead of context
- emitter: pass MutatedSchema data directly to collection components
- Use minimal TypeGraph context (just globalNamespace)

This aligns with the TypeGraph design where context is minimal and
components receive their data through props.
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-operations-wiring branch from 8ac0071 to c42edc5 Compare June 3, 2026 20:01
Expands the test coverage of the component-based emitter to exercise
the full surface area of TypeSpec-to-GraphQL translation.

New test files:
- nullability.test.ts: required vs. optional vs. T | null, input and output
  side semantics, list element nullability
- input-output-splitting.test.ts: models used as input, output, or both;
  verifies correct suffixing and separation
- unions.test.ts: named union types, nullable variants, wrapper models
- enums.test.ts: enum declarations, enum values, enum references in
  model properties and operations
- arrays.test.ts: array element non-null semantics and nested arrays
- circular-references.test.ts: self-referential and mutually recursive
  model definitions
- deprecation.test.ts: @deprecated decorator propagation to SDL
- doc-comments.test.ts: doc-comment propagation to SDL descriptions

Extends e2e.test.ts beyond the single smoke test into a full scenario
suite (complete API schema, custom scalars, union output types, models
used only as input, mutations, empty schema handling, operation
parameters, and complex SDL validation).

Extends test/main.tsp with the fixture models, operations, and helpers
needed by the e2e and integration tests.

No production code changes — this PR is tests only.
… diagnostics

- subscriptions.test.ts: 5 tests for subscription operations with
  arguments, arrays, and complex input types
- interfaces-sdl.test.ts: 6 tests for interface type declarations,
  multiple interface implementations, interface inheritance, and
  optional fields
- operation-fields-sdl.test.ts: 5 tests for @operationFields decorator
  SDL output including field arguments and interface operations
- diagnostics.test.ts: 12 tests for emitter diagnostics including
  empty-schema, void-operation-return, duplicate union variants,
  interface validation errors, and operation-kind conflicts
Updated snapshot expectations to reflect correct behavior where optional
fields (?) are nullable in both input and output contexts.

Also skipped union-within-union test that crashes in Alloy (pre-existing bug).
@FionaBronwen
FionaBronwen force-pushed the fionabronwen/graphql-components-test-suite branch from ea9883d to 8b368d5 Compare June 3, 2026 20:15
@FionaBronwen
FionaBronwen changed the base branch from fionabronwen/graphql-components-operations-wiring to feature/graphql June 9, 2026 21:04
@FionaBronwen
FionaBronwen force-pushed the feature/graphql branch 2 times, most recently from 59ad903 to 7d69aac Compare June 16, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant