blob: 0a9dee47231e045d18c6f3a44e0aaa17fe288842 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {assert} from 'chai';
6import sinon from 'sinon';
7
8import * as projects from './projects.js';
9import * as example from 'shared/test/constants-projects.js';
10
11import {prpcClient} from 'prpc-client-instance.js';
12
13let dispatch;
14
15
16describe('project reducers', () => {
17 it('root reducer initial state', () => {
18 const actual = projects.reducer(undefined, {type: null});
19 const expected = {
20 byName: {},
21 allNames: [],
22 requests: {
23 list: {
24 error: null,
25 requesting: false,
26 },
27 },
28 };
29 assert.deepEqual(actual, expected);
30 });
31
32 describe('byNameReducer', () => {
33 it('populated on LIST_SUCCESS', () => {
34 const action = {type: projects.LIST_SUCCESS, projects:
35 [example.PROJECT, example.PROJECT_2]};
36 const actual = projects.byNameReducer({}, action);
37
38 assert.deepEqual(actual, {
39 [example.NAME]: example.PROJECT,
40 [example.NAME_2]: example.PROJECT_2,
41 });
42 });
43
44 it('keeps original state on empty LIST_SUCCESS', () => {
45 const originalState = {
46 [example.NAME]: example.PROJECT,
47 [example.NAME_2]: example.PROJECT_2,
48 };
49 const action = {type: projects.LIST_SUCCESS, projects: []};
50 const actual = projects.byNameReducer(originalState, action);
51
52 assert.deepEqual(actual, originalState);
53 });
54
55 it('appends new issues to state on LIST_SUCCESS', () => {
56 const originalState = {
57 [example.NAME]: example.PROJECT,
58 };
59 const action = {type: projects.LIST_SUCCESS,
60 projects: [example.PROJECT_2]};
61 const actual = projects.byNameReducer(originalState, action);
62
63 const expected = {
64 [example.NAME]: example.PROJECT,
65 [example.NAME_2]: example.PROJECT_2,
66 };
67 assert.deepEqual(actual, expected);
68 });
69
70 it('overrides outdated data on LIST_SUCCESS', () => {
71 const originalState = {
72 [example.NAME]: example.PROJECT,
73 [example.NAME_2]: example.PROJECT_2,
74 };
75
76 const newProject2 = {
77 name: example.NAME_2,
78 summary: 'I hacked your project!',
79 };
80 const action = {type: projects.LIST_SUCCESS,
81 projects: [newProject2]};
82 const actual = projects.byNameReducer(originalState, action);
83 const expected = {
84 [example.NAME]: example.PROJECT,
85 [example.NAME_2]: newProject2,
86 };
87 assert.deepEqual(actual, expected);
88 });
89 });
90
91 it('allNames populated on LIST_SUCCESS', () => {
92 const action = {type: projects.LIST_SUCCESS, projects:
93 [example.PROJECT, example.PROJECT_2]};
94 const actual = projects.allNamesReducer([], action);
95
96 assert.deepEqual(actual, [example.NAME, example.NAME_2]);
97 });
98});
99
100describe('project selectors', () => {
101 it('byName', () => {
102 const normalizedProjects = {
103 [example.NAME]: example.PROJECT,
104 };
105 const state = {projects: {
106 byName: normalizedProjects,
107 }};
108 assert.deepEqual(projects.byName(state), normalizedProjects);
109 });
110
111 it('all', () => {
112 const state = {projects: {
113 byName: {
114 [example.NAME]: example.PROJECT,
115 },
116 allNames: [example.NAME],
117 }};
118 assert.deepEqual(projects.all(state), [example.PROJECT]);
119 });
120
121 it('requests', () => {
122 const state = {projects: {
123 requests: {
124 list: {error: null, requesting: false},
125 },
126 }};
127 assert.deepEqual(projects.requests(state), {
128 list: {error: null, requesting: false},
129 });
130 });
131});
132
133describe('project action creators', () => {
134 beforeEach(() => {
135 sinon.stub(prpcClient, 'call');
136 dispatch = sinon.stub();
137 });
138
139 afterEach(() => {
140 prpcClient.call.restore();
141 });
142
143 describe('list', () => {
144 it('success', async () => {
145 const projectsResponse = {projects: [example.PROJECT, example.PROJECT_2]};
146 prpcClient.call.returns(Promise.resolve(projectsResponse));
147
148 await projects.list()(dispatch);
149
150 sinon.assert.calledWith(dispatch, {type: projects.LIST_START});
151
152 sinon.assert.calledWith(
153 prpcClient.call, 'monorail.v3.Projects', 'ListProjects', {});
154
155 const successAction = {
156 type: projects.LIST_SUCCESS,
157 projects: projectsResponse.projects,
158 };
159 sinon.assert.calledWith(dispatch, successAction);
160 });
161
162 it('failure', async () => {
163 prpcClient.call.throws();
164
165 await projects.list()(dispatch);
166
167 const action = {
168 type: projects.LIST_FAILURE,
169 error: sinon.match.any,
170 };
171 sinon.assert.calledWith(dispatch, action);
172 });
173 });
174});