scratch-www/test/unit/redux/studio-permissions.test.js

617 lines
20 KiB
JavaScript
Raw Normal View History

2021-03-23 15:19:01 -04:00
import {
selectCanEditInfo,
selectCanAddProjects,
selectShowCommentComposer,
selectCanDeleteComment,
selectCanDeleteCommentWithoutConfirm,
selectCanReportComment,
2021-04-16 13:22:35 -04:00
selectCanRestoreComment,
selectCanFollowStudio,
selectCanEditCommentsAllowed,
2021-05-03 10:52:04 -04:00
selectCanEditOpenToAll,
selectShowCuratorInvite,
selectCanInviteCurators,
2021-05-14 12:37:05 -04:00
selectCanRemoveCurator,
2021-05-03 10:52:04 -04:00
selectCanRemoveManager,
selectCanPromoteCurators,
selectCanRemoveProject,
2021-08-19 11:59:08 -04:00
selectCanTransfer,
selectShowCommentsList,
selectShowCommentsGloballyOffError,
selectShowProjectMuteError,
selectShowCuratorMuteError,
selectShowEditMuteError
2021-04-16 13:22:35 -04:00
} from '../../../src/redux/studio-permissions';
2021-03-23 15:19:01 -04:00
2021-04-16 13:22:35 -04:00
import {getInitialState as getInitialStudioState} from '../../../src/redux/studio';
2021-06-15 17:34:05 -04:00
import {getInitialState as getInitialSessionState,
selectUserId, selectUsername, Status} from '../../../src/redux/session';
import {sessions, studios} from '../../helpers/state-fixtures.json';
2021-03-23 15:19:01 -04:00
let state;
2021-03-23 15:19:01 -04:00
const setStateByRole = (role) => {
switch (role) {
case 'admin':
state.session = sessions.user1Admin;
break;
case 'curator':
state.studio = studios.isCurator;
state.session = sessions.user1Social;
break;
case 'manager':
state.studio = studios.isManager;
state.session = sessions.user1Social;
break;
case 'creator':
state.studio = studios.creator1;
state.session = sessions.user1Social;
break;
case 'logged in':
state.session = sessions.user1Social;
break;
case 'unconfirmed':
state.session = sessions.user1;
break;
case 'logged out': // Default state set in beforeEach
break;
2021-05-03 10:52:04 -04:00
case 'invited':
state.studio = studios.isInvited;
break;
case 'muted creator':
state.studio = studios.creator1;
state.session = sessions.user1Muted;
break;
case 'muted manager':
state.studio = studios.isManager;
state.session = sessions.user1Muted;
break;
case 'muted curator':
state.studio = studios.isCurator;
state.session = sessions.user1Muted;
break;
case 'muted logged in':
state.session = sessions.user1Muted;
break;
default:
throw new Error('Unknown user role in test: ' + role);
}
};
2021-03-23 15:19:01 -04:00
beforeEach(() => {
state = {
session: getInitialSessionState(),
studio: getInitialStudioState()
};
});
2021-03-23 15:19:01 -04:00
describe('studio info', () => {
describe('can edit studio info', () => {
test.each([
['admin', true],
['curator', false],
['manager', false],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanEditInfo(state)).toBe(expected);
2021-03-23 15:19:01 -04:00
});
});
});
describe('studio projects', () => {
describe('can add project, not open to all', () => {
test.each([
['admin', false],
['curator', true],
['manager', true],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanAddProjects(state)).toBe(expected);
2021-03-23 15:19:01 -04:00
});
});
describe('can add project, open to all', () => {
test.each([
['logged in', true],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
state.studio.openToAll = true;
expect(selectCanAddProjects(state)).toBe(expected);
2021-03-23 15:19:01 -04:00
});
});
2021-05-03 10:52:04 -04:00
describe('can remove projects', () => {
test.each([
['admin', true],
['curator', false], // false for projects that were not added by them, see below
2021-05-03 10:52:04 -04:00
['manager', true],
['creator', true],
['logged in', false], // false for projects that are not theirs, see below
2021-05-03 10:52:04 -04:00
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
2021-05-03 10:52:04 -04:00
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanRemoveProject(state, 'not-me', 'not-me')).toBe(expected);
});
test('curators can remove projects they added', () => {
setStateByRole('curator');
const addedBy = selectUserId(state);
expect(selectCanRemoveProject(state, 'not-me', addedBy)).toBe(true);
});
test('curators can also remove projects they own that they did not add', () => {
setStateByRole('curator');
const creator = selectUsername(state);
expect(selectCanRemoveProject(state, creator, 'not-me')).toBe(true);
});
test('logged in users can only remove projects they own', () => {
setStateByRole('logged in');
const creator = selectUsername(state);
expect(selectCanRemoveProject(state, creator, 'not-me')).toBe(true);
2021-05-03 10:52:04 -04:00
});
});
});
2021-03-23 15:19:01 -04:00
describe('studio comments', () => {
describe('showing comment composer', () => {
test.each([
['logged in', true],
['unconfirmed', false],
['logged out', false],
['muted creator', true], // comment composer is there, but contains muted ComposeStatus
['muted logged in', true]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectShowCommentComposer(state)).toBe(expected);
2021-03-23 15:19:01 -04:00
});
});
describe('can report comment', () => {
test.each([
['logged in', true],
['unconfirmed', true],
['logged out', false],
['muted creator', true],
['muted logged in', true]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanReportComment(state, 'not me')).toBe(expected);
});
test('cannot report your own comment', () => {
setStateByRole('logged in');
const loggedInUsername = selectUsername(state);
expect(selectCanReportComment(state, loggedInUsername)).toBe(false);
2021-03-23 15:19:01 -04:00
});
});
describe('can delete others comments', () => {
test.each([
['admin', true],
['curator', false],
['manager', false],
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanDeleteComment(state, 'not me')).toBe(expected);
});
});
describe('can delete my own comment', () => {
test.each([
['admin', true],
['curator', false],
['manager', true],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', true],
['muted manager', true],
['muted curator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
const loggedInUsername = selectUsername(state);
expect(selectCanDeleteComment(state, loggedInUsername)).toBe(expected);
2021-03-23 15:19:01 -04:00
});
});
describe('can delete comment without confirmation', () => {
test.each([
['admin', true],
['curator', false],
['manager', false],
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanDeleteCommentWithoutConfirm(state)).toBe(expected);
2021-03-23 15:19:01 -04:00
});
});
describe('can restore a comment', () => {
test.each([
['admin', true],
['curator', false],
['manager', false],
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanRestoreComment(state)).toBe(expected);
});
});
describe('can follow a studio', () => {
test.each([
['logged in', true],
['unconfirmed', true],
['logged out', false],
['muted creator', true],
['muted logged in', true]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanFollowStudio(state)).toBe(expected);
});
});
describe('can set "comments allowed" on a studio', () => {
test.each([
['admin', true],
['curator', false],
['manager', false],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanEditCommentsAllowed(state)).toBe(expected);
});
});
describe('can set "open to all" on a studio', () => {
test.each([
['admin', false],
['curator', false],
['manager', true],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanEditOpenToAll(state)).toBe(expected);
});
});
});
describe('studio members', () => {
describe('can accept invitation', () => {
test.each([
['admin', false],
['curator', false],
['manager', false],
['creator', false],
['invited', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectShowCuratorInvite(state)).toBe(expected);
2021-05-03 10:52:04 -04:00
});
});
describe('can promote curators', () => {
test.each([
['admin', false],
['curator', false],
['manager', true],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanPromoteCurators(state)).toBe(expected);
2021-05-03 10:52:04 -04:00
});
});
describe('can remove curators', () => {
test.each([
['admin', true],
2021-05-14 12:37:05 -04:00
['curator', false], // except themselves, see test below
['manager', true],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
2021-05-14 12:37:05 -04:00
expect(selectCanRemoveCurator(state, 'others-username')).toBe(expected);
});
test('curators can remove themselves', () => {
setStateByRole('curator');
const loggedInUsername = selectUsername(state);
expect(selectCanRemoveCurator(state, loggedInUsername)).toBe(true);
2021-05-03 10:52:04 -04:00
});
});
describe('can remove managers', () => {
test.each([
['admin', true],
['curator', false],
['manager', true],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanRemoveManager(state, '123')).toBe(expected);
2021-05-03 10:52:04 -04:00
});
describe('nobody can remove the studio creator', () => {
2021-05-03 10:52:04 -04:00
test.each([
['admin', false],
['curator', false],
['manager', false],
2021-05-03 10:52:04 -04:00
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
2021-05-03 10:52:04 -04:00
])('%s: %s', (role, expected) => {
setStateByRole(role);
state.studio = {...state.studio, owner: 'the creator'};
expect(selectCanRemoveManager(state, 'the creator')).toBe(expected);
2021-05-03 10:52:04 -04:00
});
});
});
describe('can invite curators', () => {
test.each([
['admin', false],
['curator', false],
['manager', true],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectCanInviteCurators(state)).toBe(expected);
});
});
2021-08-19 11:59:08 -04:00
describe('can transfer host', () => {
test.each([
['admin', true],
['curator', false],
['manager', false],
['creator', true],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', true], // Muted users do not see the transfer UI
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
state.studio = {...state.studio, managers: 2, classroomId: null};
// Only admin and host see the option to transfer the current host
expect(selectCanTransfer(state, state.studio.owner)).toBe(expected);
// Nobody sees the option to transfer a manager who is not the host
expect(selectCanTransfer(state, 123)).toBe(false);
// Nobody can transfer classroom studios
state.studio = {...state.studio, classroomId: 1};
expect(selectCanTransfer(state, state.studio.owner)).toBe(false);
});
});
2021-03-23 15:19:01 -04:00
});
describe('studio mute errors', () => {
describe('should show projects mute error', () => {
test.each([
['admin', false],
['curator', false],
['manager', false],
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', true],
['muted manager', true],
['muted curator', true],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectShowProjectMuteError(state)).toBe(expected);
});
});
describe('should show projects mute error, open to all', () => {
test.each([
['admin', false],
['curator', false],
['manager', false],
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', true],
['muted manager', true],
['muted curator', true],
['muted logged in', true]
])('%s: %s', (role, expected) => {
setStateByRole(role);
state.studio.openToAll = true;
expect(selectShowProjectMuteError(state)).toBe(expected);
});
});
describe('should show curators mute error', () => {
test.each([
['admin', false],
['curator', false],
['manager', false],
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', true],
['muted manager', true],
['muted curator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectShowCuratorMuteError(state)).toBe(expected);
});
});
describe('should show edit info mute error', () => {
test.each([
['admin', false],
['curator', false],
['manager', false],
['creator', false],
['logged in', false],
['unconfirmed', false],
['logged out', false],
['muted creator', true],
['muted manager', false],
['muted curator', false],
['muted logged in', false]
])('%s: %s', (role, expected) => {
setStateByRole(role);
expect(selectShowEditMuteError(state)).toBe(expected);
});
});
describe('show comments list selector', () => {
test('show comments is true', () => {
const thisSession = {
status: Status.FETCHED,
session: {
flags: {
gallery_comments_enabled: true
}
}
};
state.session = thisSession;
expect(selectShowCommentsList(state)).toBe(true);
});
test('show comments is false because feature flag is false', () => {
const thisSession = {
status: Status.FETCHED,
session: {
flags: {
gallery_comments_enabled: false
}
}
};
state.session = thisSession;
expect(selectShowCommentsList(state)).toBe(false);
});
test('show comments is false because session not fetched', () => {
const thisSession = {
status: Status.NOT_FETCHED,
session: {
flags: {
gallery_comments_enabled: true
}
}
};
state.session = thisSession;
expect(selectShowCommentsList(state)).toBe(false);
});
});
describe('show comments globally off error', () => {
test('show comments off error because feature flag is false', () => {
const thisSession = {
status: Status.FETCHED,
session: {
flags: {
gallery_comments_enabled: false
}
}
};
state.session = thisSession;
expect(selectShowCommentsGloballyOffError(state)).toBe(true);
});
test('Do not show comments off error because feature flag is on ', () => {
const thisSession = {
status: Status.FETCHED,
session: {
flags: {
gallery_comments_enabled: true
}
}
};
state.session = thisSession;
expect(selectShowCommentsGloballyOffError(state)).toBe(false);
});
test('Do not show comments off error because session not fetched ', () => {
const thisSession = {
status: Status.NOT_FETCHED,
session: {
flags: {
gallery_comments_enabled: false
}
}
};
state.session = thisSession;
expect(selectShowCommentsGloballyOffError(state)).toBe(false);
});
});
});