Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Fragments: The superclass, '<name>FragmentMixin', has no unnamed constructor that takes no arguments #346

Open
tuanvugoodmoney opened this issue Jul 19, 2021 · 19 comments
Labels
bug Something isn't working

Comments

@tuanvugoodmoney
Copy link

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
    }
  }
}
@tuanvugoodmoney tuanvugoodmoney added the bug Something isn't working label Jul 19, 2021
@vasilich6107
Copy link
Collaborator

Hi @tuanvugoodmoney could you add some code from graphql_gateway_client_inquiry_test.dart so we can reproduce the issue

@tuanvugoodmoney
Copy link
Author

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);
  });

@vasilich6107
Copy link
Collaborator

@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?

@vasilich6107
Copy link
Collaborator

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...

@tuanvugoodmoney
Copy link
Author

I'll work on creating a new repo to reproduce the problem

@vasilich6107
Copy link
Collaborator

Thanks

@tuanvugoodmoney
Copy link
Author

@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.

Screen Shot 2021-07-21 at 10 53 17 AM

@vasilich6107
Copy link
Collaborator

Thanks for your help

@vasilich6107
Copy link
Collaborator

Will try to address the issue this week

@vasilich6107
Copy link
Collaborator

Hi @tuanvugoodmoney
Sorry for not paying proper attention to this bug.
Will try to address it in one week

@vasilich6107
Copy link
Collaborator

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

@vasilich6107
Copy link
Collaborator

@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
    }
  }
}

@jjoelson
Copy link

jjoelson commented Oct 7, 2021

Any update on this issue? I'm seeing the same compiler errors in generated code:

image

The issue seems to be caused by nested fragments within either a union or interface.

@vasilich6107
Copy link
Collaborator

@jjoelson you can apply the workaround that I suggested in my previous comment

@jjoelson
Copy link

jjoelson commented Oct 8, 2021

@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.

@cody1024d
Copy link

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

@vasilich6107
Copy link
Collaborator

@cody1024d unfortunately there is no solution for now except the reorganizing fragments structure

@cody1024d
Copy link

@vasilich6107 No problem. It is not the end of the world! Thank you for this awesome project!

@apackin
Copy link

apackin commented Mar 28, 2022

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?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants