Skip to content

Commit f77f4be

Browse files
authored
[Backport 1.9] COMPASS 1747 Fire onCollectionChanged in more cases (#1227) (#1230)
* 🔨 Refactor NamespaceStore test * ✅ Add some basic unit tests * ✅ Add test to detect the 🐛 * 🐛 onCollectionChange should fire on either of DB or Collection changed Example: db1.coll => db2.coll, the collection component is identical, but it is a different collection because it is on a different database. * 🐛 Reuse mongodb-ns It handles the '.' in collection names correctly. * 🎨 Use contexts for test readability * ✅ Add test to detect the second 🐛 * 🐛 Initialize to the default namespace of '' Reproduced on local with: npm test -- --functional https://travis-ci.com/10gen/compass/jobs/88742497 #retry 1) CollectionsStore "before all" hook: Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. https://travis-ci.com/10gen/compass/jobs/89088707
1 parent 33a0f09 commit f77f4be

File tree

2 files changed

+103
-21
lines changed

2 files changed

+103
-21
lines changed

src/internal-packages/app/lib/stores/namespace-store.js

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
const Reflux = require('reflux');
22
const app = require('hadron-app');
3-
const _ = require('lodash');
3+
const toNS = require('mongodb-ns');
44
const debug = require('debug')('mongodb-compass:namespace-store');
55

6+
/**
7+
* The default namespace when the Compass user connects to a MongoDB instance.
8+
*/
9+
const DEFAULT_NAMESPACE = '';
10+
611
/**
712
* The store holds the source of truth for the namespace being worked on.
813
*/
914
const NamespaceStore = Reflux.createStore({
15+
16+
/**
17+
* Initializing the store should set up the default namespace.
18+
*/
19+
init() {
20+
this._ns = DEFAULT_NAMESPACE;
21+
},
22+
1023
/**
1124
* Gets the current namespace being worked with in the application.
1225
*/
@@ -15,17 +28,6 @@ const NamespaceStore = Reflux.createStore({
1528
return this._ns;
1629
},
1730

18-
__nsHelper: function(ns) {
19-
if (!ns) {
20-
return ['', ''];
21-
}
22-
if (_.includes(ns, '.')) {
23-
return ns.split('.');
24-
}
25-
26-
return [ns, ''];
27-
},
28-
2931
/**
3032
* Set the current namespace being worked on in the application.
3133
*
@@ -35,17 +37,17 @@ const NamespaceStore = Reflux.createStore({
3537
debug('setting ns: from', this._ns, 'to', ns);
3638
const registry = app.appRegistry;
3739
if (registry) {
38-
const oldNns = this.__nsHelper(this._ns);
39-
const newNs = this.__nsHelper(ns);
40+
const oldNs = toNS(this._ns);
41+
const newNs = toNS(ns);
4042

41-
if (oldNns[0] !== newNs[0]) {
43+
if (oldNs.database !== newNs.database) {
4244
registry.callOnStores(function(store) {
4345
if (store.onDatabaseChanged) {
4446
store.onDatabaseChanged(ns);
4547
}
4648
});
4749
}
48-
if (oldNns[1] !== newNs[1]) {
50+
if (oldNs.database !== newNs.database || oldNs.collection !== newNs.collection) {
4951
registry.callOnStores(function(store) {
5052
if (store.onCollectionChanged) {
5153
store.onCollectionChanged(ns);

test/unit/namespace-store.test.js

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,96 @@
1-
const expect = require('chai').expect;
1+
const app = require('hadron-app');
2+
const AppRegistry = require('hadron-app-registry');
3+
const { expect } = require('chai');
4+
const Reflux = require('reflux');
25
const NamespaceStore = require('../../src/internal-packages/app/lib/stores/namespace-store');
36

7+
/**
8+
* Useful background information on namespaces:
9+
* https://docs.mongodb.com/manual/reference/limits/#naming-restrictions
10+
*/
11+
describe('NamespaceStore', () => {
12+
const initialDatabase = 'foo';
13+
const initialCollection = 'bar.baz';
14+
let appRegistry;
415

5-
describe('NamespaceStore', function() {
6-
describe('#set ns', function() {
7-
it('triggers a store event', function(done) {
8-
var unsubscribe = NamespaceStore.listen(function(ns) {
16+
beforeEach(() => {
17+
NamespaceStore.ns = `${initialDatabase}.${initialCollection}`;
18+
appRegistry = app.appRegistry;
19+
app.appRegistry = new AppRegistry();
20+
});
21+
22+
afterEach(() => {
23+
app.appRegistry = appRegistry;
24+
});
25+
26+
describe('#set ns', () => {
27+
it('triggers a store event', (done) => {
28+
const unsubscribe = NamespaceStore.listen((ns) => {
929
expect(ns).to.equal('database.collection');
1030
unsubscribe();
1131
done();
1232
});
1333
NamespaceStore.ns = 'database.collection';
1434
});
35+
36+
context('when collection changes', () => {
37+
it('calls onCollectionChanged', (done) => {
38+
const newNamespace = `${initialDatabase}.change.the-collection.please`;
39+
const CollectionSubscriberStore = Reflux.createStore({
40+
onCollectionChanged(namespace) {
41+
expect(namespace).to.be.equal(newNamespace);
42+
done();
43+
}
44+
});
45+
app.appRegistry.registerStore('CollectionSubscriber.Store', CollectionSubscriberStore);
46+
NamespaceStore.ns = newNamespace;
47+
});
48+
});
49+
50+
context('when the initial collection contains a dot', () => {
51+
context('when only the part after the dot changes', () => {
52+
it('calls onCollectionChanged', (done) => {
53+
NamespaceStore.ns = 'foo.bar.baz';
54+
const newNamespace = 'foo.bar.jaguar';
55+
const CollectionSubscriberStore = Reflux.createStore({
56+
onCollectionChanged(namespace) {
57+
expect(namespace).to.be.equal(newNamespace);
58+
done();
59+
}
60+
});
61+
app.appRegistry.registerStore('CollectionSubscriber.Store', CollectionSubscriberStore);
62+
NamespaceStore.ns = newNamespace;
63+
});
64+
});
65+
});
66+
67+
context('when the initial collection does not contain a dot', () => {
68+
it('calls onCollectionChanged', (done) => {
69+
NamespaceStore.ns = 'foo.bar';
70+
const newNamespace = 'jaguar.bar';
71+
const CollectionSubscriberStore = Reflux.createStore({
72+
onCollectionChanged(namespace) {
73+
expect(namespace).to.be.equal(newNamespace);
74+
done();
75+
}
76+
});
77+
app.appRegistry.registerStore('CollectionSubscriber.Store', CollectionSubscriberStore);
78+
NamespaceStore.ns = newNamespace;
79+
});
80+
});
81+
82+
context('when database changes', () => {
83+
it('calls onDatabaseChanged', (done) => {
84+
const newNamespace = `changeTheDB.${initialCollection}`;
85+
const DatabaseSubscriberStore = Reflux.createStore({
86+
onDatabaseChanged(namespace) {
87+
expect(namespace).to.be.equal(newNamespace);
88+
done();
89+
}
90+
});
91+
app.appRegistry.registerStore('DatabaseSubscriber.Store', DatabaseSubscriberStore);
92+
NamespaceStore.ns = newNamespace;
93+
});
94+
});
1595
});
1696
});

0 commit comments

Comments
 (0)