Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions entry_types/scrolled/config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,12 @@ de:
linkButtonVariant:
label: Button-Variante
blank: "(Standard)"
main_menu:
comments: Kommentare
comments_view:
tabs:
comments: Alle Kommentare
selection: Für Auswahl
help_entries:
content_elements:
menu_item: Inhaltselemente
Expand Down
6 changes: 6 additions & 0 deletions entry_types/scrolled/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,12 @@ en:
linkButtonVariant:
label: Button Variante
blank: "(Default)"
main_menu:
comments: Comments
comments_view:
tabs:
comments: All comments
selection: For selection
help_entries:
content_elements:
menu_item: Content Elements
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'editor/config';
import Backbone from 'backbone';
import {editor} from 'pageflow-scrolled/editor';
import {features} from 'pageflow/frontend';
import {ScrolledEntry} from 'editor/models/ScrolledEntry';
Expand Down Expand Up @@ -158,6 +159,24 @@ describe('PreviewMessageController', () => {
})).resolves.toMatchObject({type: 'SELECT', payload: {id: 1, type: 'contentElement'}});
});

it('posts SELECT_COMMENT_THREAD message on selectCommentThread event', async () => {
const entry = factories.entry(ScrolledEntry, {}, {entryTypeSeed: normalizeSeed()});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow});

await postReadyMessageAndWaitForAcknowledgement(iframeWindow);

return expect(new Promise(resolve => {
iframeWindow.addEventListener('message', event => {
if (event.data.type === 'SELECT_COMMENT_THREAD') resolve(event.data);
});
entry.trigger('selectCommentThread', 7);
})).resolves.toMatchObject({
type: 'SELECT_COMMENT_THREAD',
payload: {threadId: 7}
});
});

it('passes on range from selectContentElement event', async () => {
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({
Expand Down Expand Up @@ -495,7 +514,7 @@ describe('PreviewMessageController', () => {
})).resolves.toBe('/');
});

it('navigates to comments route on SELECTED message for contentElementComments', () => {
it('navigates to comments route with tab=selection on SELECTED contentElementComments', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({
Expand All @@ -508,28 +527,163 @@ describe('PreviewMessageController', () => {
return expect(new Promise(resolve => {
editor.on('navigate', resolve);
window.postMessage({type: 'SELECTED', payload: {id: 1, type: 'contentElementComments'}}, '*');
})).resolves.toBe('/scrolled/content_elements/1/comments');
})).resolves.toBe('/scrolled/comments?tab=selection');
});

it('navigates to comments route with threadIds payload on SELECTED contentElementComments', () => {
it('does not navigate on SELECTED contentElementComments while on the comments route', async () => {
Backbone.history.fragment = 'scrolled/comments';

const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({contentElements: [{id: 1}]})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

const expectedPayload = encodeURIComponent(JSON.stringify({threadIds: [3, 7]}));
const navigate = jest.fn();
editor.on('navigate', navigate);

await new Promise(resolve => {
entry.once('change:highlightedThreadId', resolve);
window.postMessage({
type: 'SELECTED',
payload: {id: 10, type: 'contentElementComments', highlightedThreadId: 7}
}, '*');
});

expect(navigate).not.toHaveBeenCalled();
expect(entry.get('highlightedThreadId')).toBe(7);

Backbone.history.fragment = undefined;
});

it('does not navigate on SELECTED contentElementComments while on the comments selection tab', async () => {
Backbone.history.fragment = 'scrolled/comments?tab=selection';

const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({contentElements: [{id: 1}]})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

const navigate = jest.fn();
editor.on('navigate', navigate);

await new Promise(resolve => {
entry.once('change:highlightedThreadId', resolve);
window.postMessage({
type: 'SELECTED',
payload: {id: 10, type: 'contentElementComments', highlightedThreadId: 7}
}, '*');
});

expect(navigate).not.toHaveBeenCalled();

Backbone.history.fragment = undefined;
});

it('sets highlightedThreadId on entry on SELECTED contentElementComments', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {entryTypeSeed: normalizeSeed()});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
editor.on('navigate', resolve);
entry.once('change:highlightedThreadId', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 10, type: 'contentElementComments', threadIds: [3, 7]}
payload: {id: 10, type: 'contentElementComments', highlightedThreadId: 5}
}, '*');
})).resolves.toBe(
`/scrolled/content_elements/10/comments?payload=${expectedPayload}`
);
})).resolves.toBe(5);
});

