Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/reducers/users.test.js b/static_src/reducers/users.test.js
new file mode 100644
index 0000000..ea0ce61
--- /dev/null
+++ b/static_src/reducers/users.test.js
@@ -0,0 +1,178 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assert} from 'chai';
+import sinon from 'sinon';
+
+import * as users from './users.js';
+import * as example from 'shared/test/constants-users.js';
+
+import {prpcClient} from 'prpc-client-instance.js';
+
+let dispatch;
+
+describe('user reducers', () => {
+ it('root reducer initial state', () => {
+ const actual = users.reducer(undefined, {type: null});
+ const expected = {
+ currentUserName: null,
+ byName: {},
+ projectMemberships: {},
+ requests: {
+ batchGet: {},
+ fetch: {},
+ gatherProjectMemberships: {},
+ },
+ };
+ assert.deepEqual(actual, expected);
+ });
+
+ it('currentUserName updates on LOG_IN', () => {
+ const action = {type: users.LOG_IN, user: example.USER};
+ const actual = users.currentUserNameReducer(null, action);
+ assert.deepEqual(actual, example.NAME);
+ });
+
+ it('byName updates on BATCH_GET_SUCCESS', () => {
+ const action = {type: users.BATCH_GET_SUCCESS, users: [example.USER]};
+ const actual = users.byNameReducer({}, action);
+ assert.deepEqual(actual, {[example.NAME]: example.USER});
+ });
+
+ describe('projectMembershipsReducer', () => {
+ it('updates on GATHER_PROJECT_MEMBERSHIPS_SUCCESS', () => {
+ const action = {type: users.GATHER_PROJECT_MEMBERSHIPS_SUCCESS,
+ userName: example.NAME, projectMemberships: [example.PROJECT_MEMBER]};
+ const actual = users.projectMembershipsReducer({}, action);
+ assert.deepEqual(actual, {[example.NAME]: [example.PROJECT_MEMBER]});
+ });
+
+ it('sets empty on GATHER_PROJECT_MEMBERSHIPS_SUCCESS', () => {
+ const action = {type: users.GATHER_PROJECT_MEMBERSHIPS_SUCCESS,
+ userName: example.NAME, projectMemberships: undefined};
+ const actual = users.projectMembershipsReducer({}, action);
+ assert.deepEqual(actual, {[example.NAME]: []});
+ });
+ });
+});
+
+describe('user selectors', () => {
+ it('currentUserName', () => {
+ const state = {users: {currentUserName: example.NAME}};
+ assert.deepEqual(users.currentUserName(state), example.NAME);
+ });
+
+ it('byName', () => {
+ const state = {users: {byName: example.BY_NAME}};
+ assert.deepEqual(users.byName(state), example.BY_NAME);
+ });
+
+ it('projectMemberships', () => {
+ const membershipsByName = {[example.NAME]: [example.PROJECT_MEMBER]};
+ const state = {users: {projectMemberships: membershipsByName}};
+ assert.deepEqual(users.projectMemberships(state), membershipsByName);
+ });
+});
+
+describe('user action creators', () => {
+ beforeEach(() => {
+ sinon.stub(prpcClient, 'call');
+ dispatch = sinon.stub();
+ });
+
+ afterEach(() => {
+ prpcClient.call.restore();
+ });
+
+ describe('batchGet', () => {
+ it('success', async () => {
+ prpcClient.call.returns(Promise.resolve({users: [example.USER]}));
+
+ await users.batchGet([example.NAME])(dispatch);
+
+ sinon.assert.calledWith(dispatch, {type: users.BATCH_GET_START});
+
+ const args = {names: [example.NAME]};
+ sinon.assert.calledWith(
+ prpcClient.call, 'monorail.v3.Users', 'BatchGetUsers', args);
+
+ const action = {type: users.BATCH_GET_SUCCESS, users: [example.USER]};
+ sinon.assert.calledWith(dispatch, action);
+ });
+
+ it('failure', async () => {
+ prpcClient.call.throws();
+
+ await users.batchGet([example.NAME])(dispatch);
+
+ const action = {type: users.BATCH_GET_FAILURE, error: sinon.match.any};
+ sinon.assert.calledWith(dispatch, action);
+ });
+ });
+
+ describe('fetch', () => {
+ it('success', async () => {
+ prpcClient.call.returns(Promise.resolve(example.USER));
+
+ await users.fetch(example.NAME)(dispatch);
+
+ sinon.assert.calledWith(dispatch, {type: users.FETCH_START});
+
+ const args = {name: example.NAME};
+ sinon.assert.calledWith(
+ prpcClient.call, 'monorail.v3.Users', 'GetUser', args);
+
+ const fetchAction = {type: users.FETCH_SUCCESS, user: example.USER};
+ sinon.assert.calledWith(dispatch, fetchAction);
+
+ const logInAction = {type: users.LOG_IN, user: example.USER};
+ sinon.assert.calledWith(dispatch, logInAction);
+ });
+
+ it('failure', async () => {
+ prpcClient.call.throws();
+
+ await users.fetch(example.NAME)(dispatch);
+
+ const action = {type: users.FETCH_FAILURE, error: sinon.match.any};
+ sinon.assert.calledWith(dispatch, action);
+ });
+ });
+
+ describe('gatherProjectMemberships', () => {
+ it('success', async () => {
+ prpcClient.call.returns(Promise.resolve({projectMemberships: [
+ example.PROJECT_MEMBER,
+ ]}));
+
+ await users.gatherProjectMemberships(
+ example.NAME)(dispatch);
+
+ sinon.assert.calledWith(dispatch,
+ {type: users.GATHER_PROJECT_MEMBERSHIPS_START});
+
+ const args = {user: example.NAME};
+ sinon.assert.calledWith(
+ prpcClient.call, 'monorail.v3.Frontend',
+ 'GatherProjectMembershipsForUser', args);
+
+ const action = {
+ type: users.GATHER_PROJECT_MEMBERSHIPS_SUCCESS,
+ projectMemberships: [example.PROJECT_MEMBER],
+ userName: example.NAME,
+ };
+ sinon.assert.calledWith(dispatch, action);
+ });
+
+ it('failure', async () => {
+ prpcClient.call.throws(new Error());
+
+ await users.batchGet([example.NAME])(dispatch);
+
+ const action = {type: users.BATCH_GET_FAILURE,
+ error: sinon.match.instanceOf(Error)};
+ sinon.assert.calledWith(dispatch, action);
+ });
+ });
+});