Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vitest + graphql + @graphql-tools/mock causes duplicate graphql error to be thrown #4605

Closed
6 tasks done
jkepps opened this issue Nov 28, 2023 · 6 comments
Closed
6 tasks done

Comments

@jkepps
Copy link

jkepps commented Nov 28, 2023

Describe the bug

When I try to add mocks to a graphql schema I get the following error message:

Error: Cannot use GraphQLSchema "{ __validationErrors: undefined, description: undefined, extensions: {}, astNode: undefined, extensionASTNodes: [], _queryType: Query, _mutationType: Mutation, _subscriptionType: null, _directives: [@deprecated, @include, @requireAuth, @requireDashboardUser, @requireMember, @skip, @specifiedBy, @translate], _typeMap: { AccountStatus: AccountStatus, ActivationCodeInput: ActivationCodeInput, ActiveStreaks: ActiveStreaks, AddDashboardUserToChannelResponse: AddDashboardUserToChannelResponse, AppVersion: AppVersion, AssignPeerInput: AssignPeerInput, AttendedOnlineMeeting: AttendedOnlineMeeting, Audit: Audit, AutomatedOutreachMessage: AutomatedOutreachMessage, AutomatedOutreachMessageInput: AutomatedOutreachMessageInput, AutomatedOutreachMessageMutationResponse: AutomatedOutreachMessageMutationResponse, AwayMessage: AwayMessage, AwayMessageInput: AwayMessageInput, BARC10: BARC10, BHConcernsInput: BHConcernsInput, Barc10MutationResponse: Barc10MutationResponse, Barc10Question: Barc10Question, Barc10Response: Barc10Response, Barc10ResponseInput: Barc10ResponseInput, Barc10Survey: Barc10Survey, Barc10V3Input: Barc10V3Input, BeginCheckoutInput: BeginCheckoutInput, BeginCheckoutResponse: BeginCheckoutResponse, BehavioralHealthConcern: BehavioralHealthConcern, BehavioralHealthProfile: BehavioralHealthProfile, Boolean: Boolean, Brand: Brand, CancelCheckoutResponse: CancelCheckoutResponse, Category: Category, CategoryGroup: CategoryGroup, Challenge: Challenge, ChallengeGoalType: ChallengeGoalType, ChallengeStructure: ChallengeStructure, ChangePasswordInput: ChangePasswordInput, CheckMutationResponse: CheckMutationResponse, Checkin: Checkin, CheckinLocation: CheckinLocation, CheckinLocationInput: CheckinLocationInput, CheckinResponse: CheckinResponse, Checkout: Checkout, ConcernInput: ConcernInput, Contract: Contract, ContractInput: ContractInput, ContractMutationResponse: ContractMutationResponse, ContractResponse: ContractResponse, ContractType: ContractType, CreateAccountMutationResponse: CreateAccountMutationResponse, CreateAccountV5Input: CreateAccountV5Input, CreateBulkRoutineV2Input: CreateBulkRoutineV2Input, CreateBulkRoutineV2Response: CreateBulkRoutineV2Response, CreateCheckinInput: CreateCheckinInput, CreateDashboardUserInput: CreateDashboardUserInput, CreateDashboardUserResponse: CreateDashboardUserResponse, CreateFeatureInput: CreateFeatureInput, CreateFeatureResponse: CreateFeatureResponse, CreateRedeemedRewardInput: CreateRedeemedRewardInput, CreateRewardsCodeInput: CreateRewardsCodeInput, CreateRewardsCodesInput: CreateRewardsCodesInput, CreateRewardsCodesResponse: CreateRewardsCodesResponse, CreateRewardsPlanInput: CreateRewardsPlanInput, CreateRoutineV2Input: CreateRoutineV2Input, CreateSubscriptionInput: CreateSubscriptionInput, CreateTreatmentProviderInput: CreateTreatmentProviderInput, CurrentStreak: CurrentStreak, DashboardNotification: DashboardNotification, DashboardNotificationEvent: DashboardNotificationEvent, DashboardUser: DashboardUser, DashboardUserResponse: DashboardUserResponse, Date: Date, DateTime: DateTime, DeleteAccountInput: DeleteAccountInput, DeleteAccountResponse: DeleteAccountResponse, DeleteCheckinInput: DeleteCheckinInput, DeleteCheckinResponse: DeleteCheckinResponse, DeleteDeviceInput: DeleteDeviceInput, DeleteDeviceResponse: DeleteDeviceResponse, DeleteRecurrenceInputV2: DeleteRecurrenceInputV2, DeleteRecurrenceMutationResponse: DeleteRecurrenceMutationResponse, DeleteRoutineMutationResponse: DeleteRoutineMutationResponse, DeleteRoutineV2Input: DeleteRoutineV2Input, DeletedMessage: DeletedMessage, DestroyFeatureInput: DestroyFeatureInput, DestroyFeatureResponse: DestroyFeatureResponse, DistributionMethod: DistributionMethod, EarnedReward: EarnedReward, EditRewardsPlanInput: EditRewardsPlanInput, EmailAttendanceReportInput: EmailAttendanceReportInput, EmailAttendanceReportResponse: EmailAttendanceReportResponse, Engagement: Engagement, EngagementInput: EngagementInput, EngagementMutationResponse: EngagementMutationResponse, EngagementResponse: EngagementResponse, EngagementType: EngagementType, ExperiencingConcernsResponse: ExperiencingConcernsResponse, Feature: Feature, FeatureOverride: FeatureOverride, FeatureRetireInput: FeatureRetireInput, FeatureRolloutInput: FeatureRolloutInput, FixedItem: FixedItem, Float: Float, Gender: Gender, GetClaimCodeInput: GetClaimCodeInput, GetClaimCodeResponse: GetClaimCodeResponse, GratitudeList: GratitudeList, GratitudeListInput: GratitudeListInput, GratitudeListMutationResponse: GratitudeListMutationResponse, GratitudeListResponse: GratitudeListResponse, HealthPlan: HealthPlan, HealthPlanInfo: HealthPlanInfo, ID: ID, InsuranceProfileInput: InsuranceProfileInput, Int: Int, Intake: Intake, IntakeEngagementFrequencyInterval: IntakeEngagementFrequencyInterval, IntakeInput: IntakeInput, Item: Item, Location: Location, MarkDashboardNotificationsAsSeenMutationResponse: MarkDashboardNotificationsAsSeenMutationResponse, MarkEarnedRewardsAsSeenResponse: MarkEarnedRewardsAsSeenResponse, Member: Member, MemberBenefits: MemberBenefits, MemberBenefitsFilters: MemberBenefitsFilters, MemberBenefitsMutationResponse: MemberBenefitsMutationResponse, MemberBenefitsResponse: MemberBenefitsResponse, MemberMutationResponse: MemberMutationResponse, MemberPronounInput: MemberPronounInput, MemberResponse: MemberResponse, MemberSubstanceInput: MemberSubstanceInput, Messaging: Messaging, MessagingBenefitStatus: MessagingBenefitStatus, Mutation: Mutation, MutationResponse: MutationResponse, NextStandardSurvey: NextStandardSurvey, OkToContactInput: OkToContactInput, Order: Order, Override: Override, PaidSubscription: PaidSubscription, PeerMatchSurvey: PeerMatchSurvey, PeerMatchSurveyInput: PeerMatchSurveyInput, PeerSupportArea: PeerSupportArea, PeerSupportQuestionnaire: PeerSupportQuestionnaire, PeerSupportQuestionnaireInput: PeerSupportQuestionnaireInput, Price: Price, ProblematicSubstance: ProblematicSubstance, PromoCode: PromoCode, PromoCodeMutationResponse: PromoCodeMutationResponse, Pronoun: Pronoun, PublicMeeting: PublicMeeting, PublicMeetingType: PublicMeetingType, PublicOnlineMeeting: PublicOnlineMeeting, PublicOnlineMeetingV3: PublicOnlineMeetingV3, PublicOnlineMeetings: PublicOnlineMeetings, PublicOnlineMeetingsV3: PublicOnlineMeetingsV3, Query: Query, QueryByField: QueryByField, QueryChallengesInput: QueryChallengesInput, QueryChallengesResponse: QueryChallengesResponse, QueryDashboardNotificationsInput: QueryDashboardNotificationsInput, QueryDashboardNotificationsResponse: QueryDashboardNotificationsResponse, QueryEngagementsInput: QueryEngagementsInput, QueryEngagementsResponse: QueryEngagementsResponse, QueryMembersInput: QueryMembersInput, QueryMembersOrderBy: QueryMembersOrderBy, QueryMembersResponse: QueryMembersResponse, QueryParams: QueryParams, QueryRedeemedRewardsInput: QueryRedeemedRewardsInput, QueryRedeemedRewardsResponse: QueryRedeemedRewardsResponse, QueryResponse: QueryResponse, QueryStandardSurveysInput: QueryStandardSurveysInput, QueryStandardSurveysResponse: QueryStandardSurveysResponse, QueryWellnessGoalsInput: QueryWellnessGoalsInput, ROIStatus: ROIStatus, RecurrenceV2: RecurrenceV2, RecurrenceV3: RecurrenceV3, RedeemedReward: RedeemedReward, RegisterDeviceTokenInput: RegisterDeviceTokenInput, RegisterDeviceTokenResponse: RegisterDeviceTokenResponse, RegisterLastActiveInput: RegisterLastActiveInput, RegisterLastActiveResponse: RegisterLastActiveResponse, ReleaseOfInformation: ReleaseOfInformation, ReleaseOfInformationInput: ReleaseOfInformationInput, ReleaseOfInformationMutationResponse: ReleaseOfInformationMutationResponse, ReleaseOfInformationResponse: ReleaseOfInformationResponse, RemoveDashboardUserFromChannelResponse: RemoveDashboardUserFromChannelResponse, RenewMessagingSessionTokenResponse: RenewMessagingSessionTokenResponse, RequestDashboardPasswordResetResponse: RequestDashboardPasswordResetResponse, RequestEmailVerificationInput: RequestEmailVerificationInput, RequestPhoneVerificationInput: RequestPhoneVerificationInput, RequestSMSVerificationCodeInput: RequestSMSVerificationCodeInput, RequestVerificationResponse: RequestVerificationResponse, ResetPasswordInput: ResetPasswordInput, ResetPasswordMutationResponse: ResetPasswordMutationResponse, ResetPasswordResponse: ResetPasswordResponse, RewardCredentialsInput: RewardCredentialsInput, RewardCredentialsResponse: RewardCredentialsResponse, RewardsCode: RewardsCode, RewardsCodeMutationResponse: RewardsCodeMutationResponse, RewardsCodeResponse: RewardsCodeResponse, RewardsCodesInput: RewardsCodesInput, RewardsCodesMutationResponse: RewardsCodesMutationResponse, RewardsCodesOrderBy: RewardsCodesOrderBy, RewardsCodesResponse: RewardsCodesResponse, RewardsPlan: RewardsPlan, RewardsPlanMutationResponse: RewardsPlanMutationResponse, RewardsPlanResponse: RewardsPlanResponse, RewardsPlanSegment: RewardsPlanSegment, RewardsPlanSegmentInput: RewardsPlanSegmentInput, Role: Role, RolloutPhase: RolloutPhase, Routine: Routine, RoutineCategoryGroup: RoutineCategoryGroup, RoutineCreationInfo: RoutineCreationInfo, RoutineCreationRequirement: RoutineCreationRequirement, RoutineLocationInput: RoutineLocationInput, RoutineOrigin: RoutineOrigin, RoutineQueryInput: RoutineQueryInput, RoutineResponse: RoutineResponse, RoutineStatusType: RoutineStatusType, RoutineType: RoutineType, RoutinesInput: RoutinesInput, SUDConcernsInput: SUDConcernsInput, SUDQuestionInput: SUDQuestionInput, SUDQuestionResponse: SUDQuestionResponse, SendMessageToMembersInput: SendMessageToMembersInput, SendMessageToMembersResponse: SendMessageToMembersResponse, Session: Session, SessionResponse: SessionResponse, SessionToken: SessionToken, SetAccountStatusInput: SetAccountStatusInput, SetAccountStatusMutationResponse: SetAccountStatusMutationResponse, SetRewardsEnabledInput: SetRewardsEnabledInput, SetRewardsEnabledResponse: SetRewardsEnabledResponse, SetRoutineStatusInput: SetRoutineStatusInput, SetRoutineStatusResponse: SetRoutineStatusResponse, SignInDashboardUserInput: SignInDashboardUserInput, SignInDashboardUserResponse: SignInDashboardUserResponse, SignInDashboardUserResponseV2: SignInDashboardUserResponseV2, SignInInput: SignInInput, SignInResponse: SignInResponse, SignInWithPhoneNumberInput: SignInWithPhoneNumberInput, SignInWithPhoneNumberResponse: SignInWithPhoneNumberResponse, SignOutInput: SignOutInput, SignOutResponse: SignOutResponse, SocialSupportSystemResponse: SocialSupportSystemResponse, StandardSurveyInput: StandardSurveyInput, StandardSurveyV2: StandardSurveyV2, Stats: Stats, String: String, SubscriptionMutationResponse: SubscriptionMutationResponse, SubscriptionStatus: SubscriptionStatus, SupportedHealthPlan: SupportedHealthPlan, SupportivePerson: SupportivePerson, SupportivePersonInput: SupportivePersonInput, TimeTravelInput: TimeTravelInput, TreatmentProvider: TreatmentProvider, TreatmentProviderMutationResponse: TreatmentProviderMutationResponse, UpdateAwayMessageInput: UpdateAwayMessageInput, UpdateBehavioralHealthProfileV2Input: UpdateBehavioralHealthProfileV2Input, UpdateBrandKeysInput: UpdateBrandKeysInput, UpdateDashboardUserInput: UpdateDashboardUserInput, UpdateDashboardUserResponse: UpdateDashboardUserResponse, UpdateEligibilityInput: UpdateEligibilityInput, UpdateEmailInput: UpdateEmailInput, UpdateEmailResponse: UpdateEmailResponse, UpdateEngagedInput: UpdateEngagedInput, UpdateEngagedResponse: UpdateEngagedResponse, UpdateFeatureOverridesInput: UpdateFeatureOverridesInput, UpdateFeatureOverridesResponse: UpdateFeatureOverridesResponse, UpdateMaxPotentialRewardsInput: UpdateMaxPotentialRewardsInput, UpdateMemberTreatmentProviderInput: UpdateMemberTreatmentProviderInput, UpdateMemberV3Input: UpdateMemberV3Input, UpdateMembersBenefitsInput: UpdateMembersBenefitsInput, UpdateNotesInput: UpdateNotesInput, UpdatePasswordInput: UpdatePasswordInput, UpdatePasswordMutationResponse: UpdatePasswordMutationResponse, UpdatePeerProfileInput: UpdatePeerProfileInput, UpdatePhoneNumberInput: UpdatePhoneNumberInput, UpdatePhoneNumberResponse: UpdatePhoneNumberResponse, UpdateProblematicSubstancesV2Input: UpdateProblematicSubstancesV2Input, UpdateRewardsCodeInput: UpdateRewardsCodeInput, UpdateRewardsCodesInput: UpdateRewardsCodesInput, UpdateRewardsCodesTreatmentProviderInput: UpdateRewardsCodesTreatmentProviderInput, UpdateRoutineMutationResponse: UpdateRoutineMutationResponse, UpdateRoutineV3Input: UpdateRoutineV3Input, UpdateSubscriptionPriceInput: UpdateSubscriptionPriceInput, UpdateTimeTravelResponse: UpdateTimeTravelResponse, UpdateTreatmentProviderInput: UpdateTreatmentProviderInput, UpgradeAccountInput: UpgradeAccountInput, UpgradeAccountMutationResponse: UpgradeAccountMutationResponse, UpgradeByAdminInput: UpgradeByAdminInput, UpsertFeatureOverrideInput: UpsertFeatureOverrideInput, ValidateActivationCodeResponse: ValidateActivationCodeResponse, ValidateOnboardingCodeInput: ValidateOnboardingCodeInput, ValidateOnboardingCodeMutationResponse: ValidateOnboardingCodeMutationResponse, ValidateOnboardingCodeResponse: ValidateOnboardingCodeResponse, ValidatePasswordResetCodeInput: ValidatePasswordResetCodeInput, ValidatePasswordResetCodeResponse: ValidatePasswordResetCodeResponse, ValidatePromoCodeInput: ValidatePromoCodeInput, ValidationError: ValidationError, ValidationErrors: ValidationErrors, ValueType: ValueType, VariableItem: VariableItem, VerifyChangeCredentialInput: VerifyChangeCredentialInput, VerifyChangeCredentialMutationResponse: VerifyChangeCredentialMutationResponse, VerifyChangeCredentialResponse: VerifyChangeCredentialResponse, VerifyEmailInput: VerifyEmailInput, VerifyEmailMutationResponse: VerifyEmailMutationResponse, WecWorksConnectionType: WecWorksConnectionType, WellnessGoal: WellnessGoal, WellnessGoalDomain: WellnessGoalDomain, WellnessGoalInput: WellnessGoalInput, WellnessGoalMutationResponse: WellnessGoalMutationResponse, WellnessGoalPriorityLevel: WellnessGoalPriorityLevel, WellnessGoalResponse: WellnessGoalResponse, WellnessGoalStatus: WellnessGoalStatus, WorkHours: WorkHours, WorkHoursInput: WorkHoursInput, __Directive: __Directive, __DirectiveLocation: __DirectiveLocation, __EnumValue: __EnumValue, __Field: __Field, __InputValue: __InputValue, __Schema: __Schema, __Type: __Type, __TypeKind: __TypeKind, barc10Answer: barc10Answer }, _subTypeMap: {}, _implementationsMap: { MutationResponse: [Object], Item: [Object], QueryResponse: [Object] } }" from another module or realm.

Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.