it('clears highlightedThreadId on entry on SELECTED with non-comments type', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {entryTypeSeed: normalizeSeed()});
entry.set('highlightedThreadId', 5);

const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:highlightedThreadId', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 10, type: 'sectionSettings'}
}, '*');
})).resolves.toBeUndefined();
});

it('sets selectedContentElementCommentsId on SELECTED contentElementComments', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {entryTypeSeed: normalizeSeed()});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 7, type: 'contentElementComments'}
}, '*');
})).resolves.toBe(7);
});

it('sets selectedContentElementCommentsId on SELECTED contentElement', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({contentElements: [{id: 4}]})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 4, type: 'contentElement'}
}, '*');
})).resolves.toBe(4);
});

it('sets selectedContentElementCommentsId from permaId on SELECTED newThread', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {
entryTypeSeed: normalizeSeed({contentElements: [{id: 4, permaId: 100}]})
});
const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {
id: 100,
type: 'newThread',
subjectType: 'ContentElement',
range: {anchor: {path: [0, 0], offset: 0}, focus: {path: [0, 0], offset: 1}}
}
}, '*');
})).resolves.toBe(4);
});

it('clears selectedContentElementCommentsId on SELECTED with non-content-element type', () => {
const editor = factories.editorApi();
const entry = factories.entry(ScrolledEntry, {}, {entryTypeSeed: normalizeSeed()});
entry.set('selectedContentElementCommentsId', 9);

const iframeWindow = createIframeWindow();
controller = new PreviewMessageController({entry, iframeWindow, editor});

return expect(new Promise(resolve => {
entry.once('change:selectedContentElementCommentsId', (model, value) => resolve(value));
window.postMessage({
type: 'SELECTED',
payload: {id: 10, type: 'sectionSettings'}
}, '*');
})).resolves.toBeUndefined();
});

it('navigates to new thread route with encoded payload on SELECTED for newThread', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,39 @@
import 'editor/config';

import {SideBarController} from 'editor/controllers/SideBarController';
import {ContentElementCommentsView} from 'editor/views/ContentElementCommentsView';
import {CommentsView} from 'editor/views/CommentsView';

import {factories} from 'pageflow/testHelpers';
import {useEditorGlobals} from 'support';

describe('SideBarController', () => {
const {createEntry} = useEditorGlobals();

describe('#contentElementComments', () => {
it('shows a ContentElementCommentsView without threadIds when no payload given', () => {
const entry = createEntry({
contentElements: [{id: 1, permaId: 10, typeName: 'textBlock'}]
});
describe('#comments', () => {
it('shows a CommentsView in the region', () => {
const entry = createEntry({});
entry.reviewSession = factories.reviewSession();

const region = {show: jest.fn()};
const controller = new SideBarController({region, entry});

controller.contentElementComments(1);
controller.comments();

const shown = region.show.mock.calls[0][0];
expect(shown).toBeInstanceOf(ContentElementCommentsView);
expect(shown.options.threadIds).toBeUndefined();
expect(shown).toBeInstanceOf(CommentsView);
});

it('decodes threadIds from the payload and passes it to the view', () => {
const entry = createEntry({
contentElements: [{id: 1, permaId: 10, typeName: 'textBlock'}]
});
it('passes the tab arg as defaultTab to the CommentsView', () => {
const entry = createEntry({});
entry.reviewSession = factories.reviewSession();

const region = {show: jest.fn()};
const controller = new SideBarController({region, entry});

const payload = encodeURIComponent(JSON.stringify({threadIds: [3, 7]}));

controller.contentElementComments(1, payload);
controller.comments('selection');

const shown = region.show.mock.calls[0][0];
expect(shown).toBeInstanceOf(ContentElementCommentsView);
expect(shown.options.threadIds).toEqual([3, 7]);
expect(shown.options.defaultTab).toBe('selection');
});
});
});
Loading
Loading