Last active
March 14, 2022 15:39
-
-
Save ali-ehmed/3db3558c164e8cace7937c01c01c9571 to your computer and use it in GitHub Desktop.
RSpec - Stub Graphql Client Adapter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'graphql/client' | |
require 'graphql/client/http' | |
module PlatformGraphqlClient | |
# Configure GraphQL endpoint using the basic HTTP network adapter. | |
HTTP = GraphQL::Client::HTTP.new('http://localhost:3001/api/graphql') do | |
# def headers(context) | |
# # Optionally set any HTTP headers | |
# { "Access-Token": "user-access-token" } | |
# end | |
end | |
begin | |
# Fetch latest schema on init, this will make a network request | |
SCHEMA = GraphQL::Client.load_schema(HTTP) | |
# However, it's smart to dump this to a JSON file and load from disk | |
# | |
# Run it from a script or rake task | |
# GraphQL::Client.dump_schema(CoreGraphql::HTTP, "path/to/schema.json") | |
# | |
# SCHEMA = GraphQL::Client.load_schema("path/to/schema.json") | |
# | |
CLIENT = GraphQL::Client.new(schema: SCHEMA, execute: HTTP) | |
rescue Errno::ECONNREFUSED | |
raise 'Graphql could not load schema. The Host URL is invalid/empty.' | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Stubbed Adapter for Graphqal Client object | |
class StubGraphqlClientAdapter | |
def self.execute(document: _, operation_name: _, variables: _, context: _) | |
custom_response = StubGraphqlCustomResponseGenerator.instance.notify_observers(operation_name) | |
StubGraphqlCustomResponseGenerator.instance.changed(true) if StubGraphqlCustomResponseGenerator.instance.count_observers > 0 | |
return custom_response if custom_response | |
case operation_name | |
when 'ValidateUserEmailQuery' | |
{ data: { validateUserExistence: false } }.with_indifferent_access | |
when 'CreateUserQuery' | |
{ data: { createUser: variables } }.with_indifferent_access | |
else | |
{ data: {} } | |
end | |
end | |
end | |
### CUSTOM STUBBED RESPONSE DURING TEST CASES ### | |
# If you want to generate a custom response in your specifc RSpec spec for a Graphql Query/Mutation you can use StubGraphqlCustomResponseGenerator in RSpec before hooks, which is singleton btw, and set custom mocked responses. | |
# All it does is allow you to subscribe multiple observers (which are objects of StubGraphqlCustomResponse) and inside `StubGraphqlCustomResponse.execute` | |
# it publishes those observers. You can add multiple observers at time, they'll be published sequentially everytime #execute is called. | |
# | |
# Usage Examples | |
# | |
# before do | |
# StubGraphqlCustomResponseGenerator.instance.add_response( | |
# StubGraphqlCustomResponse.new('validateUserExistence', { data: { validateUserExistence: true } }.with_indifferent_access }) | |
# ) | |
# StubGraphqlCustomResponseGenerator.instance.add_response( | |
# StubGraphqlCustomResponse.new('CreateUserQuery', { { errors: [ { message: "can't be blank ", extensions: { code: "USER_INPUT_ERROR", attribute: "password" } }] }.with_indifferent_access }) | |
# ) | |
# end | |
# | |
# it 'should see errors from third party' do | |
# # Your test definition of a method that will hit Graphql api.... | |
# end | |
# | |
class StubGraphqlCustomResponseGenerator | |
include Singleton | |
include Observable | |
def add_observer(observer) | |
super(observer) | |
changed(true) | |
end | |
alias_method :add_response, :add_observer | |
def notify_observers(*arg) | |
if defined? @observer_state and @observer_state | |
if defined? @observer_peers | |
@observer_state = false | |
# Always return executed response from StubGraphqlCustomResponse#update and reject nils | |
@observer_peers.map do |k, v| | |
k.send(v, *arg) | |
end.compact.first | |
end | |
end | |
end | |
alias_method :collect_response, :notify_observers | |
end | |
class StubGraphqlCustomResponse | |
def initialize(key, response) | |
@key = key | |
@response = response | |
end | |
def update(operation_name) | |
if @key == operation_name | |
StubGraphqlCustomResponseGenerator.instance.delete_observer(self) | |
@response | |
end | |
end | |
end | |
## Finally set `StubGraphqlClientAdapter` | |
# | |
# Reset your default Adapter (GraphQL::Client::HTTP) object in your initializer (I've set inside HTTP constant) with the `StubGraphqlClientAdapter` | |
PlatformGraphqlClient.remove_const('HTTP') | |
PlatformGraphqlClient.const_set('HTTP', StubGraphqlClientAdapter) | |
# OR | |
# Reset your default Client object in your initializer (I've set inside CLIENT constant) with a new Client object that can use | |
# the same (default) scehema but for execution, it should use `StubGraphqlClientAdapter` class instead of GraphQL::Client::HTTP. | |
PlatformGraphqlClient.remove_const('CLIENT') | |
PlatformGraphqlClient.const_set('CLIENT', GraphQL::Client.new(schema: PlatformGraphqlClient::SCHEMA, execute: StubGraphqlClientAdapter)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Place above file in your
spec
directory.