From a8e6b8b8ea770c7ba1f9b859cf77065aafcfbb6a Mon Sep 17 00:00:00 2001 From: Eric Burel Date: Thu, 27 Sep 2018 10:22:22 +0200 Subject: [PATCH] cleanup test, import, modules, wrap registerWatechedMutation with isClient --- .meteor/release | 2 +- .meteor/versions | 6 +- package-lock.json | 104 ++++++++ package.json | 1 + .../lib/modules/default_mutations.js | 231 +++++++++--------- packages/vulcan-core/test/containers.test.js | 20 +- .../lib/client/apollo-client/index.js | 3 + .../lib/client/apollo-client/links/state.js | 4 +- packages/vulcan-lib/lib/client/main.js | 2 +- packages/vulcan-lib/package.js | 9 +- .../test/client/apolloClient.test.js | 53 ++++ packages/vulcan-lib/test/client/index.js | 2 + packages/vulcan-lib/test/index.js | 1 + 13 files changed, 308 insertions(+), 130 deletions(-) create mode 100644 packages/vulcan-lib/lib/client/apollo-client/index.js create mode 100644 packages/vulcan-lib/test/client/apolloClient.test.js create mode 100644 packages/vulcan-lib/test/client/index.js create mode 100644 packages/vulcan-lib/test/index.js diff --git a/.meteor/release b/.meteor/release index 7f956de29..4c71956e2 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@1.7.0.1 +METEOR@1.7.0.5 diff --git a/.meteor/versions b/.meteor/versions index 43e72daa0..416b36950 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -4,7 +4,7 @@ allow-deny@1.1.0 apollo@3.0.0 autoupdate@1.4.0 babel-compiler@7.1.1 -babel-runtime@1.2.2 +babel-runtime@1.2.4 base64@1.0.11 binary-heap@1.0.10 blaze-tools@1.0.10 @@ -21,7 +21,7 @@ ddp-rate-limiter@1.0.7 ddp-server@2.2.0 deps@1.0.12 diff-sequence@1.1.0 -dynamic-import@0.4.1 +dynamic-import@0.4.2 ecmascript@0.11.1 ecmascript-runtime@0.7.0 ecmascript-runtime-client@0.7.1 @@ -48,7 +48,7 @@ minifier-css@1.3.1 minifier-js@2.3.5 minimongo@1.4.4 modern-browsers@0.1.1 -modules@0.12.0 +modules@0.12.2 modules-runtime@0.10.0 mongo@1.5.0 mongo-dev-server@1.1.0 diff --git a/package-lock.json b/package-lock.json index 0eee8ebd5..8a161e0fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6631,6 +6631,100 @@ "prop-types": "^15.5.10" } }, + "react-router-dom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz", + "integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==", + "requires": { + "history": "^4.7.2", + "invariant": "^2.2.4", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.1", + "react-router": "^4.3.1", + "warning": "^4.0.1" + }, + "dependencies": { + "history": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", + "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==", + "requires": { + "invariant": "^2.2.1", + "loose-envify": "^1.2.0", + "resolve-pathname": "^2.2.0", + "value-equal": "^0.4.0", + "warning": "^3.0.0" + }, + "dependencies": { + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "hoist-non-react-statics": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", + "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + } + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "react-router": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", + "integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==", + "requires": { + "history": "^4.7.2", + "hoist-non-react-statics": "^2.5.0", + "invariant": "^2.2.4", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.1", + "warning": "^4.0.1" + } + }, + "warning": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.2.tgz", + "integrity": "sha512-wbTp09q/9C+jJn4KKJfJfoS6VleK/Dti0yqWSm6KMvJ4MRCXFQNapHuJXutJIrWV0Cf4AhTdeIe4qdKHR1+Hug==", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, "react-router-scroll": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/react-router-scroll/-/react-router-scroll-0.4.4.tgz", @@ -6913,6 +7007,11 @@ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", "dev": true }, + "resolve-pathname": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", + "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" + }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", @@ -8044,6 +8143,11 @@ "spdx-expression-parse": "~1.0.0" } }, + "value-equal": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", + "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index ff482f0d1..49b3fc4e9 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "react-redux": "^5.0.6", "react-router": "^3.2.0", "react-router-bootstrap": "^0.24.4", + "react-router-dom": "^4.3.1", "react-router-scroll": "^0.4.4", "react-stripe-checkout": "^2.4.0", "recompose": "^0.26.0", diff --git a/packages/vulcan-core/lib/modules/default_mutations.js b/packages/vulcan-core/lib/modules/default_mutations.js index d7cae9bdb..25784802a 100644 --- a/packages/vulcan-core/lib/modules/default_mutations.js +++ b/packages/vulcan-core/lib/modules/default_mutations.js @@ -4,14 +4,30 @@ Default mutations */ -import { registerCallback, createMutator, updateMutator, deleteMutator, Utils, Connectors, getTypeName, getCollectionName, belongsToSet, addToSet, reorderSet, isInSet, removeFromSet, updateInSet, registerWatchedMutation, Collections } from 'meteor/vulcan:lib'; +import { + registerCallback, + createMutator, + updateMutator, + deleteMutator, + Utils, + Connectors, + getTypeName, + getCollectionName, + belongsToSet, + addToSet, + reorderSet, + isInSet, + removeFromSet, + updateInSet, + registerWatchedMutation, + Collections +} from 'meteor/vulcan:lib'; import Users from 'meteor/vulcan:users'; import isEmpty from 'lodash/isEmpty'; const defaultOptions = { create: true, update: true, upsert: true, delete: true }; -export function getDefaultMutations (options) { - +export function getDefaultMutations(options) { let typeName, collectionName, mutationOptions; if (typeof arguments[0] === 'object') { @@ -25,7 +41,7 @@ export function getDefaultMutations (options) { typeName = getTypeName(collectionName); mutationOptions = { ...defaultOptions, ...arguments[1] }; } - + // register callbacks for documentation purposes registerCollectionCallbacks(typeName, mutationOptions); @@ -65,9 +81,9 @@ export function getDefaultMutations (options) { data, currentUser: context.currentUser, validate: true, - context, + context }); - }, + } }; mutations.create = createMutation; // OpenCRUD backwards compatibility @@ -78,36 +94,36 @@ export function getDefaultMutations (options) { Handle post-mutation updates of the client cache */ - registerWatchedMutation(mutationName, multiQueryName, ({ mutation, query }) => { + if (Meteor.isClient) { + registerWatchedMutation(mutationName, multiQueryName, ({ mutation, query }) => { + // get mongo selector and options objects based on current terms + const terms = query.variables.input.terms; + const collection = Collections.find(c => c.typeName === typeName); + const parameters = collection.getParameters(terms /* apolloClient */); + const { selector, options } = parameters; + let results = query.result; + const document = mutation.result.data[mutationName].data; - // get mongo selector and options objects based on current terms - const terms = query.variables.input.terms; - const collection = Collections.find(c => c.typeName === typeName); - const parameters = collection.getParameters(terms, /* apolloClient */); - const { selector, options } = parameters; - let results = query.result; - const document = mutation.result.data[mutationName].data; - - if (belongsToSet(document, selector)) { - if (!isInSet(results[multiResolverName], document)) { - // make sure document hasn't been already added as this may be called several times - results[multiResolverName] = addToSet(results[multiResolverName], document); + if (belongsToSet(document, selector)) { + if (!isInSet(results[multiResolverName], document)) { + // make sure document hasn't been already added as this may be called several times + results[multiResolverName] = addToSet(results[multiResolverName], document); + } + results[multiResolverName] = reorderSet(results[multiResolverName], options.sort); } - results[multiResolverName] = reorderSet(results[multiResolverName], options.sort); - } - results[multiResolverName].__typename = `Multi${typeName}Output`; + results[multiResolverName].__typename = `Multi${typeName}Output`; - // console.log('// create'); - // console.log(mutation); - // console.log(query); - // console.log(collection); - // console.log(parameters); - // console.log(results); - - return results; - }); + // console.log('// create'); + // console.log(mutation); + // console.log(query); + // console.log(collection); + // console.log(parameters); + // console.log(results); + return results; + }); + } } if (mutationOptions.update) { @@ -137,7 +153,6 @@ export function getDefaultMutations (options) { }, async mutation(root, { selector, data }, context) { - const collection = context[collectionName]; if (isEmpty(selector)) { @@ -146,7 +161,7 @@ export function getDefaultMutations (options) { // get entire unmodified document from database const document = await Connectors.get(collection, selector); - + if (!document) { throw new Error(`Could not find document to update for selector: ${JSON.stringify(selector)}`); } @@ -162,10 +177,9 @@ export function getDefaultMutations (options) { currentUser: context.currentUser, validate: true, context, - document, + document }); - }, - + } }; mutations.update = updateMutation; @@ -177,41 +191,42 @@ export function getDefaultMutations (options) { Handle post-mutation updates of the client cache */ - registerWatchedMutation(mutationName, multiQueryName, ({ mutation, query }) => { + if (Meteor.isClient) { + registerWatchedMutation(mutationName, multiQueryName, ({ mutation, query }) => { + // get mongo selector and options objects based on current terms + const terms = query.variables.input.terms; + const collection = Collections.find(c => c.typeName === typeName); + const parameters = collection.getParameters(terms /* apolloClient */); + const { selector, options } = parameters; + let results = query.result; + const document = mutation.result.data[mutationName].data; - // get mongo selector and options objects based on current terms - const terms = query.variables.input.terms; - const collection = Collections.find(c => c.typeName === typeName); - const parameters = collection.getParameters(terms, /* apolloClient */); - const { selector, options } = parameters; - let results = query.result; - const document = mutation.result.data[mutationName].data; - - if (belongsToSet(document, selector)) { - // edited document belongs to the list - if (!isInSet(results[multiResolverName], document)) { - // if document wasn't already in list, add it - results[multiResolverName] = addToSet(results[multiResolverName], document); + if (belongsToSet(document, selector)) { + // edited document belongs to the list + if (!isInSet(results[multiResolverName], document)) { + // if document wasn't already in list, add it + results[multiResolverName] = addToSet(results[multiResolverName], document); + } else { + // if document was already in the list, update it + results[multiResolverName] = updateInSet(results[multiResolverName], document); + } + results[multiResolverName] = reorderSet(results[multiResolverName], options.sort, selector); } else { - // if document was already in the list, update it - results[multiResolverName] = updateInSet(results[multiResolverName], document); + // if edited doesn't belong to current list anymore (based on view selector), remove it + results[multiResolverName] = removeFromSet(results[multiResolverName], document); } - results[multiResolverName] = reorderSet(results[multiResolverName], options.sort, selector); - } else { - // if edited doesn't belong to current list anymore (based on view selector), remove it - results[multiResolverName] = removeFromSet(results[multiResolverName], document); - } - results[multiResolverName].__typename = `Multi${typeName}Output`; + results[multiResolverName].__typename = `Multi${typeName}Output`; - // console.log('// update'); - // console.log(mutation); - // console.log(query); - // console.log(parameters); - // console.log(results); + // console.log('// update'); + // console.log(mutation); + // console.log(query); + // console.log(parameters); + // console.log(results); - return results; - }); + return results; + }); + } } if (mutationOptions.upsert) { // mutation for upserting a specific document @@ -229,7 +244,7 @@ export function getDefaultMutations (options) { } else { return await collection.options.mutations.create.mutation(root, { data }, context); } - }, + } }; } if (mutationOptions.delete) { @@ -251,11 +266,10 @@ export function getDefaultMutations (options) { // OpenCRUD backwards compatibility return Users.owns(user, document) ? Users.canDo(user, [`${typeName.toLowerCase()}.delete.own`, `${collectionName.toLowerCase()}.remove.own`]) - : Users.canDo(user, [`${typeName.toLowerCase()}.delete.all`, `${collectionName.toLowerCase()}.remove.all`]); + : Users.canDo(user, [`${typeName.toLowerCase()}.delete.all`, `${collectionName.toLowerCase()}.remove.all`]); }, async mutation(root, { selector }, context) { - const collection = context[collectionName]; if (isEmpty(selector)) { @@ -263,7 +277,7 @@ export function getDefaultMutations (options) { } const document = await Connectors.get(collection, selector); - + if (!document) { throw new Error(`Could not find document to delete for selector: ${JSON.stringify(selector)}`); } @@ -276,9 +290,9 @@ export function getDefaultMutations (options) { currentUser: context.currentUser, validate: true, context, - document, + document }); - }, + } }; mutations.delete = deleteMutation; @@ -290,18 +304,20 @@ export function getDefaultMutations (options) { Handle post-mutation updates of the client cache */ - registerWatchedMutation(mutationName, multiQueryName, ({ mutation, query }) => { - let results = query.result; - const document = mutation.result.data[mutationName].data; - results[multiResolverName] = removeFromSet(results[multiResolverName], document); - results[multiResolverName].__typename = `Multi${typeName}Output`; - // console.log('// delete') - // console.log(mutation); - // console.log(query); - // console.log(parameters); - // console.log(results); - return results; - }); + if (Meteor.isClient) { + registerWatchedMutation(mutationName, multiQueryName, ({ mutation, query }) => { + let results = query.result; + const document = mutation.result.data[mutationName].data; + results[multiResolverName] = removeFromSet(results[multiResolverName], document); + results[multiResolverName].__typename = `Multi${typeName}Output`; + // console.log('// delete') + // console.log(mutation); + // console.log(query); + // console.log(parameters); + // console.log(results); + return results; + }); + } } return mutations; @@ -317,11 +333,11 @@ const registerCollectionCallbacks = (typeName, options) => { properties: [ { document: 'The document being inserted' }, { currentUser: 'The current user' }, - { validationErrors: 'An object that can be used to accumulate validation errors' }, + { validationErrors: 'An object that can be used to accumulate validation errors' } ], runs: 'sync', returns: 'document', - description: 'Validate a document before insertion (can be skipped when inserting directly on server).', + description: 'Validate a document before insertion (can be skipped when inserting directly on server).' }); registerCallback({ name: `${typeName}.create.before`, @@ -329,7 +345,7 @@ const registerCollectionCallbacks = (typeName, options) => { properties: [{ currentUser: 'The current user' }], runs: 'sync', returns: 'document', - description: 'Perform operations on a new document before it\'s inserted in the database.', + description: 'Perform operations on a new document before it\'s inserted in the database.' }); registerCallback({ name: `${typeName}.create.after`, @@ -337,18 +353,16 @@ const registerCollectionCallbacks = (typeName, options) => { properties: [{ currentUser: 'The current user' }], runs: 'sync', returns: 'document', - description: 'Perform operations on a new document after it\'s inserted in the database but *before* the mutation returns it.', + description: + 'Perform operations on a new document after it\'s inserted in the database but *before* the mutation returns it.' }); registerCallback({ name: `${typeName}.create.async`, iterator: { document: 'The document being inserted' }, - properties: [ - { currentUser: 'The current user' }, - { collection: 'The collection the document belongs to' }, - ], + properties: [{ currentUser: 'The current user' }, { collection: 'The collection the document belongs to' }], runs: 'async', returns: null, - description: 'Perform operations on a new document after it\'s inserted in the database asynchronously.', + description: 'Perform operations on a new document after it\'s inserted in the database asynchronously.' }); } if (options.update) { @@ -358,33 +372,28 @@ const registerCollectionCallbacks = (typeName, options) => { properties: [ { document: 'The document being edited' }, { currentUser: 'The current user' }, - { validationErrors: 'An object that can be used to accumulate validation errors' }, + { validationErrors: 'An object that can be used to accumulate validation errors' } ], runs: 'sync', returns: 'modifier', - description: 'Validate a document before update (can be skipped when updating directly on server).', + description: 'Validate a document before update (can be skipped when updating directly on server).' }); registerCallback({ name: `${typeName}.update.before`, iterator: { data: 'The client data' }, - properties: [ - { document: 'The document being edited' }, - { currentUser: 'The current user' }, - ], + properties: [{ document: 'The document being edited' }, { currentUser: 'The current user' }], runs: 'sync', returns: 'modifier', - description: 'Perform operations on a document before it\'s updated in the database.', + description: 'Perform operations on a document before it\'s updated in the database.' }); registerCallback({ name: `${typeName}.update.after`, iterator: { newDocument: 'The document after the update' }, - properties: [ - { document: 'The document being edited' }, - { currentUser: 'The current user' }, - ], + properties: [{ document: 'The document being edited' }, { currentUser: 'The current user' }], runs: 'sync', returns: 'document', - description: 'Perform operations on a document after it\'s updated in the database but *before* the mutation returns it.', + description: + 'Perform operations on a document after it\'s updated in the database but *before* the mutation returns it.' }); registerCallback({ name: `${typeName}.update.async`, @@ -392,11 +401,11 @@ const registerCollectionCallbacks = (typeName, options) => { properties: [ { document: 'The document before the edit' }, { currentUser: 'The current user' }, - { collection: 'The collection the document belongs to' }, + { collection: 'The collection the document belongs to' } ], runs: 'async', returns: null, - description: 'Perform operations on a document after it\'s updated in the database asynchronously.', + description: 'Perform operations on a document after it\'s updated in the database asynchronously.' }); } if (options.delete) { @@ -405,11 +414,11 @@ const registerCollectionCallbacks = (typeName, options) => { iterator: { document: 'The document being removed' }, properties: [ { currentUser: 'The current user' }, - { validationErrors: 'An object that can be used to accumulate validation errors' }, + { validationErrors: 'An object that can be used to accumulate validation errors' } ], runs: 'sync', returns: 'document', - description: 'Validate a document before removal (can be skipped when removing directly on server).', + description: 'Validate a document before removal (can be skipped when removing directly on server).' }); registerCallback({ name: `${typeName}.delete.before`, @@ -417,18 +426,18 @@ const registerCollectionCallbacks = (typeName, options) => { properties: [{ currentUser: 'The current user' }], runs: 'sync', returns: null, - description: 'Perform operations on a document before it\'s removed from the database.', + description: 'Perform operations on a document before it\'s removed from the database.' }); registerCallback({ name: `${typeName}.delete.async`, properties: [ { document: 'The document being removed' }, { currentUser: 'The current user' }, - { collection: 'The collection the document belongs to' }, + { collection: 'The collection the document belongs to' } ], runs: 'async', returns: null, - description: 'Perform operations on a document after it\'s removed from the database asynchronously.', + description: 'Perform operations on a document after it\'s removed from the database asynchronously.' }); } }; diff --git a/packages/vulcan-core/test/containers.test.js b/packages/vulcan-core/test/containers.test.js index 08f0756e9..c98db9ea5 100644 --- a/packages/vulcan-core/test/containers.test.js +++ b/packages/vulcan-core/test/containers.test.js @@ -1,39 +1,39 @@ import { extractCollectionInfo, extractFragmentInfo } from '../lib/modules/containers/handleOptions'; import expect from 'expect'; -describe('vulcan-core/containers', function () { - describe('handleOptions', function () { +describe('vulcan-core/containers', function() { + describe('handleOptions', function() { const expectedCollectionName = 'COLLECTION_NAME'; - const expectedCollection = { options: { expectedCollectionName } }; - it('get collectionName from collection', function () { + const collectionNameOptions = { collectionName: expectedCollectionName }; + const expectedCollection = { options: collectionNameOptions }; + it('get collectionName from collection', function() { const options = { collection: expectedCollection }; const { collection, collectionName } = extractCollectionInfo(options); expect(collection).toEqual(expectedCollection); expect(collectionName).toEqual(expectedCollectionName); }); - it('get collection from collectioName', function () { + it('get collection from collectioName', function() { // MOCK getCollection - const options = { collectionName: expectedCollectionName }; - const { collection, collectionName } = extractCollectionInfo(options); + const { collection, collectionName } = extractCollectionInfo(collectionNameOptions); expect(collection).toEqual(expectedCollection); expect(collectionName).toEqual(expectedCollectionName); }); const expectedFragmentName = 'FRAGMENT_NAME'; const expectedFragment = { definitions: [{ name: { value: expectedFragmentName } }] }; - it('get fragment from fragmentName', function () { + it('get fragment from fragmentName', function() { // MOCK getCollection const options = { fragmentName: expectedFragmentName }; const { fragment, fragmentName } = extractFragmentInfo(options); expect(fragment).toEqual(expectedFragment); expect(fragmentName).toEqual(expectedFragmentName); }); - it('get fragmentName from fragment', function () { + it('get fragmentName from fragment', function() { const options = { fragment: expectedFragment }; const { fragment, fragmentName } = extractFragmentInfo(options); expect(fragment).toEqual(expectedFragment); expect(fragmentName).toEqual(expectedFragmentName); }); - it('get fragmentName and fragment from collectionName', function () { + it('get fragmentName and fragment from collectionName', function() { // if options does not contain fragment, we get the collection default fragment based on its name const options = {}; const { fragment, fragmentName } = extractFragmentInfo(options, expectedCollectionName); diff --git a/packages/vulcan-lib/lib/client/apollo-client/index.js b/packages/vulcan-lib/lib/client/apollo-client/index.js new file mode 100644 index 000000000..eeb76223f --- /dev/null +++ b/packages/vulcan-lib/lib/client/apollo-client/index.js @@ -0,0 +1,3 @@ +export * from './links/state'; +export * from './updates'; +export * from './apollo2'; diff --git a/packages/vulcan-lib/lib/client/apollo-client/links/state.js b/packages/vulcan-lib/lib/client/apollo-client/links/state.js index f62d061d9..035386628 100644 --- a/packages/vulcan-lib/lib/client/apollo-client/links/state.js +++ b/packages/vulcan-lib/lib/client/apollo-client/links/state.js @@ -31,7 +31,7 @@ const registeredDefaults = {}; /** * Defaults are default response to queries */ -export const addDefault = ({ name, defaultValue, options = {} }) => { +export const registerDefault = ({ name, defaultValue, options = {} }) => { registeredDefaults[name] = defaultValue; return registeredDefaults; }; @@ -40,7 +40,7 @@ export const getDefaults = () => registeredDefaults; // Mutation are equivalent to a Redux Action + Reducer // except it uses GraphQL to retrieve/update data in the cache const registeredMutations = {}; -export const addMutation = ({ name, mutation, options = {} }) => { +export const registerMutation = ({ name, mutation, options = {} }) => { registeredMutations[name] = mutation; return registeredMutations; }; diff --git a/packages/vulcan-lib/lib/client/main.js b/packages/vulcan-lib/lib/client/main.js index a6d91cf15..ba77d97a2 100644 --- a/packages/vulcan-lib/lib/client/main.js +++ b/packages/vulcan-lib/lib/client/main.js @@ -5,4 +5,4 @@ export * from './mongo_redux.js'; export * from './render_context.js'; export * from './inject_data.js'; -export * from './apollo-client/apollo2.js'; \ No newline at end of file +export * from './apollo-client'; diff --git a/packages/vulcan-lib/package.js b/packages/vulcan-lib/package.js index c5e5ca0db..a59174bf4 100644 --- a/packages/vulcan-lib/package.js +++ b/packages/vulcan-lib/package.js @@ -2,7 +2,7 @@ Package.describe({ name: 'vulcan:lib', summary: 'Vulcan libraries.', version: '1.12.8', - git: 'https://github.com/VulcanJS/Vulcan.git', + git: 'https://github.com/VulcanJS/Vulcan.git' }); Package.onUse(function(api) { @@ -47,7 +47,7 @@ Package.onUse(function(api) { // 'aldeed:collection2-core@2.0.0', 'meteorhacks:picker@1.0.3', 'percolatestudio:synced-cron@1.1.0', - 'meteorhacks:inject-initial@1.0.4', + 'meteorhacks:inject-initial@1.0.4' ]; api.use(packages); @@ -59,3 +59,8 @@ Package.onUse(function(api) { api.mainModule('lib/server/main.js', 'server'); api.mainModule('lib/client/main.js', 'client'); }); + +Package.onTest(function(api) { + api.use(['ecmascript', 'meteortesting:mocha', 'vulcan:lib']); + api.mainModule('./test/index.js'); +}); diff --git a/packages/vulcan-lib/test/client/apolloClient.test.js b/packages/vulcan-lib/test/client/apolloClient.test.js new file mode 100644 index 000000000..7b9034f49 --- /dev/null +++ b/packages/vulcan-lib/test/client/apolloClient.test.js @@ -0,0 +1,53 @@ +import expect from 'jest'; +import { + registerDefault, + getDefaults, + registerMutation, + getMutations, + getResolvers, + createStateLink, + createApolloClient +} from '../../lib/client/main.js'; +if (Meteor.isClient) { + describe('vulcan-lib/apolloClient', function() { + describe('apollo-state-link', () => { + it('register and retrieve a mutation', function() { + const dummyMutation = () => {}; + registerMutation({ + name: 'dummyMutation', + mutation: dummyMutation + }); + const mutations = getMutations(); + expect(mutations['dummyMutation']).toEqual(dummyMutation); + }); + it('register and retrieve a default value', function() { + const dummyDefault = () => {}; + registerDefault({ + name: 'dummyDefault', + defaultValue: dummyDefault + }); + const defaults = getDefaults(); + expect(defaults['dummyDefault']).toEqual(dummyDefault); + }); + it('register mutation and get resolvers', function() { + const dummyMutation = () => {}; + registerMutation({ + name: 'dummyMutation', + mutation: dummyMutation + }); + const resolvers = getResolvers(); + expect(resolvers.Mutation['dummyMutation']).toEqual(dummyMutation); + }); + it('create a stateLink', () => { + const stateLink = createStateLink(); + expect(stateLink).toBeDefined(); + }); + }); + describe('apollo-client', function() { + it('create a client', function() { + const apolloClient = createApolloClient(); + expect(apolloClient).toBeDefined(); + }); + }); + }); +} diff --git a/packages/vulcan-lib/test/client/index.js b/packages/vulcan-lib/test/client/index.js new file mode 100644 index 000000000..52a054edb --- /dev/null +++ b/packages/vulcan-lib/test/client/index.js @@ -0,0 +1,2 @@ +// import client only tests here +import './apolloClient.tests.js'; diff --git a/packages/vulcan-lib/test/index.js b/packages/vulcan-lib/test/index.js new file mode 100644 index 000000000..61cf0435d --- /dev/null +++ b/packages/vulcan-lib/test/index.js @@ -0,0 +1 @@ +import './client/index';