UNPKG

relay-test-utils

Version:

Utilities for testing Relay applications.

323 lines (322 loc) • 14.3 kB
'use strict'; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"]; var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); var areEqual = require("fbjs/lib/areEqual"); var invariant = require('invariant'); var _require = require('relay-runtime'), Environment = _require.Environment, Network = _require.Network, Observable = _require.Observable, QueryResponseCache = _require.QueryResponseCache, RecordSource = _require.RecordSource, Store = _require.Store, createOperationDescriptor = _require.createOperationDescriptor, getRequest = _require.getRequest; var MAX_SIZE = 10; var MAX_TTL = 5 * 60 * 1000; function mockInstanceMethod(object, key) { object[key] = jest.fn(object[key].bind(object)); } function mockDisposableMethod(object, key) { var fn = object[key].bind(object); object[key] = jest.fn(function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var disposable = fn.apply(void 0, args); var dispose = jest.fn(function () { return disposable.dispose(); }); object[key].mock.dispose = dispose; return { dispose: dispose }; }); var mockClear = object[key].mockClear.bind(object[key]); object[key].mockClear = function () { mockClear(); object[key].mock.dispose = null; }; } function mockObservableMethod(object, key) { var fn = object[key].bind(object); var subscriptions = []; object[key] = jest.fn(function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return fn.apply(void 0, args)["do"]({ start: function start(subscription) { subscriptions.push(subscription); } }); }); object[key].mock.subscriptions = subscriptions; var mockClear = object[key].mockClear.bind(object[key]); object[key].mockClear = function () { mockClear(); object[key].mock.subscriptions = []; }; } function createMockEnvironment(config) { var _config$store, _global, _global$process, _global$process$env; var store = (_config$store = config === null || config === void 0 ? void 0 : config.store) !== null && _config$store !== void 0 ? _config$store : new Store(new RecordSource()); var cache = new QueryResponseCache({ size: MAX_SIZE, ttl: MAX_TTL }); var pendingRequests = []; var pendingOperations = []; var queuePendingOperation = function queuePendingOperation(query, variables) { var operationDescriptor = createOperationDescriptor(getRequest(query), variables); pendingOperations = pendingOperations.concat([operationDescriptor]); }; var resolversQueue = []; var queueOperationResolver = function queueOperationResolver(resolver) { resolversQueue = resolversQueue.concat([resolver]); }; var execute = function execute(request, variables, cacheConfig) { var id = request.id, text = request.text; var cacheID = id !== null && id !== void 0 ? id : text; var cachedPayload = null; if (((cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.force) == null || (cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.force) === false) && cacheID != null) { cachedPayload = cache.get(cacheID, variables); } if (cachedPayload !== null) { return Observable.from(cachedPayload); } var currentOperation = pendingOperations.find(function (op) { return op.request.node.params === request && areEqual(op.request.variables, variables); }); if (currentOperation != null && resolversQueue.length > 0) { var currentResolver = resolversQueue[0]; var result = currentResolver(currentOperation); if (result != null) { resolversQueue = resolversQueue.filter(function (res) { return res !== currentResolver; }); pendingOperations = pendingOperations.filter(function (op) { return op !== currentOperation; }); if (result instanceof Error) { return Observable.create(function (sink) { sink.error(result); }); } else { return Observable.from(result); } } } return Observable.create(function (sink) { var nextRequest = { request: request, variables: variables, cacheConfig: cacheConfig, sink: sink }; pendingRequests = pendingRequests.concat([nextRequest]); return function () { pendingRequests = pendingRequests.filter(function (pending) { return !areEqual(pending, nextRequest); }); var currentOperation = pendingOperations.find(function (op) { return areEqual(op.request.node.params, request) && areEqual(op.request.variables, variables); }); pendingOperations = pendingOperations.filter(function (op) { return op !== currentOperation; }); }; }); }; function getConcreteRequest(input) { if (input.kind === 'Request') { var request = input; return request; } else { var operationDescriptor = input; !pendingOperations.includes(operationDescriptor) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernMockEnvironment: Operation "%s" was not found in the list of pending operations', operationDescriptor.request.node.operation.name) : invariant(false) : void 0; return operationDescriptor.request.node; } } function getRequests(input) { var concreteRequest; var operationDescriptor; if (input.kind === 'Request') { concreteRequest = input; } else { operationDescriptor = input; concreteRequest = operationDescriptor.request.node; } var foundRequests = pendingRequests.filter(function (pending) { if (!areEqual(pending.request, concreteRequest.params)) { return false; } if (operationDescriptor) { return areEqual(operationDescriptor.request.variables, pending.variables); } else { return true; } }); !foundRequests.length ? process.env.NODE_ENV !== "production" ? invariant(false, 'MockEnvironment: Cannot respond to request, it has not been requested yet.') : invariant(false) : void 0; foundRequests.forEach(function (foundRequest) { !foundRequest.sink ? process.env.NODE_ENV !== "production" ? invariant(false, 'MockEnvironment: Cannot respond to `%s`, it has not been requested yet.', concreteRequest.params.name) : invariant(false) : void 0; }); return foundRequests; } function ensureValidPayload(payload) { !(typeof payload === 'object' && payload !== null && payload.hasOwnProperty('data')) ? process.env.NODE_ENV !== "production" ? invariant(false, 'MockEnvironment(): Expected payload to be an object with a `data` key.') : invariant(false) : void 0; return payload; } var cachePayload = function cachePayload(request, variables, payload) { var _getConcreteRequest$p = getConcreteRequest(request).params, id = _getConcreteRequest$p.id, text = _getConcreteRequest$p.text; var cacheID = id !== null && id !== void 0 ? id : text; !(cacheID != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'CacheID should not be null') : invariant(false) : void 0; cache.set(cacheID, variables, payload); }; var clearCache = function clearCache() { cache.clear(); }; var isLoading = function isLoading(request, variables, cacheConfig) { return pendingRequests.some(function (pending) { return areEqual(pending.request, getConcreteRequest(request).params) && areEqual(pending.variables, variables) && areEqual(pending.cacheConfig, cacheConfig !== null && cacheConfig !== void 0 ? cacheConfig : {}); }); }; var reject = function reject(request, error) { var rejectError = typeof error === 'string' ? new Error(error) : error; getRequests(request).forEach(function (foundRequest) { var sink = foundRequest.sink; !(sink !== null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Sink should be defined.') : invariant(false) : void 0; sink.error(rejectError); }); }; var nextValue = function nextValue(request, payload) { getRequests(request).forEach(function (foundRequest) { var sink = foundRequest.sink; !(sink !== null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Sink should be defined.') : invariant(false) : void 0; sink.next(ensureValidPayload(payload)); }); }; var complete = function complete(request) { getRequests(request).forEach(function (foundRequest) { var sink = foundRequest.sink; !(sink !== null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Sink should be defined.') : invariant(false) : void 0; sink.complete(); }); }; var resolve = function resolve(request, response) { getRequests(request).forEach(function (foundRequest) { var sink = foundRequest.sink; !(sink !== null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Sink should be defined.') : invariant(false) : void 0; var payloads = Array.isArray(response) ? response : [response]; payloads.forEach(function (payload) { sink.next(ensureValidPayload(payload)); }); sink.complete(); }); }; var getMostRecentOperation = function getMostRecentOperation() { var mostRecentOperation = pendingOperations[pendingOperations.length - 1]; !(mostRecentOperation != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernMockEnvironment: There are no pending operations in the list') : invariant(false) : void 0; return mostRecentOperation; }; var findOperation = function findOperation(findFn) { var pendingOperation = pendingOperations.find(findFn); !(pendingOperation != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernMockEnvironment: Operation was not found in the list of pending operations') : invariant(false) : void 0; return pendingOperation; }; var environment = new Environment((0, _objectSpread2["default"])({ configName: 'RelayModernMockEnvironment', network: Network.create(execute, execute), store: store }, config)); var createExecuteProxy = function createExecuteProxy(env, fn) { return function () { for (var _len3 = arguments.length, argumentsList = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { argumentsList[_key3] = arguments[_key3]; } var operation = argumentsList[0].operation; pendingOperations = pendingOperations.concat([operation]); return fn.apply(env, argumentsList); }; }; environment.execute = createExecuteProxy(environment, environment.execute); environment.executeSubscription = createExecuteProxy(environment, environment.executeSubscription); environment.executeWithSource = createExecuteProxy(environment, environment.executeWithSource); environment.executeMutation = createExecuteProxy(environment, environment.executeMutation); if (((_global = global) === null || _global === void 0 ? void 0 : (_global$process = _global.process) === null || _global$process === void 0 ? void 0 : (_global$process$env = _global$process.env) === null || _global$process$env === void 0 ? void 0 : _global$process$env.NODE_ENV) === 'test') { mockDisposableMethod(environment, 'applyUpdate'); mockInstanceMethod(environment, 'commitPayload'); mockInstanceMethod(environment, 'getStore'); mockInstanceMethod(environment, 'lookup'); mockInstanceMethod(environment, 'check'); mockDisposableMethod(environment, 'subscribe'); mockDisposableMethod(environment, 'retain'); mockObservableMethod(environment, 'execute'); mockObservableMethod(environment, 'executeSubscription'); mockObservableMethod(environment, 'executeWithSource'); mockObservableMethod(environment, 'executeMutation'); mockInstanceMethod(store, 'getSource'); mockInstanceMethod(store, 'lookup'); mockInstanceMethod(store, 'notify'); mockInstanceMethod(store, 'publish'); mockDisposableMethod(store, 'retain'); mockDisposableMethod(store, 'subscribe'); } var mock = { cachePayload: cachePayload, clearCache: clearCache, isLoading: isLoading, reject: reject, resolve: resolve, nextValue: nextValue, complete: complete, getMostRecentOperation: getMostRecentOperation, resolveMostRecentOperation: function resolveMostRecentOperation(payload) { var operation = getMostRecentOperation(); var data = typeof payload === 'function' ? payload(operation) : payload; return resolve(operation, data); }, rejectMostRecentOperation: function rejectMostRecentOperation(error) { var operation = getMostRecentOperation(); var rejector = typeof error === 'function' ? error(operation) : error; return reject(operation, rejector); }, findOperation: findOperation, queuePendingOperation: queuePendingOperation, getAllOperations: function getAllOperations() { return pendingOperations; }, queueOperationResolver: queueOperationResolver }; environment.mock = mock; environment.mockClear = function () { var _store$getSource$clea, _store$getSource; environment.applyUpdate.mockClear(); environment.commitPayload.mockClear(); environment.getStore.mockClear(); environment.lookup.mockClear(); environment.check.mockClear(); environment.subscribe.mockClear(); environment.retain.mockClear(); environment.execute.mockClear(); environment.executeMutation.mockClear(); environment.executeSubscription.mockClear(); (_store$getSource$clea = (_store$getSource = store.getSource()).clear) === null || _store$getSource$clea === void 0 ? void 0 : _store$getSource$clea.call(_store$getSource); store.getSource.mockClear(); store.lookup.mockClear(); store.notify.mockClear(); store.publish.mockClear(); store.retain.mockClear(); store.subscribe.mockClear(); cache.clear(); pendingOperations = []; pendingRequests = []; }; return environment; } module.exports = { createMockEnvironment: createMockEnvironment };