Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
293 lines
9.9 KiB
TypeScript
293 lines
9.9 KiB
TypeScript
import { expect } from 'chai';
|
|
import proxyquireRaw from 'proxyquire';
|
|
import * as sinon from 'sinon';
|
|
|
|
const proxyquire = proxyquireRaw.noCallThru();
|
|
|
|
type Stubbed = { [k: string]: any };
|
|
|
|
describe('eraseTeam (TypeScript) module', () => {
|
|
let sandbox: sinon.SinonSandbox;
|
|
let stubs: Stubbed;
|
|
let subject: any;
|
|
|
|
beforeEach(() => {
|
|
sandbox = sinon.createSandbox();
|
|
|
|
stubs = {
|
|
'Team': {
|
|
getMatchingTeamRooms: sandbox.stub().resolves([]),
|
|
unsetTeamIdOfRooms: sandbox.stub().resolves(),
|
|
removeAllMembersFromTeam: sandbox.stub().resolves(),
|
|
deleteById: sandbox.stub().resolves(),
|
|
},
|
|
'Users': {
|
|
findOneById: sandbox.stub().resolves(null),
|
|
},
|
|
'Rooms': {
|
|
findOneById: sandbox.stub().resolves(null),
|
|
},
|
|
'eraseRoomStub': sandbox.stub().resolves(true),
|
|
'deleteRoomStub': sandbox.stub().resolves(),
|
|
'../../lib/logger/system': {
|
|
SystemLogger: {
|
|
error: sandbox.stub(),
|
|
},
|
|
},
|
|
'@rocket.chat/apps': {
|
|
AppEvents: {
|
|
IPreRoomDeletePrevent: 'IPreRoomDeletePrevent',
|
|
IPostRoomDeleted: 'IPostRoomDeleted',
|
|
},
|
|
Apps: {
|
|
self: {
|
|
isLoaded: () => false,
|
|
triggerEvent: sandbox.stub().resolves(false),
|
|
},
|
|
},
|
|
},
|
|
'@rocket.chat/models': {
|
|
Rooms: {
|
|
findOneById: (...args: any[]) => stubs.Rooms.findOneById(...args),
|
|
},
|
|
Users: {
|
|
findOneById: (...args: any[]) => stubs.Users.findOneById(...args),
|
|
},
|
|
},
|
|
'@rocket.chat/core-services': {
|
|
MeteorError: (function () {
|
|
class MeteorError extends Error {
|
|
public error: string | undefined;
|
|
|
|
public details: any;
|
|
|
|
constructor(message?: string, error?: string, details?: any) {
|
|
super(message);
|
|
this.error = error;
|
|
this.details = details;
|
|
}
|
|
}
|
|
return MeteorError;
|
|
})(),
|
|
},
|
|
};
|
|
|
|
subject = proxyquire('./eraseTeam', {
|
|
'@rocket.chat/apps': stubs['@rocket.chat/apps'],
|
|
'@rocket.chat/models': stubs['@rocket.chat/models'],
|
|
'../../lib/eraseRoom': { __esModule: true, eraseRoom: stubs.eraseRoomStub },
|
|
'../../lib/rooms/deleteRoom': { __esModule: true, deleteRoom: stubs.deleteRoomStub },
|
|
'../../lib/logger/system': stubs['../../lib/logger/system'],
|
|
'@rocket.chat/core-services': {
|
|
MeteorError: stubs['@rocket.chat/core-services'].MeteorError,
|
|
Team: stubs.Team,
|
|
},
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
sandbox.restore();
|
|
});
|
|
|
|
describe('eraseTeamShared', () => {
|
|
it('throws when user is undefined', async () => {
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
await expect(subject.eraseTeamShared(undefined, { _id: 'team1', roomId: 'teamRoom' }, [], () => {})).to.be.rejected;
|
|
});
|
|
|
|
it('erases provided rooms (excluding team.roomId) and cleans up team', async () => {
|
|
const team = { _id: 'team-id', roomId: 'team-room' };
|
|
const user = { _id: 'user-1', username: 'u' };
|
|
stubs.Team.getMatchingTeamRooms.resolves(['room-1', 'room-2', team.roomId]);
|
|
stubs.Rooms.findOneById.withArgs(team.roomId).resolves({ _id: team.roomId });
|
|
|
|
const erased: Array<{ rid: string; user: any }> = [];
|
|
const eraseRoomFn = async (rid: string, user: any) => {
|
|
erased.push({ rid, user });
|
|
};
|
|
|
|
await subject.eraseTeamShared(user, team, ['room-1', 'room-2', team.roomId], eraseRoomFn);
|
|
|
|
expect(erased.some((r) => r.rid === 'room-1')).to.be.true;
|
|
expect(erased.some((r) => r.rid === 'room-2')).to.be.true;
|
|
sinon.assert.calledOnce(stubs.Team.unsetTeamIdOfRooms);
|
|
expect(erased.some((r) => r.rid === team.roomId)).to.be.true;
|
|
sinon.assert.calledOnce(stubs.Team.removeAllMembersFromTeam);
|
|
sinon.assert.calledOnce(stubs.Team.deleteById);
|
|
});
|
|
|
|
it('skips the main room but still deletes the team when the main room no longer exists', async () => {
|
|
const team = { _id: 'team-id', roomId: 'team-room' };
|
|
const user = { _id: 'user-1', username: 'u' };
|
|
stubs.Team.getMatchingTeamRooms.resolves([]);
|
|
stubs.Rooms.findOneById.withArgs(team.roomId).resolves(null);
|
|
|
|
const eraseRoomFn = sandbox.stub().resolves();
|
|
|
|
await subject.eraseTeamShared(user, team, [], eraseRoomFn);
|
|
|
|
sinon.assert.notCalled(eraseRoomFn);
|
|
sinon.assert.calledOnce(stubs.Team.unsetTeamIdOfRooms);
|
|
sinon.assert.calledOnce(stubs.Team.removeAllMembersFromTeam);
|
|
sinon.assert.calledOnce(stubs.Team.deleteById);
|
|
});
|
|
});
|
|
|
|
describe('eraseTeam', () => {
|
|
it('calls eraseRoom for the team main room (via eraseTeamShared)', async () => {
|
|
const team = { _id: 't1', roomId: 't-room' };
|
|
const user = { _id: 'u1', username: 'u', name: 'User' };
|
|
stubs.Team.getMatchingTeamRooms.resolves([]);
|
|
stubs.Rooms.findOneById.withArgs(team.roomId).resolves({ _id: team.roomId });
|
|
const { eraseRoomStub } = stubs;
|
|
eraseRoomStub.resolves(true);
|
|
|
|
await subject.eraseTeam(user, team, []);
|
|
|
|
sinon.assert.calledWith(eraseRoomStub, team.roomId, user);
|
|
});
|
|
});
|
|
|
|
describe('eraseTeamOnRelinquishRoomOwnerships', () => {
|
|
it('returns successfully deleted room ids only', async () => {
|
|
const team = { _id: 't1', roomId: 't-room' };
|
|
stubs.Team.getMatchingTeamRooms.resolves(['r1', 'r2']);
|
|
|
|
stubs.Rooms.findOneById.withArgs('r1').resolves({ _id: 'r1', federated: false });
|
|
stubs.Rooms.findOneById.withArgs('r2').resolves(null);
|
|
|
|
stubs.deleteRoomStub.withArgs('r1').resolves();
|
|
stubs.deleteRoomStub.withArgs('r2').rejects(new Error('boom'));
|
|
|
|
const base = proxyquire('./eraseTeam', {
|
|
'@rocket.chat/apps': stubs['@rocket.chat/apps'],
|
|
'@rocket.chat/models': stubs['@rocket.chat/models'],
|
|
'../../lib/eraseRoom': { __esModule: true, eraseRoom: stubs.eraseRoomStub },
|
|
'../../lib/rooms/deleteRoom': { __esModule: true, deleteRoom: stubs.deleteRoomStub },
|
|
'../../lib/logger/system': stubs['../../lib/logger/system'],
|
|
'@rocket.chat/core-services': {
|
|
MeteorError: stubs['@rocket.chat/core-services'].MeteorError,
|
|
Team: stubs.Team,
|
|
},
|
|
});
|
|
|
|
const result: string[] = await base.eraseTeamOnRelinquishRoomOwnerships(team, ['r1', 'r2']);
|
|
expect(result).to.be.an('array').that.includes('r1').and.not.includes('r2');
|
|
});
|
|
});
|
|
|
|
describe('eraseRoomLooseValidation', () => {
|
|
let baseModule: any;
|
|
|
|
beforeEach(() => {
|
|
baseModule = proxyquire('./eraseTeam', {
|
|
'@rocket.chat/apps': stubs['@rocket.chat/apps'],
|
|
'@rocket.chat/models': stubs['@rocket.chat/models'],
|
|
'../../lib/eraseRoom': { __esModule: true, eraseRoom: stubs.eraseRoomStub },
|
|
'../../lib/rooms/deleteRoom': { __esModule: true, deleteRoom: stubs.deleteRoomStub },
|
|
'../../lib/logger/system': stubs['../../lib/logger/system'],
|
|
'@rocket.chat/core-services': {
|
|
MeteorError: stubs['@rocket.chat/core-services'].MeteorError,
|
|
Team: stubs.Team,
|
|
},
|
|
});
|
|
});
|
|
|
|
it('returns false when room not found', async () => {
|
|
stubs.Rooms.findOneById.resolves(null);
|
|
const res = await baseModule.eraseRoomLooseValidation('does-not-exist');
|
|
expect(res).to.be.false;
|
|
});
|
|
|
|
it('returns false when room.federated is true', async () => {
|
|
stubs.Rooms.findOneById.resolves({ _id: 'r', federated: true });
|
|
const res = await baseModule.eraseRoomLooseValidation('r');
|
|
expect(res).to.be.false;
|
|
});
|
|
|
|
it('returns false when app pre-delete prevents deletion', async () => {
|
|
const listenerStub = sandbox.stub().resolves(true);
|
|
const AppsStub = {
|
|
AppEvents: stubs['@rocket.chat/apps'].AppEvents,
|
|
Apps: {
|
|
self: {
|
|
isLoaded: () => true,
|
|
triggerEvent: listenerStub,
|
|
},
|
|
},
|
|
};
|
|
|
|
const m = proxyquire('./eraseTeam', {
|
|
'@rocket.chat/apps': AppsStub,
|
|
'@rocket.chat/models': stubs['@rocket.chat/models'],
|
|
'../../lib/eraseRoom': { __esModule: true, eraseRoom: stubs.eraseRoomStub },
|
|
'../../lib/rooms/deleteRoom': { __esModule: true, deleteRoom: stubs.deleteRoomStub },
|
|
'../../lib/logger/system': stubs['../../lib/logger/system'],
|
|
'@rocket.chat/core-services': {
|
|
MeteorError: stubs['@rocket.chat/core-services'].MeteorError,
|
|
Team: stubs.Team,
|
|
},
|
|
});
|
|
|
|
stubs.Rooms.findOneById.resolves({ _id: 'r', federated: false });
|
|
|
|
const res = await m.eraseRoomLooseValidation('r');
|
|
expect(listenerStub.calledOnce).to.be.true;
|
|
expect(res).to.be.false;
|
|
});
|
|
|
|
it('logs and returns false when deleteRoom throws', async () => {
|
|
stubs.Rooms.findOneById.resolves({ _id: 'r', federated: false });
|
|
stubs.deleteRoomStub.rejects(new Error('boom'));
|
|
|
|
const m = proxyquire('./eraseTeam', {
|
|
'@rocket.chat/apps': stubs['@rocket.chat/apps'],
|
|
'@rocket.chat/models': stubs['@rocket.chat/models'],
|
|
'../../lib/eraseRoom': { __esModule: true, eraseRoom: stubs.eraseRoomStub },
|
|
'../../lib/rooms/deleteRoom': { __esModule: true, deleteRoom: stubs.deleteRoomStub },
|
|
'../../lib/logger/system': stubs['../../lib/logger/system'],
|
|
'@rocket.chat/core-services': {
|
|
MeteorError: stubs['@rocket.chat/core-services'].MeteorError,
|
|
Team: stubs.Team,
|
|
},
|
|
});
|
|
|
|
const res = await m.eraseRoomLooseValidation('r');
|
|
expect(res).to.be.false;
|
|
sinon.assert.calledOnce(stubs['../../lib/logger/system'].SystemLogger.error);
|
|
});
|
|
|
|
it('calls post-deleted event and returns true on success', async () => {
|
|
const roomEventStub = sandbox.stub().onFirstCall().resolves(false).onSecondCall().resolves();
|
|
const AppsStub = {
|
|
AppEvents: stubs['@rocket.chat/apps'].AppEvents,
|
|
Apps: {
|
|
self: {
|
|
isLoaded: () => true,
|
|
triggerEvent: roomEventStub,
|
|
},
|
|
},
|
|
};
|
|
|
|
stubs.deleteRoomStub.resolves();
|
|
const m = proxyquire('./eraseTeam', {
|
|
'@rocket.chat/apps': AppsStub,
|
|
'@rocket.chat/models': stubs['@rocket.chat/models'],
|
|
'../../lib/eraseRoom': { __esModule: true, eraseRoom: stubs.eraseRoomStub },
|
|
'../../lib/rooms/deleteRoom': { __esModule: true, deleteRoom: stubs.deleteRoomStub },
|
|
'../../lib/logger/system': stubs['../../lib/logger/system'],
|
|
'@rocket.chat/core-services': {
|
|
MeteorError: stubs['@rocket.chat/core-services'].MeteorError,
|
|
Team: stubs.Team,
|
|
},
|
|
});
|
|
|
|
stubs.Rooms.findOneById.resolves({ _id: 'r', federated: false });
|
|
|
|
const res = await m.eraseRoomLooseValidation('r');
|
|
expect(res).to.be.true;
|
|
sinon.assert.calledTwice(roomEventStub);
|
|
});
|
|
});
|
|
});
|