mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
441 lines
19 KiB
TypeScript
441 lines
19 KiB
TypeScript
|
import {BaseAPI} from 'app/common/BaseAPI';
|
||
|
import {UserAPI, Workspace} from 'app/common/UserAPI';
|
||
|
import {assert} from 'chai';
|
||
|
import flatten = require('lodash/flatten');
|
||
|
import sortBy = require('lodash/sortBy');
|
||
|
import {TestServer} from 'test/gen-server/apiUtils';
|
||
|
import * as testUtils from 'test/server/testUtils';
|
||
|
|
||
|
describe('removedAt', function() {
|
||
|
let home: TestServer;
|
||
|
testUtils.setTmpLogLevel('error');
|
||
|
|
||
|
before(async function() {
|
||
|
home = new TestServer(this);
|
||
|
await home.start(['home', 'docs']);
|
||
|
const api = await home.createHomeApi('chimpy', 'docs');
|
||
|
await api.newOrg({name: 'testy', domain: 'testy'});
|
||
|
});
|
||
|
|
||
|
after(async function() {
|
||
|
this.timeout(100000);
|
||
|
const api = await home.createHomeApi('chimpy', 'docs');
|
||
|
await api.deleteOrg('testy');
|
||
|
await home.stop();
|
||
|
});
|
||
|
|
||
|
function docNames(data: Workspace|Workspace[]) {
|
||
|
if ('docs' in data) {
|
||
|
return data.docs.map(doc => doc.name).sort();
|
||
|
}
|
||
|
return flatten(
|
||
|
sortBy(data, 'name')
|
||
|
.map(ws => ws.docs.map(d => `${ws.name}:${d.name}`).sort()));
|
||
|
}
|
||
|
|
||
|
function workspaceNames(data: Workspace[]) {
|
||
|
return data.map(ws => ws.name).sort();
|
||
|
}
|
||
|
|
||
|
describe('scenario', function() {
|
||
|
const org: string = 'testy';
|
||
|
let api: UserAPI; // regular api
|
||
|
let xapi: UserAPI; // api for soft-deleted resources
|
||
|
let bapi: BaseAPI; // api cast to allow custom requests
|
||
|
let ws1: number;
|
||
|
let ws2: number;
|
||
|
let ws3: number;
|
||
|
let ws4: number;
|
||
|
let doc11: string;
|
||
|
let doc21: string;
|
||
|
let doc12: string;
|
||
|
let doc31: string;
|
||
|
|
||
|
before(async function() {
|
||
|
api = await home.createHomeApi('chimpy', org);
|
||
|
xapi = api.forRemoved();
|
||
|
bapi = api as unknown as BaseAPI;
|
||
|
// Get rid of home workspace
|
||
|
for (const ws of await api.getOrgWorkspaces('current')) {
|
||
|
await api.deleteWorkspace(ws.id);
|
||
|
}
|
||
|
// Make two workspaces with two docs apiece, one workspace with one doc,
|
||
|
// and one empty workspace
|
||
|
ws1 = await api.newWorkspace({name: 'ws1'}, 'current');
|
||
|
ws2 = await api.newWorkspace({name: 'ws2'}, 'current');
|
||
|
ws3 = await api.newWorkspace({name: 'ws3'}, 'current');
|
||
|
ws4 = await api.newWorkspace({name: 'ws4'}, 'current');
|
||
|
doc11 = await api.newDoc({name: 'doc11'}, ws1);
|
||
|
doc12 = await api.newDoc({name: 'doc12'}, ws1);
|
||
|
doc21 = await api.newDoc({name: 'doc21'}, ws2);
|
||
|
await api.newDoc({name: 'doc22'}, ws2);
|
||
|
doc31 = await api.newDoc({name: 'doc31'}, ws3);
|
||
|
});
|
||
|
|
||
|
it('hides soft-deleted docs from regular api', async function() {
|
||
|
// This can be too low for running this test directly (when database needs to be created).
|
||
|
this.timeout(10000);
|
||
|
|
||
|
// Check that doc11 is visible via regular api
|
||
|
assert.equal((await api.getDoc(doc11)).name, 'doc11');
|
||
|
assert.typeOf((await api.getDoc(doc11)).removedAt, 'undefined');
|
||
|
assert.deepEqual(docNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws1:doc11', 'ws1:doc12', 'ws2:doc21', 'ws2:doc22', 'ws3:doc31']);
|
||
|
assert.deepEqual(workspaceNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws1', 'ws2', 'ws3', 'ws4']);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws1)), ['doc11', 'doc12']);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws2)), ['doc21', 'doc22']);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws3)), ['doc31']);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws4)), []);
|
||
|
|
||
|
// Soft-delete doc11, leaving one doc in ws1
|
||
|
await api.softDeleteDoc(doc11);
|
||
|
|
||
|
// Check that doc11 is no longer visible via regular api
|
||
|
await assert.isRejected(api.getDoc(doc11), /not found/);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws1)), ['doc12']);
|
||
|
assert.deepEqual(docNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws1:doc12', 'ws2:doc21', 'ws2:doc22', 'ws3:doc31']);
|
||
|
|
||
|
// Check that various related endpoints are forbidden
|
||
|
let docApi = api.getDocAPI(doc11);
|
||
|
await assert.isRejected(docApi.getSnapshots(), /404.*document is deleted/i);
|
||
|
await assert.isRejected(docApi.getRows('Table1'), /404.*document is deleted/i);
|
||
|
await assert.isRejected(docApi.forceReload(), /404.*document is deleted/i);
|
||
|
|
||
|
// Check that doc11 is visible via forRemoved api
|
||
|
assert.equal((await xapi.getDoc(doc11)).name, 'doc11');
|
||
|
assert.typeOf((await xapi.getDoc(doc11)).removedAt, 'string');
|
||
|
assert.deepEqual(docNames(await xapi.getWorkspace(ws1)), ['doc11']);
|
||
|
await assert.isRejected(xapi.getWorkspace(ws2), /not found/);
|
||
|
assert.deepEqual(docNames(await xapi.getOrgWorkspaces('current')),
|
||
|
['ws1:doc11']);
|
||
|
assert.deepEqual(workspaceNames(await xapi.getOrgWorkspaces('current')),
|
||
|
['ws1']);
|
||
|
|
||
|
docApi = xapi.getDocAPI(doc11);
|
||
|
await assert.isFulfilled(docApi.getSnapshots());
|
||
|
await assert.isFulfilled(docApi.getRows('Table1'));
|
||
|
await assert.isFulfilled(docApi.forceReload());
|
||
|
});
|
||
|
|
||
|
it('lists workspaces even with all docs soft-deleted', async function() {
|
||
|
// Soft-delete doc12, leaving ws1 empty
|
||
|
await api.softDeleteDoc(doc12);
|
||
|
// Soft-delete doc31, leaving ws3 empty
|
||
|
await api.softDeleteDoc(doc31);
|
||
|
|
||
|
// Check docs are not visible, but workspaces are
|
||
|
await assert.isRejected(api.getDoc(doc12), /not found/);
|
||
|
await assert.isRejected(api.getDoc(doc31), /not found/);
|
||
|
assert.deepEqual(docNames(await api.getOrgWorkspaces('current')), ['ws2:doc21', 'ws2:doc22']);
|
||
|
assert.deepEqual(workspaceNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws1', 'ws2', 'ws3', 'ws4']);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws1)), []);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws3)), []);
|
||
|
|
||
|
// Check docs are visible via forRemoved api
|
||
|
assert.equal((await xapi.getDoc(doc12)).name, 'doc12');
|
||
|
assert.typeOf((await xapi.getDoc(doc12)).removedAt, 'string');
|
||
|
assert.equal((await xapi.getDoc(doc31)).name, 'doc31');
|
||
|
assert.typeOf((await xapi.getDoc(doc31)).removedAt, 'string');
|
||
|
assert.equal((await xapi.getWorkspace(ws1)).name, 'ws1');
|
||
|
assert.typeOf((await xapi.getWorkspace(ws1)).removedAt, 'undefined');
|
||
|
assert.deepEqual(docNames(await xapi.getWorkspace(ws1)), ['doc11', 'doc12']);
|
||
|
assert.deepEqual(docNames(await xapi.getWorkspace(ws3)), ['doc31']);
|
||
|
await assert.isRejected(xapi.getWorkspace(ws2), /not found/);
|
||
|
assert.deepEqual(docNames(await xapi.getOrgWorkspaces('current')),
|
||
|
['ws1:doc11', 'ws1:doc12', 'ws3:doc31']);
|
||
|
assert.deepEqual(workspaceNames(await xapi.getOrgWorkspaces('current')),
|
||
|
['ws1', 'ws3']);
|
||
|
});
|
||
|
|
||
|
it('can revert soft-deleted docs', async function() {
|
||
|
// Undelete docs
|
||
|
await api.undeleteDoc(doc11);
|
||
|
await api.undeleteDoc(doc12);
|
||
|
await api.undeleteDoc(doc31);
|
||
|
|
||
|
// Check that doc11 is visible via regular api again
|
||
|
assert.equal((await api.getDoc(doc11)).name, 'doc11');
|
||
|
assert.typeOf((await api.getDoc(doc11)).removedAt, 'undefined');
|
||
|
assert.deepEqual(docNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws1:doc11', 'ws1:doc12', 'ws2:doc21', 'ws2:doc22', 'ws3:doc31']);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws1)), ['doc11', 'doc12']);
|
||
|
|
||
|
// Check that no "trash" is visible anymore
|
||
|
assert.deepEqual(docNames(await xapi.getOrgWorkspaces('current')), []);
|
||
|
await assert.isRejected(xapi.getWorkspace(ws1), /not found/);
|
||
|
await assert.isRejected(xapi.getWorkspace(ws2), /not found/);
|
||
|
await assert.isRejected(xapi.getWorkspace(ws3), /not found/);
|
||
|
await assert.isRejected(xapi.getWorkspace(ws4), /not found/);
|
||
|
});
|
||
|
|
||
|
it('hides soft-deleted workspaces from regular api', async function() {
|
||
|
// Soft-delete ws1, ws3, and ws4
|
||
|
await api.softDeleteWorkspace(ws1);
|
||
|
await api.softDeleteWorkspace(ws3);
|
||
|
await api.softDeleteWorkspace(ws4);
|
||
|
|
||
|
// Check that workspaces are no longer visible via regular api
|
||
|
await assert.isRejected(api.getDoc(doc11), /not found/);
|
||
|
await assert.isRejected(api.getWorkspace(ws1), /not found/);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws2)), ['doc21', 'doc22']);
|
||
|
await assert.isRejected(api.getDoc(doc31), /not found/);
|
||
|
await assert.isRejected(api.getWorkspace(ws3), /not found/);
|
||
|
await assert.isRejected(api.getWorkspace(ws4), /not found/);
|
||
|
assert.deepEqual(docNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws2:doc21', 'ws2:doc22']);
|
||
|
|
||
|
// Check that workspaces are visible via forRemoved api
|
||
|
assert.equal((await xapi.getWorkspace(ws1)).name, 'ws1');
|
||
|
assert.typeOf((await xapi.getWorkspace(ws1)).removedAt, 'string');
|
||
|
assert.equal((await xapi.getDoc(doc11)).name, 'doc11');
|
||
|
assert.equal((await xapi.getWorkspace(ws3)).name, 'ws3');
|
||
|
assert.typeOf((await xapi.getWorkspace(ws3)).removedAt, 'string');
|
||
|
assert.equal((await xapi.getWorkspace(ws4)).name, 'ws4');
|
||
|
assert.typeOf((await xapi.getWorkspace(ws4)).removedAt, 'string');
|
||
|
// we may not want the following - may want to explicitly set removedAt
|
||
|
// on docs within a soft-deleted workspace
|
||
|
assert.typeOf((await xapi.getDoc(doc11)).removedAt, 'undefined');
|
||
|
assert.typeOf((await xapi.getDoc(doc12)).removedAt, 'undefined');
|
||
|
assert.typeOf((await xapi.getDoc(doc31)).removedAt, 'undefined');
|
||
|
assert.deepEqual(docNames(await xapi.getWorkspace(ws1)), ['doc11', 'doc12']);
|
||
|
await assert.isRejected(xapi.getWorkspace(ws2), /not found/);
|
||
|
assert.deepEqual(docNames(await xapi.getWorkspace(ws3)), ['doc31']);
|
||
|
assert.deepEqual(docNames(await xapi.getWorkspace(ws4)), []);
|
||
|
assert.deepEqual(docNames(await xapi.getOrgWorkspaces('current')),
|
||
|
['ws1:doc11', 'ws1:doc12', 'ws3:doc31']);
|
||
|
});
|
||
|
|
||
|
it('can combine soft-deleted workspaces and soft-deleted docs', async function() {
|
||
|
// Delete a doc in an undeleted workspace, and in a soft-deleted workspace.
|
||
|
await api.softDeleteDoc(doc21);
|
||
|
await xapi.softDeleteDoc(doc11);
|
||
|
assert.deepEqual(docNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws2:doc22']);
|
||
|
assert.deepEqual(docNames(await xapi.getOrgWorkspaces('current')),
|
||
|
['ws1:doc11', 'ws1:doc12', 'ws2:doc21', 'ws3:doc31']);
|
||
|
});
|
||
|
|
||
|
it('can revert soft-deleted workspaces', async function() {
|
||
|
// Undelete workspaces and docs
|
||
|
await api.undeleteWorkspace(ws1);
|
||
|
await api.undeleteWorkspace(ws3);
|
||
|
await api.undeleteWorkspace(ws4);
|
||
|
await api.undeleteDoc(doc21);
|
||
|
await api.undeleteDoc(doc11);
|
||
|
|
||
|
// Check that docs are visible via regular api again
|
||
|
assert.equal((await api.getDoc(doc11)).name, 'doc11');
|
||
|
assert.typeOf((await api.getDoc(doc11)).removedAt, 'undefined');
|
||
|
assert.deepEqual(docNames(await api.getOrgWorkspaces('current')),
|
||
|
['ws1:doc11', 'ws1:doc12', 'ws2:doc21', 'ws2:doc22', 'ws3:doc31']);
|
||
|
assert.deepEqual(docNames(await api.getWorkspace(ws1)), ['doc11', 'doc12']);
|
||
|
|
||
|
// Check that no "trash" is visible anymore
|
||
|
assert.deepEqual(docNames(await xapi.getOrgWorkspaces('current')), []);
|
||
|
});
|
||
|
|
||
|
|
||
|
// This checks that the following problem is fixed:
|
||
|
// If a document is deleted in a workspace with many other documents, the
|
||
|
// deletion used to take an unreasonable length of time.
|
||
|
it('deletes documents reasonably quickly', async function() {
|
||
|
this.timeout(15000);
|
||
|
const ws = await api.newWorkspace({name: 'speedTest'}, 'testy');
|
||
|
// Create a batch of many documents.
|
||
|
const docIds = await Promise.all(new Array(50).fill(0).map(() => api.newDoc({name: 'doc'}, ws)));
|
||
|
// Explicitly set users on some of the documents.
|
||
|
await api.updateDocPermissions(docIds[5], {
|
||
|
users: {
|
||
|
'test1@getgrist.com': 'viewers',
|
||
|
}
|
||
|
});
|
||
|
await api.updateDocPermissions(docIds[10], {
|
||
|
users: {
|
||
|
'test2@getgrist.com': 'owners',
|
||
|
'test3@getgrist.com': 'editors',
|
||
|
}
|
||
|
});
|
||
|
const userRef = (email: string) => home.dbManager.getUserByLogin(email).then((user) => user!.ref);
|
||
|
const idTest1 = (await home.dbManager.getUserByLogin("test1@getgrist.com"))!.id;
|
||
|
const idTest2 = (await home.dbManager.getUserByLogin("test2@getgrist.com"))!.id;
|
||
|
const idTest3 = (await home.dbManager.getUserByLogin("test3@getgrist.com"))!.id;
|
||
|
// Create one extra document, with one extra user.
|
||
|
const extraDocId = await api.newDoc({name: 'doc'}, ws);
|
||
|
await api.updateDocPermissions(extraDocId, {
|
||
|
users: { 'kiwi@getgrist.com': 'viewers' }
|
||
|
});
|
||
|
assert.deepEqual(await api.getWorkspaceAccess(ws), {
|
||
|
"maxInheritedRole": "owners",
|
||
|
"users": [
|
||
|
{
|
||
|
"id": 1,
|
||
|
"name": "Chimpy",
|
||
|
"email": "chimpy@getgrist.com",
|
||
|
"ref": await userRef("chimpy@getgrist.com"),
|
||
|
"picture": null,
|
||
|
"access": "owners",
|
||
|
"parentAccess": "owners",
|
||
|
"isMember": true,
|
||
|
},
|
||
|
{
|
||
|
"id": 2,
|
||
|
"name": "Kiwi",
|
||
|
"email": "kiwi@getgrist.com",
|
||
|
"ref": await userRef("kiwi@getgrist.com"),
|
||
|
"picture": null,
|
||
|
"access": "guests",
|
||
|
"parentAccess": null,
|
||
|
"isMember": false,
|
||
|
},
|
||
|
{
|
||
|
"id": idTest1,
|
||
|
"name": "",
|
||
|
"email": "test1@getgrist.com",
|
||
|
"ref": await userRef("test1@getgrist.com"),
|
||
|
"picture": null,
|
||
|
"access": "guests",
|
||
|
"parentAccess": null,
|
||
|
"isMember": false,
|
||
|
},
|
||
|
{
|
||
|
"id": idTest2,
|
||
|
"name": "",
|
||
|
"email": "test2@getgrist.com",
|
||
|
"ref": await userRef("test2@getgrist.com"),
|
||
|
"picture": null,
|
||
|
"access": "guests",
|
||
|
"parentAccess": null,
|
||
|
"isMember": false,
|
||
|
},
|
||
|
{
|
||
|
"id": idTest3,
|
||
|
"name": "",
|
||
|
"email": "test3@getgrist.com",
|
||
|
"ref": await userRef("test3@getgrist.com"),
|
||
|
"picture": null,
|
||
|
"access": "guests",
|
||
|
"parentAccess": null,
|
||
|
"isMember": false,
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
// Delete the batch of documents, retaining the one extra.
|
||
|
await Promise.all(docIds.map(docId => api.deleteDoc(docId)));
|
||
|
// Make sure the guest from the extra doc is retained, while all others evaporate.
|
||
|
assert.deepEqual(await api.getWorkspaceAccess(ws), {
|
||
|
"maxInheritedRole": "owners",
|
||
|
"users": [
|
||
|
{
|
||
|
"id": 1,
|
||
|
"name": "Chimpy",
|
||
|
"email": "chimpy@getgrist.com",
|
||
|
"ref": await userRef("chimpy@getgrist.com"),
|
||
|
"picture": null,
|
||
|
"access": "owners",
|
||
|
"parentAccess": "owners",
|
||
|
"isMember": true,
|
||
|
},
|
||
|
{
|
||
|
"id": 2,
|
||
|
"name": "Kiwi",
|
||
|
"email": "kiwi@getgrist.com",
|
||
|
"ref": await userRef("kiwi@getgrist.com"),
|
||
|
"picture": null,
|
||
|
"access": "guests",
|
||
|
"parentAccess": null,
|
||
|
"isMember": false,
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('does not interfere with DocAuthKey-based caching', async function() {
|
||
|
const info = await api.getSessionActive();
|
||
|
|
||
|
// Flush cache, then try to access doc11 as a removed doc.
|
||
|
home.dbManager.flushDocAuthCache();
|
||
|
await assert.isRejected(xapi.getDoc(doc11), /not found/);
|
||
|
|
||
|
// Check that cached authentication is correct.
|
||
|
const auth = await home.dbManager.getDocAuthCached({urlId: doc11, userId: info.user.id, org});
|
||
|
assert.equal(auth.access, 'owners');
|
||
|
});
|
||
|
|
||
|
it('respects permanent flag on /api/docs/:did/remove', async function() {
|
||
|
await bapi.testRequest(`${api.getBaseUrl()}/api/docs/${doc11}/remove`,
|
||
|
{method: 'POST'});
|
||
|
await bapi.testRequest(`${api.getBaseUrl()}/api/docs/${doc12}/remove?permanent=1`,
|
||
|
{method: 'POST'});
|
||
|
await api.undeleteDoc(doc11);
|
||
|
await assert.isRejected(api.undeleteDoc(doc12), /not found/);
|
||
|
});
|
||
|
|
||
|
it('respects permanent flag on /api/workspaces/:wid/remove', async function() {
|
||
|
await bapi.testRequest(`${api.getBaseUrl()}/api/workspaces/${ws1}/remove`,
|
||
|
{method: 'POST'});
|
||
|
await bapi.testRequest(`${api.getBaseUrl()}/api/workspaces/${ws2}/remove?permanent=1`,
|
||
|
{method: 'POST'});
|
||
|
await api.undeleteWorkspace(ws1);
|
||
|
await assert.isRejected(api.undeleteWorkspace(ws2), /not found/);
|
||
|
});
|
||
|
|
||
|
it('can hard-delete a soft-deleted document', async function() {
|
||
|
const tmp1 = await api.newDoc({name: 'tmp1'}, ws1);
|
||
|
const tmp2 = await api.newDoc({name: 'tmp2'}, ws1);
|
||
|
await api.softDeleteDoc(tmp1);
|
||
|
await api.deleteDoc(tmp1);
|
||
|
await api.softDeleteDoc(tmp2);
|
||
|
await bapi.testRequest(`${api.getBaseUrl()}/api/docs/${tmp2}/remove?permanent=1`,
|
||
|
{method: 'POST'});
|
||
|
await assert.isRejected(api.undeleteDoc(tmp1));
|
||
|
await assert.isRejected(api.undeleteDoc(tmp2));
|
||
|
});
|
||
|
|
||
|
it('can hard-delete a soft-deleted workspace', async function() {
|
||
|
const tmp1 = await api.newWorkspace({name: 'tmp1'}, 'current');
|
||
|
const tmp2 = await api.newWorkspace({name: 'tmp2'}, 'current');
|
||
|
await api.softDeleteWorkspace(tmp1);
|
||
|
await api.deleteWorkspace(tmp1);
|
||
|
await api.softDeleteWorkspace(tmp2);
|
||
|
await bapi.testRequest(`${api.getBaseUrl()}/api/workspaces/${tmp2}/remove?permanent=1`,
|
||
|
{method: 'POST'});
|
||
|
await assert.isRejected(api.undeleteWorkspace(tmp1));
|
||
|
await assert.isRejected(api.undeleteWorkspace(tmp2));
|
||
|
});
|
||
|
|
||
|
// This checks that the following problem is fixed:
|
||
|
// If I shared a doc with a friend, and then soft-deleted a doc in the same workspace,
|
||
|
// that friend used to see the workspace in their trash (empty, but there).
|
||
|
it('does not show workspaces for docs user does not have access to', async function() {
|
||
|
// Make two docs in a workspace, and share one with a friend.
|
||
|
const ws = await api.newWorkspace({name: 'wsWithSharing'}, 'testy');
|
||
|
const shared = await api.newDoc({name: 'shared'}, ws);
|
||
|
const unshared = await api.newDoc({name: 'unshared'}, ws);
|
||
|
await api.updateDocPermissions(shared, {
|
||
|
users: { 'charon@getgrist.com': 'viewers' }
|
||
|
});
|
||
|
|
||
|
// Check the friend sees nothing in their trash.
|
||
|
const charon = await home.createHomeApi('charon', 'docs');
|
||
|
let result = await charon.forRemoved().getOrgWorkspaces('testy');
|
||
|
assert.lengthOf(result, 0);
|
||
|
|
||
|
// Deleted the unshared doc, and check the friend still sees nothing in their trash.
|
||
|
await api.softDeleteDoc(unshared);
|
||
|
result = await charon.forRemoved().getOrgWorkspaces('testy');
|
||
|
assert.lengthOf(result, 0);
|
||
|
|
||
|
// Deleted the shared doc, and check the friend sees it in trash.
|
||
|
// (There might be a case for only owners seeing it? i.e. you see something in
|
||
|
// trash if you have the power to restore it? But in a team site it might be
|
||
|
// useful to have some insight into what happened to a doc you can view.)
|
||
|
await api.softDeleteDoc(shared);
|
||
|
result = await charon.forRemoved().getOrgWorkspaces('testy');
|
||
|
assert.deepEqual(docNames(result), ['wsWithSharing:shared']);
|
||
|
});
|
||
|
});
|
||
|
});
|