Commit 5b323946 authored by Robert Knight's avatar Robert Knight

Replace `FRAME_CONNECTED` event in groups service

parent c64f42dd
...@@ -3,6 +3,7 @@ import serviceConfig from '../service-config'; ...@@ -3,6 +3,7 @@ import serviceConfig from '../service-config';
import { isReply } from '../util/annotation-metadata'; import { isReply } from '../util/annotation-metadata';
import { combineGroups } from '../util/groups'; import { combineGroups } from '../util/groups';
import { awaitStateChange } from '../util/state'; import { awaitStateChange } from '../util/state';
import { watch } from '../util/watch';
const DEFAULT_ORG_ID = '__default__'; const DEFAULT_ORG_ID = '__default__';
...@@ -31,14 +32,19 @@ export default function groups( ...@@ -31,14 +32,19 @@ export default function groups(
const svc = serviceConfig(settings); const svc = serviceConfig(settings);
const authority = svc ? svc.authority : null; const authority = svc ? svc.authority : null;
function getDocumentUriForGroupSearch() { /**
function mainUri() { * Return the main document URI that is used to fetch groups associated with
const mainFrame = store.mainFrame(); * the site that the user is on.
if (!mainFrame) { */
return null; function mainUri() {
} const mainFrame = store.mainFrame();
return mainFrame.uri; if (!mainFrame) {
return null;
} }
return mainFrame.uri;
}
function getDocumentUriForGroupSearch() {
return awaitStateChange(store, mainUri); return awaitStateChange(store, mainUri);
} }
...@@ -167,11 +173,7 @@ export default function groups( ...@@ -167,11 +173,7 @@ export default function groups(
}); });
} }
// The document URI passed to the most recent `GET /api/groups` call in order let didSubscribeToUriChanges = false;
// to include groups associated with this page. This is retained to determine
// whether we need to re-fetch groups if the URLs of frames connected to the
// sidebar app changes.
let documentUri = null;
/* /*
* Fetch an individual group. * Fetch an individual group.
...@@ -193,15 +195,27 @@ export default function groups( ...@@ -193,15 +195,27 @@ export default function groups(
* The groups that are fetched depend on the current user, the URI of * The groups that are fetched depend on the current user, the URI of
* the current document, and the direct-linked group and/or annotation. * the current document, and the direct-linked group and/or annotation.
* *
* On startup, `load()` must be called to trigger the initial groups fetch.
* Subsequently groups are automatically reloaded if the logged-in user or
* main document URI changes.
*
* @return {Promise<Group[]>} * @return {Promise<Group[]>}
*/ */
async function load() { async function load() {
// Step 1: Get the URI of the active document, so we can fetch groups // Step 1: Get the URI of the active document, so we can fetch groups
// associated with that document. // associated with that document.
let documentUri;
if (isSidebar) { if (isSidebar) {
documentUri = await getDocumentUriForGroupSearch(); documentUri = await getDocumentUriForGroupSearch();
} }
if (!didSubscribeToUriChanges) {
didSubscribeToUriChanges = true;
watch(store.subscribe, mainUri, () => {
load();
});
}
// Step 2: Concurrently fetch the groups the user is a member of, // Step 2: Concurrently fetch the groups the user is a member of,
// the groups associated with the current document and the annotation // the groups associated with the current document and the annotation
// and/or group that was direct-linked (if any). // and/or group that was direct-linked (if any).
...@@ -362,16 +376,6 @@ export default function groups( ...@@ -362,16 +376,6 @@ export default function groups(
return load(); return load();
}); });
// refetch the list of groups when document url changes
$rootScope.$on(events.FRAME_CONNECTED, () => {
return getDocumentUriForGroupSearch().then(uri => {
if (documentUri !== uri) {
documentUri = uri;
load();
}
});
});
return { return {
all: all, all: all,
get: get, get: get,
......
import events from '../../events'; import events from '../../events';
import fakeReduxStore from '../../test/fake-redux-store'; import fakeReduxStore from '../../test/fake-redux-store';
import groups, { $imports } from '../groups'; import groups, { $imports } from '../groups';
import { waitFor } from '../../../test-util/wait';
/** /**
* Generate a truth table containing every possible combination of a set of * Generate a truth table containing every possible combination of a set of
...@@ -108,7 +109,7 @@ describe('groups', function () { ...@@ -108,7 +109,7 @@ describe('groups', function () {
}, },
$on: function (event, callback) { $on: function (event, callback) {
if (event === events.USER_CHANGED || event === events.FRAME_CONNECTED) { if (event === events.USER_CHANGED) {
this.eventCallbacks[event] = callback; this.eventCallbacks[event] = callback;
} }
}, },
...@@ -809,7 +810,7 @@ describe('groups', function () { ...@@ -809,7 +810,7 @@ describe('groups', function () {
}); });
}); });
describe('calls load on various events', function () { describe('automatic re-fetching', function () {
it('refetches groups when the logged-in user changes', () => { it('refetches groups when the logged-in user changes', () => {
service(); service();
...@@ -819,43 +820,46 @@ describe('groups', function () { ...@@ -819,43 +820,46 @@ describe('groups', function () {
}); });
context('when a new frame connects', () => { context('when a new frame connects', () => {
it('should refetch groups if main frame URL has changed', () => { it('should refetch groups if main frame URL has changed', async () => {
const svc = service(); const svc = service();
fakeStore.setState({ fakeStore.setState({
frames: [{ uri: 'https://domain.com/page-a' }], frames: [{ uri: 'https://domain.com/page-a' }],
}); });
return svc await svc.load();
.load()
.then(() => { // Simulate main frame URL change, eg. due to client-side navigation in
// Simulate main frame URL change, eg. due to client-side navigation in // a single page application.
// a single page application. fakeApi.groups.list.resetHistory();
fakeApi.groups.list.resetHistory(); fakeStore.setState({
fakeStore.setState({ frames: [{ uri: 'https://domain.com/page-b' }],
frames: [{ uri: 'https://domain.com/page-b' }], });
});
await waitFor(() => fakeApi.groups.list.callCount > 0);
return fakeRootScope.eventCallbacks[events.FRAME_CONNECTED](); assert.calledOnce(fakeApi.groups.list);
})
.then(() => {
assert.calledOnce(fakeApi.groups.list);
});
}); });
it('should not refetch groups if main frame URL has not changed', () => { it('should not refetch groups if main frame URL has not changed', async () => {
const svc = service(); const svc = service();
fakeStore.setState({ fakeStore.setState({
frames: [{ uri: 'https://domain.com/page-a' }], frames: [{ uri: 'https://domain.com/page-a' }],
}); });
return svc
.load() await svc.load();
.then(() => { assert.calledOnce(fakeApi.groups.list);
return fakeRootScope.eventCallbacks[events.FRAME_CONNECTED]();
}) // A new frame connects, but the main frame URI remains the same.
.then(() => { fakeApi.groups.list.resetHistory();
assert.calledOnce(fakeApi.groups.list); fakeStore.setState({
}); frames: [
{ uri: 'https://domain.com/page-a' },
{ uri: 'https://domain.com/iframe-b' },
],
});
await new Promise(resolve => setTimeout(resolve, 1));
assert.notCalled(fakeApi.groups.list);
}); });
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment