This repository has been archived on 2022-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
outline/server/api/documents.test.js

1596 lines
46 KiB
JavaScript
Raw Normal View History

/* eslint-disable flowtype/require-valid-file-annotation */
import TestServer from 'fetch-test-server';
import app from '../app';
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
import {
Document,
View,
Star,
Revision,
Backlink,
CollectionUser,
} from '../models';
import { flushdb, seed } from '../test/support';
import {
buildShare,
buildCollection,
buildUser,
buildDocument,
} from '../test/factories';
const server = new TestServer(app.callback());
beforeEach(flushdb);
2017-07-15 23:08:12 +00:00
afterAll(server.close);
describe('#documents.info', async () => {
it('should return published document', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
});
it('should return archived document', async () => {
const { user, document } = await seed();
await document.archive(user.id);
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
});
it('should not return published document in collection not a member of', async () => {
feat: Add groups and group permissions (#1204) * WIP - got one API test to pass yay * adds group update endpoint * added group policies * adds groups.list API * adds groups.info * remove comment * WIP * tests for delete * adds group membership list * adds tests for groups list * add and remove user endpoints for group * ask some questions * fix up some issues around primary keys * remove export from group permissions Co-Authored-By: Tom Moor <tom.moor@gmail.com> * remove random file * only create events on actual updates, add tests to ensure * adds uniqueness validation to group name * throw validation errors on model and let it pass through the controller * fix linting * WIP * WIP * WIP * WIP * WIP basic edit and delete * basic CRUD for groups and memberships in place * got member counts working * add member count and limit the number of users sent over teh wire to 6 * factor avatar with AvatarWithPresence into its own class * wip * WIP avatars in group lists * WIP collection groups * add and remove group endpoints * wip add collection groups * wip get group adding to collections to work * wip get updating collection group memberships to work * wip get new group modal working * add tests for collection index * include collection groups in the withmemberships scope * tie permissions to group memberships * remove unused import * Update app/components/GroupListItem.js update title copy Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/migrations/20191211044318-create-groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/CollectionMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/models/Group.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * minor fixes * Update app/scenes/CollectionMembers/AddGroupsToCollection.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/Collection.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/CollectionMembers/CollectionMembers.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/GroupNew.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/GroupNew.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/Settings/Groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/documents.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/CollectionMembers/components/CollectionGroupMemberListItem.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * address comments * WIP - getting websocket stuff up and running * socket event for group deletion * wrapped up cascading deletes * lint * flow * fix: UI feedback * fix: Facepile size * fix: Lots of missing await's * Allow clicking facepile on group list item to open members * remove unused route push, grammar * fix: Remove bad analytics events feat: Add group events to audit log * collection. -> collections. * Add groups to entity websocket events (sync create/update/delete) between clients * fix: Users should not be able to see groups they are not a member of * fix: Not caching errors in UI when changing group memberships * fix: Hide unusable UI * test * fix: Tweak language * feat: Automatically open 'add member' modal after creating group Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-03-15 03:48:32 +00:00
const user = await buildUser();
const collection = await buildCollection({
private: true,
teamId: user.teamId,
});
const document = await buildDocument({ collectionId: collection.id });
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), id: document.id },
});
expect(res.status).toEqual(403);
});
it('should return drafts', async () => {
const { user, document } = await seed();
document.publishedAt = null;
await document.save();
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
});
2018-05-13 20:26:06 +00:00
it('should return document from shareId without token', async () => {
const { document, user } = await seed();
const share = await buildShare({
documentId: document.id,
teamId: document.teamId,
userId: user.id,
});
const res = await server.post('/api/documents.info', {
body: { shareId: share.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
expect(body.data.createdBy).toEqual(undefined);
expect(body.data.updatedBy).toEqual(undefined);
});
it('should not return document from revoked shareId', async () => {
const { document, user } = await seed();
const share = await buildShare({
documentId: document.id,
teamId: document.teamId,
userId: user.id,
});
await share.revoke(user.id);
const res = await server.post('/api/documents.info', {
body: { shareId: share.id },
});
expect(res.status).toEqual(400);
});
it('should not return document from archived shareId', async () => {
const { document, user } = await seed();
const share = await buildShare({
documentId: document.id,
teamId: document.teamId,
userId: user.id,
});
await document.archive(user.id);
const res = await server.post('/api/documents.info', {
body: { shareId: share.id },
});
expect(res.status).toEqual(400);
});
it('should return document from shareId with token', async () => {
const { user, document } = await seed();
2018-05-13 20:26:06 +00:00
const share = await buildShare({
documentId: document.id,
teamId: document.teamId,
userId: user.id,
2018-05-13 20:26:06 +00:00
});
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), shareId: share.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
expect(body.data.createdBy.id).toEqual(user.id);
expect(body.data.updatedBy.id).toEqual(user.id);
2018-05-13 20:26:06 +00:00
});
2018-05-26 18:23:21 +00:00
it('should return draft document from shareId with token', async () => {
const { user, document } = await seed();
document.publishedAt = null;
await document.save();
const share = await buildShare({
documentId: document.id,
teamId: document.teamId,
userId: user.id,
});
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), shareId: share.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
expect(body.data.createdBy.id).toEqual(user.id);
expect(body.data.updatedBy.id).toEqual(user.id);
});
it('should return document from shareId in collection not a member of', async () => {
const { user, document, collection } = await seed();
const share = await buildShare({
documentId: document.id,
teamId: document.teamId,
userId: user.id,
});
collection.private = true;
await collection.save();
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), shareId: share.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
});
it('should require authorization without token', async () => {
const { document } = await seed();
const res = await server.post('/api/documents.info', {
body: { id: document.id },
});
expect(res.status).toEqual(403);
});
it('should require authorization with incorrect token', async () => {
const { document } = await seed();
const user = await buildUser();
const res = await server.post('/api/documents.info', {
body: { token: user.getJwtToken(), id: document.id },
});
expect(res.status).toEqual(403);
});
2018-05-26 18:23:21 +00:00
it('should require a valid shareId', async () => {
const res = await server.post('/api/documents.info', {
body: { shareId: 123 },
});
expect(res.status).toEqual(400);
});
});
describe('#documents.list', async () => {
it('should return documents', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.list', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it('should not return unpublished documents', async () => {
const { user, document } = await seed();
document.publishedAt = null;
await document.save();
const res = await server.post('/api/documents.list', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should not return documents in private collections not a member of', async () => {
const { user, collection } = await seed();
collection.private = true;
await collection.save();
const res = await server.post('/api/documents.list', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should allow changing sort direction', async () => {
const { user, document } = await seed();
const anotherDoc = await buildDocument({
title: 'another document',
text: 'random text',
userId: user.id,
teamId: user.teamId,
});
const res = await server.post('/api/documents.list', {
body: { token: user.getJwtToken(), direction: 'ASC' },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data[0].id).toEqual(document.id);
expect(body.data[1].id).toEqual(anotherDoc.id);
});
2017-11-20 05:32:18 +00:00
it('should allow filtering by collection', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.list', {
2018-08-08 06:23:26 +00:00
body: {
token: user.getJwtToken(),
collection: document.collectionId,
},
2017-11-20 05:32:18 +00:00
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
2017-11-20 05:32:18 +00:00
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
it('should allow filtering to private collection', async () => {
const { user, collection } = await seed();
collection.private = true;
await collection.save();
await CollectionUser.create({
createdById: user.id,
collectionId: collection.id,
userId: user.id,
permission: 'read',
});
const res = await server.post('/api/documents.list', {
body: {
token: user.getJwtToken(),
collection: collection.id,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
});
it('should return backlinks', async () => {
const { user, document } = await seed();
const anotherDoc = await buildDocument({
title: 'another document',
text: 'random text',
userId: user.id,
teamId: user.teamId,
});
await Backlink.create({
reverseDocumentId: anotherDoc.id,
documentId: document.id,
userId: user.id,
});
const res = await server.post('/api/documents.list', {
body: { token: user.getJwtToken(), backlinkDocumentId: document.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(anotherDoc.id);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.list');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
describe('#documents.pinned', async () => {
it('should return pinned documents', async () => {
const { user, document } = await seed();
document.pinnedById = user.id;
await document.save();
const res = await server.post('/api/documents.pinned', {
body: { token: user.getJwtToken(), collectionId: document.collectionId },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it('should return pinned documents in private collections member of', async () => {
const { user, collection, document } = await seed();
collection.private = true;
await collection.save();
document.pinnedById = user.id;
await document.save();
await CollectionUser.create({
collectionId: collection.id,
userId: user.id,
createdById: user.id,
permission: 'read_write',
});
const res = await server.post('/api/documents.pinned', {
body: { token: user.getJwtToken(), collectionId: document.collectionId },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it('should not return pinned documents in private collections not a member of', async () => {
feat: Add groups and group permissions (#1204) * WIP - got one API test to pass yay * adds group update endpoint * added group policies * adds groups.list API * adds groups.info * remove comment * WIP * tests for delete * adds group membership list * adds tests for groups list * add and remove user endpoints for group * ask some questions * fix up some issues around primary keys * remove export from group permissions Co-Authored-By: Tom Moor <tom.moor@gmail.com> * remove random file * only create events on actual updates, add tests to ensure * adds uniqueness validation to group name * throw validation errors on model and let it pass through the controller * fix linting * WIP * WIP * WIP * WIP * WIP basic edit and delete * basic CRUD for groups and memberships in place * got member counts working * add member count and limit the number of users sent over teh wire to 6 * factor avatar with AvatarWithPresence into its own class * wip * WIP avatars in group lists * WIP collection groups * add and remove group endpoints * wip add collection groups * wip get group adding to collections to work * wip get updating collection group memberships to work * wip get new group modal working * add tests for collection index * include collection groups in the withmemberships scope * tie permissions to group memberships * remove unused import * Update app/components/GroupListItem.js update title copy Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/migrations/20191211044318-create-groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/CollectionMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/models/Group.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * minor fixes * Update app/scenes/CollectionMembers/AddGroupsToCollection.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/Collection.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/CollectionMembers/CollectionMembers.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/GroupNew.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/GroupNew.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/Settings/Groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/documents.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/CollectionMembers/components/CollectionGroupMemberListItem.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * address comments * WIP - getting websocket stuff up and running * socket event for group deletion * wrapped up cascading deletes * lint * flow * fix: UI feedback * fix: Facepile size * fix: Lots of missing await's * Allow clicking facepile on group list item to open members * remove unused route push, grammar * fix: Remove bad analytics events feat: Add group events to audit log * collection. -> collections. * Add groups to entity websocket events (sync create/update/delete) between clients * fix: Users should not be able to see groups they are not a member of * fix: Not caching errors in UI when changing group memberships * fix: Hide unusable UI * test * fix: Tweak language * feat: Automatically open 'add member' modal after creating group Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-03-15 03:48:32 +00:00
const collection = await buildCollection({
private: true,
});
const user = await buildUser({ teamId: collection.teamId });
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
const res = await server.post('/api/documents.pinned', {
body: { token: user.getJwtToken(), collectionId: collection.id },
});
feat: Add groups and group permissions (#1204) * WIP - got one API test to pass yay * adds group update endpoint * added group policies * adds groups.list API * adds groups.info * remove comment * WIP * tests for delete * adds group membership list * adds tests for groups list * add and remove user endpoints for group * ask some questions * fix up some issues around primary keys * remove export from group permissions Co-Authored-By: Tom Moor <tom.moor@gmail.com> * remove random file * only create events on actual updates, add tests to ensure * adds uniqueness validation to group name * throw validation errors on model and let it pass through the controller * fix linting * WIP * WIP * WIP * WIP * WIP basic edit and delete * basic CRUD for groups and memberships in place * got member counts working * add member count and limit the number of users sent over teh wire to 6 * factor avatar with AvatarWithPresence into its own class * wip * WIP avatars in group lists * WIP collection groups * add and remove group endpoints * wip add collection groups * wip get group adding to collections to work * wip get updating collection group memberships to work * wip get new group modal working * add tests for collection index * include collection groups in the withmemberships scope * tie permissions to group memberships * remove unused import * Update app/components/GroupListItem.js update title copy Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/migrations/20191211044318-create-groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/CollectionMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/models/Group.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * minor fixes * Update app/scenes/CollectionMembers/AddGroupsToCollection.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/menus/GroupMenu.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/Collection.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/CollectionMembers/CollectionMembers.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/GroupNew.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/GroupNew.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/Settings/Groups.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update server/api/documents.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * Update app/scenes/CollectionMembers/components/CollectionGroupMemberListItem.js Co-Authored-By: Tom Moor <tom.moor@gmail.com> * address comments * WIP - getting websocket stuff up and running * socket event for group deletion * wrapped up cascading deletes * lint * flow * fix: UI feedback * fix: Facepile size * fix: Lots of missing await's * Allow clicking facepile on group list item to open members * remove unused route push, grammar * fix: Remove bad analytics events feat: Add group events to audit log * collection. -> collections. * Add groups to entity websocket events (sync create/update/delete) between clients * fix: Users should not be able to see groups they are not a member of * fix: Not caching errors in UI when changing group memberships * fix: Hide unusable UI * test * fix: Tweak language * feat: Automatically open 'add member' modal after creating group Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-03-15 03:48:32 +00:00
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
expect(res.status).toEqual(403);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.pinned');
expect(res.status).toEqual(401);
});
});
describe('#documents.drafts', async () => {
it('should return unpublished documents', async () => {
const { user, document } = await seed();
document.publishedAt = null;
await document.save();
const res = await server.post('/api/documents.drafts', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
});
it('should not return documents in private collections not a member of', async () => {
const { user, document, collection } = await seed();
document.publishedAt = null;
await document.save();
collection.private = true;
await collection.save();
const res = await server.post('/api/documents.drafts', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
});
2017-10-17 05:36:44 +00:00
describe('#documents.revision', async () => {
it("should return a document's revisions", async () => {
2017-10-17 05:36:44 +00:00
const { user, document } = await seed();
const res = await server.post('/api/documents.revisions', {
body: {
token: user.getJwtToken(),
id: document.id,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).not.toEqual(document.id);
expect(body.data[0].title).toEqual(document.title);
});
it('should not return revisions for document in collection not a member of', async () => {
const { user, document, collection } = await seed();
collection.private = true;
await collection.save();
const res = await server.post('/api/documents.revisions', {
body: { token: user.getJwtToken(), id: document.id },
});
expect(res.status).toEqual(403);
});
it('should require authorization', async () => {
const { document } = await seed();
const user = await buildUser();
const res = await server.post('/api/documents.revisions', {
body: {
token: user.getJwtToken(),
id: document.id,
},
});
expect(res.status).toEqual(403);
});
2017-10-17 05:36:44 +00:00
});
2017-07-11 04:24:25 +00:00
describe('#documents.search', async () => {
it('should return results', async () => {
const { user } = await seed();
const res = await server.post('/api/documents.search', {
body: { token: user.getJwtToken(), query: 'much' },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].document.text).toEqual('# Much test support');
2017-07-11 04:24:25 +00:00
});
it('should return results in ranked order', async () => {
const { user } = await seed();
const firstResult = await buildDocument({
title: 'search term',
text: 'random text',
userId: user.id,
teamId: user.teamId,
});
const secondResult = await buildDocument({
title: 'random text',
text: 'search term',
userId: user.id,
teamId: user.teamId,
});
const res = await server.post('/api/documents.search', {
body: { token: user.getJwtToken(), query: 'search term' },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(2);
expect(body.data[0].document.id).toEqual(firstResult.id);
expect(body.data[1].document.id).toEqual(secondResult.id);
});
2019-01-08 05:44:33 +00:00
it('should return partial results in ranked order', async () => {
const { user } = await seed();
const firstResult = await buildDocument({
title: 'search term',
text: 'random text',
userId: user.id,
teamId: user.teamId,
});
const secondResult = await buildDocument({
title: 'random text',
text: 'search term',
userId: user.id,
teamId: user.teamId,
});
const res = await server.post('/api/documents.search', {
body: { token: user.getJwtToken(), query: 'sear &' },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(2);
expect(body.data[0].document.id).toEqual(firstResult.id);
expect(body.data[1].document.id).toEqual(secondResult.id);
});
it('should strip junk from search term', async () => {
const { user } = await seed();
const firstResult = await buildDocument({
title: 'search term',
text: 'this is some random text of the document body',
userId: user.id,
teamId: user.teamId,
});
const res = await server.post('/api/documents.search', {
body: { token: user.getJwtToken(), query: 'rando &\\;:()' },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].document.id).toEqual(firstResult.id);
});
it('should not return draft documents', async () => {
const { user } = await seed();
await buildDocument({
title: 'search term',
text: 'search term',
publishedAt: null,
userId: user.id,
teamId: user.teamId,
});
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should return draft documents created by user if chosen', async () => {
const { user } = await seed();
const document = await buildDocument({
title: 'search term',
text: 'search term',
publishedAt: null,
userId: user.id,
teamId: user.teamId,
});
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
includeDrafts: 'true',
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].document.id).toEqual(document.id);
});
it('should not return draft documents created by other users', async () => {
const { user } = await seed();
await buildDocument({
title: 'search term',
text: 'search term',
publishedAt: null,
teamId: user.teamId,
});
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
includeDrafts: 'true',
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should not return archived documents', async () => {
const { user } = await seed();
const document = await buildDocument({
title: 'search term',
text: 'search term',
teamId: user.teamId,
});
await document.archive(user.id);
const res = await server.post('/api/documents.search', {
body: { token: user.getJwtToken(), query: 'search term' },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should return archived documents if chosen', async () => {
const { user } = await seed();
const document = await buildDocument({
title: 'search term',
text: 'search term',
teamId: user.teamId,
});
await document.archive(user.id);
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
includeArchived: 'true',
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].document.id).toEqual(document.id);
});
it('should return documents for a specific user', async () => {
const { user } = await seed();
const document = await buildDocument({
title: 'search term',
text: 'search term',
teamId: user.teamId,
userId: user.id,
});
// This one will be filtered out
await buildDocument({
title: 'search term',
text: 'search term',
teamId: user.teamId,
});
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
userId: user.id,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].document.id).toEqual(document.id);
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
it('should return documents for a specific private collection', async () => {
const { user, collection } = await seed();
collection.private = true;
await collection.save();
await CollectionUser.create({
createdById: user.id,
collectionId: collection.id,
userId: user.id,
permission: 'read',
});
const document = await buildDocument({
title: 'search term',
text: 'search term',
teamId: user.teamId,
collectionId: collection.id,
});
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
collectionId: collection.id,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].document.id).toEqual(document.id);
});
it('should return documents for a specific collection', async () => {
const { user } = await seed();
const collection = await buildCollection();
const document = await buildDocument({
title: 'search term',
text: 'search term',
teamId: user.teamId,
});
// This one will be filtered out
await buildDocument({
title: 'search term',
text: 'search term',
teamId: user.teamId,
collectionId: collection.id,
});
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
collectionId: document.collectionId,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].document.id).toEqual(document.id);
});
it('should not return documents in private collections not a member of', async () => {
const { user } = await seed();
const collection = await buildCollection({ private: true });
await buildDocument({
title: 'search term',
text: 'search term',
publishedAt: null,
teamId: user.teamId,
collectionId: collection.id,
});
const res = await server.post('/api/documents.search', {
body: { token: user.getJwtToken(), query: 'search term' },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should not allow unknown dateFilter values', async () => {
const { user } = await seed();
const res = await server.post('/api/documents.search', {
body: {
token: user.getJwtToken(),
query: 'search term',
dateFilter: 'DROP TABLE students;',
},
});
expect(res.status).toEqual(400);
});
2017-07-11 04:24:25 +00:00
it('should require authentication', async () => {
const res = await server.post('/api/documents.search');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
});
describe('#documents.archived', async () => {
it('should return archived documents', async () => {
const { user } = await seed();
const document = await buildDocument({
userId: user.id,
teamId: user.teamId,
});
await document.archive(user.id);
const res = await server.post('/api/documents.archived', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
});
it('should not return deleted documents', async () => {
const { user } = await seed();
const document = await buildDocument({
userId: user.id,
teamId: user.teamId,
});
await document.delete();
const res = await server.post('/api/documents.archived', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should not return documents in private collections not a member of', async () => {
const { user } = await seed();
const collection = await buildCollection({ private: true });
const document = await buildDocument({
teamId: user.teamId,
collectionId: collection.id,
});
await document.archive(user.id);
const res = await server.post('/api/documents.archived', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.archived');
expect(res.status).toEqual(401);
});
});
describe('#documents.viewed', async () => {
it('should return empty result if no views', async () => {
const { user } = await seed();
const res = await server.post('/api/documents.viewed', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should return recently viewed documents', async () => {
const { user, document } = await seed();
await View.increment({ documentId: document.id, userId: user.id });
const res = await server.post('/api/documents.viewed', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it('should not return recently viewed but deleted documents', async () => {
const { user, document } = await seed();
await View.increment({ documentId: document.id, userId: user.id });
await document.destroy();
const res = await server.post('/api/documents.viewed', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should not return recently viewed documents in collection not a member of', async () => {
const { user, document, collection } = await seed();
await View.increment({ documentId: document.id, userId: user.id });
collection.private = true;
await collection.save();
const res = await server.post('/api/documents.viewed', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.viewed');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
});
describe('#documents.starred', async () => {
it('should return empty result if no stars', async () => {
const { user } = await seed();
const res = await server.post('/api/documents.starred', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(0);
});
it('should return starred documents', async () => {
const { user, document } = await seed();
await Star.create({ documentId: document.id, userId: user.id });
const res = await server.post('/api/documents.starred', {
body: { token: user.getJwtToken() },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.length).toEqual(1);
expect(body.data[0].id).toEqual(document.id);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.starred');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
});
describe('#documents.pin', async () => {
it('should pin the document', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.pin', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
expect(res.status).toEqual(200);
expect(body.data.pinned).toEqual(true);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.pin');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
it('should require authorization', async () => {
const { document } = await seed();
const user = await buildUser();
const res = await server.post('/api/documents.pin', {
body: { token: user.getJwtToken(), id: document.id },
});
expect(res.status).toEqual(403);
});
});
describe('#documents.restore', () => {
it('should allow restore of archived documents', async () => {
const { user, document } = await seed();
await document.archive(user.id);
const res = await server.post('/api/documents.restore', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
expect(body.data.archivedAt).toEqual(null);
});
it('should restore archived when previous parent is archived', async () => {
const { user, document } = await seed();
const childDocument = await buildDocument({
userId: user.id,
teamId: user.teamId,
collectionId: document.collectionId,
parentDocumentId: document.id,
});
await childDocument.archive(user.id);
await document.archive(user.id);
const res = await server.post('/api/documents.restore', {
body: { token: user.getJwtToken(), id: childDocument.id },
});
const body = await res.json();
expect(body.data.parentDocumentId).toEqual(undefined);
expect(body.data.archivedAt).toEqual(null);
});
it('should restore the document to a previous version', async () => {
const { user, document } = await seed();
const revision = await Revision.findOne({
where: { documentId: document.id },
});
const previousText = revision.text;
const revisionId = revision.id;
// update the document contents
document.text = 'UPDATED';
await document.save();
const res = await server.post('/api/documents.restore', {
body: { token: user.getJwtToken(), id: document.id, revisionId },
});
const body = await res.json();
expect(body.data.text).toEqual(previousText);
});
it('should not allow restoring a revision in another document', async () => {
const { user, document } = await seed();
const anotherDoc = await buildDocument();
const revision = await Revision.findOne({
where: { documentId: anotherDoc.id },
});
const revisionId = revision.id;
const res = await server.post('/api/documents.restore', {
body: { token: user.getJwtToken(), id: document.id, revisionId },
});
expect(res.status).toEqual(403);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.restore');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
it('should require authorization', async () => {
const { document } = await seed();
const revision = await Revision.findOne({
where: { documentId: document.id },
});
const revisionId = revision.id;
const user = await buildUser();
const res = await server.post('/api/documents.restore', {
body: { token: user.getJwtToken(), id: document.id, revisionId },
});
expect(res.status).toEqual(403);
});
});
describe('#documents.unpin', async () => {
it('should unpin the document', async () => {
const { user, document } = await seed();
document.pinnedBy = user;
await document.save();
const res = await server.post('/api/documents.unpin', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
expect(res.status).toEqual(200);
expect(body.data.pinned).toEqual(false);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.unpin');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
it('should require authorization', async () => {
const { document } = await seed();
const user = await buildUser();
const res = await server.post('/api/documents.unpin', {
body: { token: user.getJwtToken(), id: document.id },
});
expect(res.status).toEqual(403);
});
});
describe('#documents.star', async () => {
it('should star the document', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.star', {
body: { token: user.getJwtToken(), id: document.id },
});
const stars = await Star.findAll();
expect(res.status).toEqual(200);
expect(stars.length).toEqual(1);
expect(stars[0].documentId).toEqual(document.id);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.star');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
it('should require authorization', async () => {
const { document } = await seed();
const user = await buildUser();
const res = await server.post('/api/documents.star', {
body: { token: user.getJwtToken(), id: document.id },
});
expect(res.status).toEqual(403);
});
});
describe('#documents.unstar', async () => {
it('should unstar the document', async () => {
const { user, document } = await seed();
await Star.create({ documentId: document.id, userId: user.id });
const res = await server.post('/api/documents.unstar', {
body: { token: user.getJwtToken(), id: document.id },
});
const stars = await Star.findAll();
expect(res.status).toEqual(200);
expect(stars.length).toEqual(0);
});
it('should require authentication', async () => {
const res = await server.post('/api/documents.star');
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
it('should require authorization', async () => {
const { document } = await seed();
const user = await buildUser();
const res = await server.post('/api/documents.unstar', {
body: { token: user.getJwtToken(), id: document.id },
});
expect(res.status).toEqual(403);
});
});
2017-06-29 06:18:46 +00:00
2017-09-24 20:51:33 +00:00
describe('#documents.create', async () => {
it('should create as a new document', async () => {
const { user, collection } = await seed();
const res = await server.post('/api/documents.create', {
body: {
token: user.getJwtToken(),
collectionId: collection.id,
2017-09-24 20:51:33 +00:00
title: 'new document',
text: 'hello',
publish: true,
2017-09-24 20:51:33 +00:00
},
});
const body = await res.json();
const newDocument = await Document.findByPk(body.data.id);
2017-09-24 20:51:33 +00:00
expect(res.status).toEqual(200);
expect(newDocument.parentDocumentId).toBe(null);
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
expect(newDocument.collectionId).toBe(collection.id);
2017-09-24 20:51:33 +00:00
});
2018-08-07 05:22:15 +00:00
it('should not allow very long titles', async () => {
const { user, collection } = await seed();
const res = await server.post('/api/documents.create', {
body: {
token: user.getJwtToken(),
collectionId: collection.id,
2018-08-07 05:22:15 +00:00
title:
'This is a really long title that is not acceptable to Outline because it is so ridiculously long that we need to have a limit somewhere',
text: ' ',
},
});
expect(res.status).toEqual(400);
});
it('should create as a child and add to collection if published', async () => {
2017-09-24 20:51:33 +00:00
const { user, document, collection } = await seed();
const res = await server.post('/api/documents.create', {
body: {
token: user.getJwtToken(),
collectionId: collection.id,
parentDocumentId: document.id,
2017-09-24 20:51:33 +00:00
title: 'new document',
text: 'hello',
publish: true,
2017-09-24 20:51:33 +00:00
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.title).toBe('new document');
});
2018-02-25 04:44:13 +00:00
it('should error with invalid parentDocument', async () => {
const { user, collection } = await seed();
const res = await server.post('/api/documents.create', {
body: {
token: user.getJwtToken(),
collectionId: collection.id,
parentDocumentId: 'd7a4eb73-fac1-4028-af45-d7e34d54db8e',
title: 'new document',
text: 'hello',
},
});
const body = await res.json();
2018-02-25 04:44:13 +00:00
expect(res.status).toEqual(403);
expect(body).toMatchSnapshot();
});
it('should create as a child and not add to collection', async () => {
const { user, document, collection } = await seed();
const res = await server.post('/api/documents.create', {
body: {
token: user.getJwtToken(),
collectionId: collection.id,
parentDocumentId: document.id,
title: 'new document',
text: 'hello',
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.title).toBe('new document');
});
2017-09-24 20:51:33 +00:00
});
2017-06-29 06:18:46 +00:00
describe('#documents.update', async () => {
it('should update document details in the root', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
title: 'Updated title',
text: 'Updated text',
lastRevision: document.revision,
2017-06-29 06:18:46 +00:00
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.title).toBe('Updated title');
expect(body.data.text).toBe('Updated text');
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
it('should allow publishing document in private collection', async () => {
const { user, collection, document } = await seed();
document.publishedAt = null;
await document.save();
collection.private = true;
await collection.save();
await CollectionUser.create({
createdById: user.id,
collectionId: collection.id,
userId: user.id,
permission: 'read_write',
});
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
title: 'Updated title',
text: 'Updated text',
lastRevision: document.revision,
publish: true,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.publishedAt).toBeTruthy();
expect(body.policies[0].abilities.update).toEqual(true);
});
it('should not edit archived document', async () => {
const { user, document } = await seed();
await document.archive();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
title: 'Updated title',
text: 'Updated text',
lastRevision: document.revision,
},
});
expect(res.status).toEqual(403);
});
2018-05-07 05:13:52 +00:00
it('should not create new version when autosave=true', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
title: 'Updated title',
text: 'Updated text',
lastRevision: document.revision,
autosave: true,
},
});
const prevRevisionRecords = await Revision.count();
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.title).toBe('Updated title');
expect(body.data.text).toBe('Updated text');
const revisionRecords = await Revision.count();
expect(revisionRecords).toBe(prevRevisionRecords);
});
it('should fail if document lastRevision does not match', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
text: 'Updated text',
lastRevision: 123,
},
});
const body = await res.json();
expect(res.status).toEqual(400);
expect(body).toMatchSnapshot();
});
2017-06-29 06:18:46 +00:00
it('should update document details for children', async () => {
const { user, document, collection } = await seed();
collection.documentStructure = [
{
id: 'af1da94b-9591-4bab-897c-11774b804b77',
url: '/d/some-beef-RSZwQDsfpc',
title: 'some beef',
children: [
{
id: 'ab1da94b-9591-4bab-897c-11774b804b66',
url: '/d/another-doc-RSZwQDsfpc',
title: 'Another doc',
children: [],
},
{ ...document.toJSON(), children: [] },
],
},
];
await collection.save();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
title: 'Updated title',
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.title).toBe('Updated title');
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
it('allows editing by read-write collection user', async () => {
const { user, document, collection } = await seed();
collection.private = true;
await collection.save();
await CollectionUser.create({
collectionId: collection.id,
userId: user.id,
createdById: user.id,
permission: 'read_write',
});
const res = await server.post('/api/documents.update', {
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
body: {
token: user.getJwtToken(),
id: document.id,
text: 'Changed text',
lastRevision: document.revision,
},
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
const body = await res.json();
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
expect(res.status).toEqual(200);
expect(body.data.text).toBe('Changed text');
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
it('does not allow editing by read-only collection user', async () => {
const { user, document, collection } = await seed();
collection.private = true;
await collection.save();
await CollectionUser.create({
collectionId: collection.id,
userId: user.id,
createdById: user.id,
permission: 'read',
});
const res = await server.post('/api/documents.update', {
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
body: {
token: user.getJwtToken(),
id: document.id,
text: 'Changed text',
lastRevision: document.revision,
},
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
expect(res.status).toEqual(403);
});
it('should append document with text', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
text: 'Additional text',
lastRevision: document.revision,
append: true,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.text).toBe(document.text + 'Additional text');
});
it('should require text while appending', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
lastRevision: document.revision,
title: 'Updated Title',
append: true,
},
});
const body = await res.json();
expect(res.status).toEqual(400);
expect(body).toMatchSnapshot();
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
it('should allow setting empty text', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.update', {
body: {
token: user.getJwtToken(),
id: document.id,
lastRevision: document.revision,
title: 'Updated Title',
text: '',
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.text).toBe('');
});
feat: Memberships (#1032) * WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
2019-10-06 01:42:03 +00:00
it('should require authentication', async () => {
const { document } = await seed();
const res = await server.post('/api/documents.update', {
body: { id: document.id, text: 'Updated' },
});
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
it('should require authorization', async () => {
const { document } = await seed();
const user = await buildUser();
const res = await server.post('/api/documents.update', {
body: { token: user.getJwtToken(), id: document.id, text: 'Updated' },
});
expect(res.status).toEqual(403);
});
2017-06-29 06:18:46 +00:00
});
describe('#documents.archive', async () => {
it('should allow archiving document', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.archive', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.updatedBy.id).toEqual(user.id);
expect(body.data.archivedAt).toBeTruthy();
});
it('should require authentication', async () => {
const { document } = await seed();
const res = await server.post('/api/documents.archive', {
body: { id: document.id },
});
expect(res.status).toEqual(401);
});
});
describe('#documents.delete', async () => {
it('should allow deleting document', async () => {
const { user, document } = await seed();
const res = await server.post('/api/documents.delete', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.success).toEqual(true);
});
it('should allow deleting document without collection', async () => {
const { user, document, collection } = await seed();
// delete collection without hooks to trigger document deletion
await collection.destroy({ hooks: false });
const res = await server.post('/api/documents.delete', {
body: { token: user.getJwtToken(), id: document.id },
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.success).toEqual(true);
});
it('should require authentication', async () => {
const { document } = await seed();
const res = await server.post('/api/documents.delete', {
body: { id: document.id },
});
const body = await res.json();
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
});