https://yarnpkg.com/en/docs/selective-version-resolutions

Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.

This is the source code that works perfectly fine with Jest:

import { buildClientSchema } from "graphql";
import { it, expect } from "vitest";
import introspectionResult from "./graphql.schema.json";
import { addMocksToSchema } from "@graphql-tools/mock";

const schema = buildClientSchema(introspectionResult);

addMocksToSchema({ schema });

it("runs", () => {
  expect(1 + 1).toBe(2);
});

Reproduction

https://codesandbox.io/p/devbox/objective-danilo-8qwtnh?file=%2Findex.test.ts%3A13%2C1

System Info

System:
    OS: macOS 14.0
    CPU: (12) arm64 Apple M2 Max
    Memory: 1.79 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.16.0 - ~/.asdf/installs/nodejs/18.16.0/bin/node
    Yarn: 3.3.1 - ~/.asdf/installs/nodejs/18.16.0/bin/yarn
    npm: 9.5.1 - ~/.asdf/plugins/nodejs/shims/npm
  Browsers:
    Brave Browser: 119.1.60.118
    Safari: 17.0
  npmPackages:
    @vitejs/plugin-react: ^4.1.0 => 4.1.0
    @vitest/coverage-v8: ^0.34.6 => 0.34.6
    vite: ^4.5.0 => 4.5.0
    vitest: ^0.34.6 => 0.34.6

