artemis
artemis copied to clipboard
Fragments: The superclass, '<name>FragmentMixin', has no unnamed constructor that takes no arguments
Before reporting a bug, please test the beta branch!
Bug description
I have a fragment that with direct fields except __typename and a union. The fragment and query is generated successfully, but when I write a unit test, I get the following errors while loading the unit tests. The query and fragment runs successfully on Apollo Graph explorer.
Errors
Failed to load "test/graphql_gateway_client_inquiry_test.dart":
lib/src/graphql/graphql.graphql.dart:3251:7: Error: The superclass, 'InquiryFragmentMixin', has no unnamed constructor that takes no arguments.
class InquiryFragmentMixin$Inquiry extends InquiryFragmentMixin
^
lib/src/graphql/graphql.graphql.dart:3272:7: Error: The superclass, 'InquiryFragmentMixin', has no unnamed constructor that takes no arguments.
class InquiryFragmentMixin$InquiryNotFoundError extends InquiryFragmentMixin
^
lib/src/graphql/graphql.graphql.dart:3290:7: Error: The superclass, 'InquiryFragmentMixin', has no unnamed constructor that takes no arguments.
class InquiryFragmentMixin$ServiceUnavailableError extends InquiryFragmentMixin
^
lib/src/graphql/graphql.graphql.dart:3308:7: Error: The superclass, 'InquiryFragmentMixin', has no unnamed constructor that takes no arguments.
class InquiryFragmentMixin$InquiryResumeFailedError extends InquiryFragmentMixin
Specs
Artemis version: 7.1.1-beta.1
build.yaml:
targets:
$default:
sources:
- lib/**
- lib/src/graphql/**
- lib/src/graphql/schema.graphql
graphql_gateway:
builders:
source_gen|combining_builder:
options:
ignore_for_file:
- public_member_api_docs
- lines_longer_than_80_chars
- constant_identifier_names
artemis:
options:
fragments_glob: lib/src/graphql/fragments/*.fragment.graphql
schema_mapping:
- schema: lib/src/graphql/schema.graphql
queries_glob: lib/src/graphql/queries/**.graphql
output: lib/src/graphql/graphql.dart
scalar_mapping:
- graphql_type: PhoneNumber
dart_type: String
- graphql_type: EmailAddress
dart_type: String
- graphql_type: DateTime
dart_type: DateTime
- graphql_type: PostalCode
dart_type: String
json_serializable:
options:
include_if_null: false
Artemis output:
flutter pub run build_runner build --verbose
[ +119 ms] executing: sysctl hw.optional.arm64
[ +24 ms] Exit code 1 from: sysctl hw.optional.arm64
[ ] sysctl: unknown oid 'hw.optional.arm64'
[ +13 ms] executing: [/Applications/Flutter/beta/] git -c log.showSignature=false log -n 1 --pretty=format:%H
[ +52 ms] Exit code 0 from: git -c log.showSignature=false log -n 1 --pretty=format:%H
[ ] d79295af24c3ed621c33713ecda14ad196fd9c31
[ ] executing: [/Applications/Flutter/beta/] git tag --points-at d79295af24c3ed621c33713ecda14ad196fd9c31
[ +198 ms] Exit code 0 from: git tag --points-at d79295af24c3ed621c33713ecda14ad196fd9c31
[ ] 2.2.2
[ +7 ms] executing: [/Applications/Flutter/beta/] git rev-parse --abbrev-ref --symbolic @{u}
[ +18 ms] Exit code 0 from: git rev-parse --abbrev-ref --symbolic @{u}
[ ] origin/stable
[ ] executing: [/Applications/Flutter/beta/] git ls-remote --get-url origin
[ +17 ms] Exit code 0 from: git ls-remote --get-url origin
[ ] https://github.com/flutter/flutter.git
[ +133 ms] executing: [/Applications/Flutter/beta/] git rev-parse --abbrev-ref HEAD
[ +26 ms] Exit code 0 from: git rev-parse --abbrev-ref HEAD
[ +1 ms] stable
[ +9 ms] executing: sw_vers -productName
[ +21 ms] Exit code 0 from: sw_vers -productName
[ +1 ms] macOS
[ ] executing: sw_vers -productVersion
[ +21 ms] Exit code 0 from: sw_vers -productVersion
[ ] 11.4
[ ] executing: sw_vers -buildVersion
[ +24 ms] Exit code 0 from: sw_vers -buildVersion
[ ] 20F71
[ +97 ms] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[ +5 ms] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[ +173 ms] Artifact Instance of 'MaterialFonts' is not required, skipping update.
[ ] Artifact Instance of 'GradleWrapper' is not required, skipping update.
[ ] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[ ] Artifact Instance of 'FlutterSdk' is not required, skipping update.
[ ] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[ ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FontSubsetArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'PubDependencies' is not required, skipping update.
[ +19 ms] executing: /Applications/Flutter/beta/bin/cache/dart-sdk/bin/pub run build_runner build --verbose
[INFO] Entrypoint:Generating build script...
[INFO] Entrypoint:Generating build script completed, took 650ms
[INFO] BuildDefinition:Initializing inputs
[INFO] BuildDefinition:Reading cached asset graph...
[INFO] BuildDefinition:Reading cached asset graph completed, took 80ms
[INFO] BuildDefinition:Checking for updates since last build...
[INFO] BuildDefinition:Checking for updates since last build completed, took 498ms
[INFO] Build:Running build...
[INFO] Build:Running build completed, took 20ms
[INFO] Build:Caching finalized dependency graph...
[INFO] Build:Caching finalized dependency graph completed, took 44ms
[INFO] Build:Succeeded after 78ms with 0 outputs (0 actions)
[+3945 ms] "flutter run" took 4,186ms.
[ +5 ms] Running shutdown hooks
[ ] Shutdown hooks complete
[ ] exiting with code 0
GraphQL schema:
union InquiryResult = Inquiry | InquiryNotFoundError | InquiryResumeFailedError | ServiceUnavailableError
GraphQL query:
fragment inquiryResultFragment on InquiryResult {
__typename
... on Inquiry {
id
status
accessToken
}
... on InquiryNotFoundError {
message
}
... on ServiceUnavailableError {
message
}
... on InquiryResumeFailedError {
message
}
}
query getInquiryById($inquiryById: ID!) {
user {
inquiryBy(id: $inquiryById) {
...inquiryResultFragment
}
}
}
Hi @tuanvugoodmoney could you add some code from graphql_gateway_client_inquiry_test.dart
so we can reproduce the issue
import 'package:mocktail/mocktail.dart';
import 'package:test/test.dart';
late GraphQLClient graphQLClient;
late GraphQLGatewayClient graphQLGatewayClient;
setUpAll(() {
registerFallbackValue<QueryOptions>(FakeQueryOptions());
});
setUp(() {
graphQLClient = MockGraphQLClient();
graphQLGatewayClient = GraphQLGatewayClient(
graphQLClient: graphQLClient,
);
});
test('invokes query with correct query options', () async {
final result = MockQueryResult();
when(() => result.hasException).thenReturn(false);
when(() => result.data).thenReturn(data);
final queryCalls = <QueryOptions?>[];
when(() => graphQLClient.query(any())).thenAnswer((invocation) async {
queryCalls.add(invocation.positionalArguments.first);
return result;
});
await graphQLGatewayClient.getInquiryById(inquiryId: 'inquiryId');
expect(queryCalls.length, 1);
expect(
queryCalls.first!.document,
GetInquiryByIdQuery(
variables: GetInquiryByIdArguments(
inquiryById: 'inquiryById',
),
).document,
);
expect(queryCalls.first!.variables, const <String, dynamic>{
'inquiryById': 'inquiryId',
});
expect(queryCalls.first!.fetchPolicy, FetchPolicy.noCache);
});
@tuanvugoodmoney I do not see here anything related to generated code... This file does not imports any implementation from generated code
Where this error come from? Is there any stacktrace?
This code import only two libraries test
and mocktail
. It should still work fine if you delete everything related to generated code. Unless you posted limited version of file...
I'll work on creating a new repo to reproduce the problem
Thanks
@vasilich6107 See this repository. My original project had analysis turned off for all generated graphql files so I didn't see compilation errors. In this new project, the generated graphql.graqhql.dart actually has a compilation error, see screenshot. In the same repo, you can see the user fragment generates normally.
If you try to run the test, the original error referenced in this ticket shows up, due to compilation error.
Thanks for your help
Will try to address the issue this week
Hi @tuanvugoodmoney Sorry for not paying proper attention to this bug. Will try to address it in one week
Hi @tuanvugoodmoney
For now I can only suggest you to write
query getInquiryById($inquiryById: ID!) {
user {
inquiryBy(id: $inquiryById) {
__typename
... on Inquiry {
id
}
... on InquiryNotFoundError {
message
}
... on ServiceUnavailableError {
message
}
... on InquiryResumeFailedError {
message
}
}
}
}
without using the fragment
@tuanvugoodmoney you can also write like this to incorporate fragments
query getInquiryById($inquiryById: ID!) {
user {
...User
}
}
fragment User on User {
inquiryBy(id: $inquiryById) {
__typename
... on Inquiry {
id
}
... on InquiryNotFoundError {
message
}
... on ServiceUnavailableError {
message
}
... on InquiryResumeFailedError {
message
}
}
}
Any update on this issue? I'm seeing the same compiler errors in generated code:

The issue seems to be caused by nested fragments within either a union or interface.
@jjoelson you can apply the workaround that I suggested in my previous comment
@vasilich6107 Thank you for the quick response! I am able to work around it for now by restructuring my fragments.
I might dive a bit into the Artemis code to see if I can figure out the issue, so I'll comment here if I find anything useful.
This is also affecting me :(
I have the nested fragment inside of an interface, and I get a similar extends XYZMixin
compile error.
Going to use the workaround to avoid the inner fragment, but it's definitely not as clean
@cody1024d unfortunately there is no solution for now except the reorganizing fragments structure
@vasilich6107 No problem. It is not the end of the world! Thank you for this awesome project!
Any updates on this issue?
I would like to use a shared mixin from a union to render a UI for all queries that return the data, so the workaround above results in a type error.
Example:
// schema.grapqhl
interface InsightTabFields {
id: ID!
name: String!
}
type Insight implements InsightTabFields {
id: ID!
name: String!
insight: String!
}
type Image implements InsightTabFields {
id: ID!
name: String!
image: String!
}
type Game {
users: [User!]!
insights: [InsightTab!]!
otherGameData: OtherGameData!
}
type User {
insights: [InsightTab!]!
otherUserData: OtherUserData!
}
// fragments.graphql
fragment InsightTab on InsightTab {
__typename
... on Insight {
__typename
...Insight
}
... on Image {
__typename
...Image
}
}
fragment Insight on Insight {
id
name
insight
}
fragment Image on Image {
id
name
image
}
fragment User on User {
__typename
insights: {
__typename
...InsightTab
}
otherUserData: {
__typename
...otherUserData
}
}
fragment Game on Game {
__typename
insights: {
__typename
...InsightTab
}
otherGameData: {
__typename
...otherGameData
}
}
// queries
query GetUserInsightTabs($userId: ID!) {
getUserInsightTabs(userId: $userId) {
__typename
...User
}
}
query GetMatchInsightTabs($matchId: ID!) {
getMatchInsightTabs(matchId: $matchId) {
__typename
...Game
}
}
We're using the same UI widget to show all insights. So the workaround posted results in the error UserMixin$InsightTab is not of type GameMixin$InsightTab. I was hoping to make the widget expect InsightTabMixin so both cases work. Is there a fix or other workaround I should try?