Add studio selector and tests

This commit is contained in:
Paul Kaplan 2021-03-23 15:19:01 -04:00
parent f03fbb503b
commit 99195d6df3
2 changed files with 131 additions and 2 deletions

View file

@ -3,6 +3,9 @@ const keyMirror = require('keymirror');
const api = require('../lib/api'); const api = require('../lib/api');
const log = require('../lib/log'); const log = require('../lib/log');
const {selectUserId} = require('./session');
const {selectIsAdmin, selectIsSocial} = require('./permissions');
const Status = keyMirror({ const Status = keyMirror({
FETCHED: null, FETCHED: null,
NOT_FETCHED: null, NOT_FETCHED: null,
@ -18,6 +21,7 @@ const getInitialState = () => ({
commentingAllowed: false, commentingAllowed: false,
thumbnail: '', thumbnail: '',
followers: 0, followers: 0,
owner: null,
rolesStatus: Status.NOT_FETCHED, rolesStatus: Status.NOT_FETCHED,
manager: false, manager: false,
@ -55,6 +59,8 @@ const studioReducer = (state, action) => {
} }
}; };
// Action Creators
const setFetchStatus = (fetchType, fetchStatus, error) => ({ const setFetchStatus = (fetchType, fetchStatus, error) => ({
type: 'SET_FETCH_STATUS', type: 'SET_FETCH_STATUS',
fetchType, fetchType,
@ -72,6 +78,8 @@ const setRoles = roles => ({
roles: roles roles: roles
}); });
// Thunks
const getInfo = studioId => (dispatch => { const getInfo = studioId => (dispatch => {
dispatch(setFetchStatus('infoStatus', Status.FETCHING)); dispatch(setFetchStatus('infoStatus', Status.FETCHING));
api({uri: `/studios/${studioId}`}, (err, body, res) => { api({uri: `/studios/${studioId}`}, (err, body, res) => {
@ -86,7 +94,8 @@ const getInfo = studioId => (dispatch => {
openToAll: body.open_to_all, openToAll: body.open_to_all,
commentingAllowed: body.commenting_allowed, commentingAllowed: body.commenting_allowed,
updated: new Date(body.history.modified), updated: new Date(body.history.modified),
followers: body.stats.followers followers: body.stats.followers,
owner: body.owner
})); }));
}); });
}); });
@ -111,10 +120,32 @@ const getRoles = (studioId, username, token) => (dispatch => {
}); });
}); });
// Selectors
// Fine-grain selector helpers - not exported, use the higher level selectors below
const isCreator = state =>
state.studio.owner !== null && // Never try matching if owner has not been set
selectUserId(state) === state.studio.owner;
const isCurator = state => state.studio.curator;
const isManager = state => state.studio.manager || isCreator(state);
// Action-based permissions selectors
const selectCanEditInfo = state => selectIsAdmin(state) || isManager(state);
const selectCanAddProjects = state =>
isManager(state) ||
isCurator(state) ||
(selectIsSocial(state) && state.studio.openToAll);
module.exports = { module.exports = {
getInitialState, getInitialState,
studioReducer, studioReducer,
Status, Status,
// Thunks
getInfo, getInfo,
getRoles getRoles,
// Selectors
selectCanEditInfo,
selectCanAddProjects
}; };

View file

@ -0,0 +1,98 @@
import {
getInitialState as getInitialStudioState,
selectCanEditInfo,
selectCanAddProjects
} from '../../../src/redux/studio';
import {
getInitialState as getInitialSessionState
} from '../../../src/redux/session';
const fixtures = {
permissions: {
isAdmin: {admin: true},
isSocial: {social: true}
},
studio: {
isManager: {manager: true},
isCurator: {curator: true},
creator1: {owner: 1},
openToAll: {openToAll: true}
},
session: {
user1: {
session: {user: {id: 1}}
}
}
};
describe('studio selectors', () => {
let state;
beforeEach(() => {
state = {
permissions: {},
session: getInitialSessionState(),
studio: getInitialStudioState()
};
});
describe('studio info', () => {
test('is editable by admin', () => {
state.permissions = fixtures.permissions.isAdmin;
expect(selectCanEditInfo(state)).toBe(true);
});
test('is editable by managers and studio creator', () => {
state.studio = fixtures.studio.isManager;
expect(selectCanEditInfo(state)).toBe(true);
state.studio = fixtures.studio.creator1;
state.session = fixtures.session.user1;
expect(selectCanEditInfo(state)).toBe(true);
});
test('is not editable by curators', () => {
state.studio = fixtures.studio.isCurator;
state.session = fixtures.session.user1;
expect(selectCanEditInfo(state)).toBe(false);
});
test('is not editable by other logged in users', () => {
state.session = fixtures.session.user1;
expect(selectCanEditInfo(state)).toBe(false);
});
test('is not editable by logged out users', () => {
expect(selectCanEditInfo(state)).toBe(false);
});
});
describe('studio projects', () => {
test('cannot be added by admin', () => {
state.permissions = fixtures.permissions.isAdmin;
state.session = fixtures.session.user1;
expect(selectCanAddProjects(state)).toBe(false);
});
test('can be added by managers and studio creator', () => {
state.studio = fixtures.studio.isManager;
expect(selectCanAddProjects(state)).toBe(true);
state.studio = fixtures.studio.creator1;
state.session = fixtures.session.user1;
expect(selectCanAddProjects(state)).toBe(true);
});
test('can be added by curators', () => {
state.studio = fixtures.studio.isCurator;
state.session = fixtures.session.user1;
expect(selectCanAddProjects(state)).toBe(true);
});
test('can be added by social users if studio is openToAll', () => {
state.studio = fixtures.studio.openToAll;
state.permissions = fixtures.permissions.isSocial;
state.session = fixtures.session.user1;
expect(selectCanAddProjects(state)).toBe(true);
});
test('cannot be added by social users if not openToAll', () => {
state.permissions = fixtures.permissions.isSocial;
state.session = fixtures.session.user1;
expect(selectCanAddProjects(state)).toBe(false);
});
});
});