Used Package Manager

yarn

Validations

@markusv
Copy link

markusv commented Dec 6, 2023

I had the same issue. Seems to be related to v1 of vitest. Everything is ok in v 0.34.6

@jkepps
Copy link
Author

jkepps commented Dec 6, 2023

@markusv i'm using vitest 0.34.6 both in my project and in the code sandbox 🙁

@EvHaus
Copy link
Contributor

EvHaus commented Dec 7, 2023

This started happening for me after the vitest@1.0.1 upgrade as well. It was not an issue with vitest@0.34.6. I tried the various solutions in vitejs/vite#7879 and none of them worked.

@jkepps
Copy link
Author

jkepps commented Dec 8, 2023

looks like adding this line to the vite config did the trick in vitest 0.34.6 and 1.0.2

resolve: { alias: { graphql: "graphql/index.js" } },

@jkepps jkepps closed this as completed Dec 8, 2023
@amccarthy1
Copy link

This happened for me too. The vite config trick worked, but I'm using yarn workspaces and have a ton of configs to keep updated with this.

I'm glad there's a workaround, but any idea why this would happen to begin with? It seems like the config is likely masking a dependency resolution bug either with vitest or graphql. I don't get this issue running the same type of tests with jest or earlier versions of vitest.

@EvHaus
Copy link
Contributor

EvHaus commented Dec 8, 2023

The resolve: { alias: { graphql: "graphql/index.js" } } solution fixes the original issue, but introduces new errors when importing other modules from the graphql package.

// This
import { print } from 'graphql/language/printer';

// Now fails with
Error: Failed to resolve import "graphql/language/printer" from "myfile.ts". Does the file exist?

I had to also add aliases for all the related imports too (in the right priority order):

resolve: {
  alias: {
   'graphql/language/printer': 'graphql/language/printer.js',
   'graphql/language': 'graphql/language/index.js',
    graphql: 'graphql/index.js'
  },
}

@github-actions github-actions bot locked and limited conversation to collaborators Jan 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants