diff --git a/src/internal-packages/app/lib/stores/namespace-store.js b/src/internal-packages/app/lib/stores/namespace-store.js index 1c63bc823ed..c43b7ef22a4 100644 --- a/src/internal-packages/app/lib/stores/namespace-store.js +++ b/src/internal-packages/app/lib/stores/namespace-store.js @@ -1,12 +1,25 @@ const Reflux = require('reflux'); const app = require('hadron-app'); -const _ = require('lodash'); +const toNS = require('mongodb-ns'); const debug = require('debug')('mongodb-compass:namespace-store'); +/** + * The default namespace when the Compass user connects to a MongoDB instance. + */ +const DEFAULT_NAMESPACE = ''; + /** * The store holds the source of truth for the namespace being worked on. */ const NamespaceStore = Reflux.createStore({ + + /** + * Initializing the store should set up the default namespace. + */ + init() { + this._ns = DEFAULT_NAMESPACE; + }, + /** * Gets the current namespace being worked with in the application. */ @@ -15,17 +28,6 @@ const NamespaceStore = Reflux.createStore({ return this._ns; }, - __nsHelper: function(ns) { - if (!ns) { - return ['', '']; - } - if (_.includes(ns, '.')) { - return ns.split('.'); - } - - return [ns, '']; - }, - /** * Set the current namespace being worked on in the application. * @@ -35,17 +37,17 @@ const NamespaceStore = Reflux.createStore({ debug('setting ns: from', this._ns, 'to', ns); const registry = app.appRegistry; if (registry) { - const oldNns = this.__nsHelper(this._ns); - const newNs = this.__nsHelper(ns); + const oldNs = toNS(this._ns); + const newNs = toNS(ns); - if (oldNns[0] !== newNs[0]) { + if (oldNs.database !== newNs.database) { registry.callOnStores(function(store) { if (store.onDatabaseChanged) { store.onDatabaseChanged(ns); } }); } - if (oldNns[1] !== newNs[1]) { + if (oldNs.database !== newNs.database || oldNs.collection !== newNs.collection) { registry.callOnStores(function(store) { if (store.onCollectionChanged) { store.onCollectionChanged(ns); diff --git a/test/unit/namespace-store.test.js b/test/unit/namespace-store.test.js index c1ed9600cf6..07190c07bbc 100644 --- a/test/unit/namespace-store.test.js +++ b/test/unit/namespace-store.test.js @@ -1,16 +1,96 @@ -const expect = require('chai').expect; +const app = require('hadron-app'); +const AppRegistry = require('hadron-app-registry'); +const { expect } = require('chai'); +const Reflux = require('reflux'); const NamespaceStore = require('../../src/internal-packages/app/lib/stores/namespace-store'); +/** + * Useful background information on namespaces: + * https://docs.mongodb.com/manual/reference/limits/#naming-restrictions + */ +describe('NamespaceStore', () => { + const initialDatabase = 'foo'; + const initialCollection = 'bar.baz'; + let appRegistry; -describe('NamespaceStore', function() { - describe('#set ns', function() { - it('triggers a store event', function(done) { - var unsubscribe = NamespaceStore.listen(function(ns) { + beforeEach(() => { + NamespaceStore.ns = `${initialDatabase}.${initialCollection}`; + appRegistry = app.appRegistry; + app.appRegistry = new AppRegistry(); + }); + + afterEach(() => { + app.appRegistry = appRegistry; + }); + + describe('#set ns', () => { + it('triggers a store event', (done) => { + const unsubscribe = NamespaceStore.listen((ns) => { expect(ns).to.equal('database.collection'); unsubscribe(); done(); }); NamespaceStore.ns = 'database.collection'; }); + + context('when collection changes', () => { + it('calls onCollectionChanged', (done) => { + const newNamespace = `${initialDatabase}.change.the-collection.please`; + const CollectionSubscriberStore = Reflux.createStore({ + onCollectionChanged(namespace) { + expect(namespace).to.be.equal(newNamespace); + done(); + } + }); + app.appRegistry.registerStore('CollectionSubscriber.Store', CollectionSubscriberStore); + NamespaceStore.ns = newNamespace; + }); + }); + + context('when the initial collection contains a dot', () => { + context('when only the part after the dot changes', () => { + it('calls onCollectionChanged', (done) => { + NamespaceStore.ns = 'foo.bar.baz'; + const newNamespace = 'foo.bar.jaguar'; + const CollectionSubscriberStore = Reflux.createStore({ + onCollectionChanged(namespace) { + expect(namespace).to.be.equal(newNamespace); + done(); + } + }); + app.appRegistry.registerStore('CollectionSubscriber.Store', CollectionSubscriberStore); + NamespaceStore.ns = newNamespace; + }); + }); + }); + + context('when the initial collection does not contain a dot', () => { + it('calls onCollectionChanged', (done) => { + NamespaceStore.ns = 'foo.bar'; + const newNamespace = 'jaguar.bar'; + const CollectionSubscriberStore = Reflux.createStore({ + onCollectionChanged(namespace) { + expect(namespace).to.be.equal(newNamespace); + done(); + } + }); + app.appRegistry.registerStore('CollectionSubscriber.Store', CollectionSubscriberStore); + NamespaceStore.ns = newNamespace; + }); + }); + + context('when database changes', () => { + it('calls onDatabaseChanged', (done) => { + const newNamespace = `changeTheDB.${initialCollection}`; + const DatabaseSubscriberStore = Reflux.createStore({ + onDatabaseChanged(namespace) { + expect(namespace).to.be.equal(newNamespace); + done(); + } + }); + app.appRegistry.registerStore('DatabaseSubscriber.Store', DatabaseSubscriberStore); + NamespaceStore.ns = newNamespace; + }); + }); }); });