blob: d55897e894f24eae1dd62aade84677ed5b966c0b [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 {MrPhase} from './mr-phase.js';
9
10
11let element;
12
13describe('mr-phase', () => {
14 beforeEach(() => {
15 element = document.createElement('mr-phase');
16 document.body.appendChild(element);
17 });
18
19 afterEach(() => {
20 document.body.removeChild(element);
21 });
22
23 it('initializes', () => {
24 assert.instanceOf(element, MrPhase);
25 });
26
27 it('clicking edit button opens edit dialog', async () => {
28 element.phaseName = 'Beta';
29
30 await element.updateComplete;
31
32 const editDialog = element.querySelector('#editPhase');
33 assert.isFalse(editDialog.opened);
34
35 element.querySelector('.phase-edit').click();
36
37 await element.updateComplete;
38
39 assert.isTrue(editDialog.opened);
40 });
41
42 it('discarding form changes closes dialog', async () => {
43 await element.updateComplete;
44
45 // Open the edit dialog.
46 element.edit();
47 const editDialog = element.querySelector('#editPhase');
48 const editForm = element.querySelector('#metadataForm');
49
50 await element.updateComplete;
51
52 assert.isTrue(editDialog.opened);
53 editForm.discard();
54
55 await element.updateComplete;
56
57 assert.isFalse(editDialog.opened);
58 });
59
60 describe('milestone fetching', () => {
61 beforeEach(() => {
62 sinon.stub(element, 'fetchMilestoneData');
63 });
64
65 it('_launchedMilestone extracts M-Launched for phase', () => {
66 element._fieldValueMap = new Map([['m-launched beta', ['87']]]);
67 element.phaseName = 'Beta';
68
69 assert.equal(element._launchedMilestone, '87');
70 assert.equal(element._approvedMilestone, undefined);
71 assert.equal(element._targetMilestone, undefined);
72 });
73
74 it('_approvedMilestone extracts M-Approved for phase', () => {
75 element._fieldValueMap = new Map([['m-approved beta', ['86']]]);
76 element.phaseName = 'Beta';
77
78 assert.equal(element._launchedMilestone, undefined);
79 assert.equal(element._approvedMilestone, '86');
80 assert.equal(element._targetMilestone, undefined);
81 });
82
83 it('_targetMilestone extracts M-Target for phase', () => {
84 element._fieldValueMap = new Map([['m-target beta', ['85']]]);
85 element.phaseName = 'Beta';
86
87 assert.equal(element._launchedMilestone, undefined);
88 assert.equal(element._approvedMilestone, undefined);
89 assert.equal(element._targetMilestone, '85');
90 });
91
92 it('_milestoneToFetch returns empty when no relevant milestone', () => {
93 element._fieldValueMap = new Map([['m-target beta', ['85']]]);
94 element.phaseName = 'Stable';
95
96 assert.equal(element._milestoneToFetch, '');
97 });
98
99 it('_milestoneToFetch selects highest milestone', () => {
100 element._fieldValueMap = new Map([
101 ['m-target beta', ['84']],
102 ['m-approved beta', ['85']],
103 ['m-launched beta', ['86']]]);
104 element.phaseName = 'Beta';
105
106 assert.equal(element._milestoneToFetch, '86');
107 });
108
109 it('does not fetch when no milestones specified', async () => {
110 element.issue = {projectName: 'chromium', localId: 12};
111
112 await element.updateComplete;
113
114 sinon.assert.notCalled(element.fetchMilestoneData);
115 });
116
117 it('does not fetch when milestone to fetch is unchanged', async () => {
118 element._fetchedMilestone = '86';
119 element._fieldValueMap = new Map([['m-target beta', ['86']]]);
120 element.phaseName = 'Beta';
121
122 await element.updateComplete;
123
124 sinon.assert.notCalled(element.fetchMilestoneData);
125 });
126
127 it('fetches when milestone found', async () => {
128 element._fetchedMilestone = undefined;
129 element._fieldValueMap = new Map([['m-target beta', ['86']]]);
130 element.phaseName = 'Beta';
131
132 await element.updateComplete;
133
134 sinon.assert.calledWith(element.fetchMilestoneData, '86');
135 });
136
137 it('re-fetches when new milestone found', async () => {
138 element._fetchedMilestone = '86';
139 element._fieldValueMap = new Map([
140 ['m-target beta', ['86']],
141 ['m-launched beta', ['87']]]);
142 element.phaseName = 'Beta';
143
144 await element.updateComplete;
145
146 sinon.assert.calledWith(element.fetchMilestoneData, '87');
147 });
148
149 it('re-fetches only after last stale fetch finishes', async () => {
150 element._fetchedMilestone = '84';
151 element._fieldValueMap = new Map([['m-target beta', ['86']]]);
152 element.phaseName = 'Beta';
153 element._isFetchingMilestone = true;
154
155 await element.updateComplete;
156
157 sinon.assert.notCalled(element.fetchMilestoneData);
158
159 // Previous in flight fetch finishes.
160 element._fetchedMilestone = '85';
161 element._isFetchingMilestone = false;
162
163 await element.updateComplete;
164
165 sinon.assert.calledWith(element.fetchMilestoneData, '86');
166 });
167 });
168
169 describe('milestone fetching with fake server responses', () => {
170 beforeEach(() => {
171 sinon.stub(window, 'fetch');
172 sinon.spy(element, 'fetchMilestoneData');
173 });
174
175 afterEach(() => {
176 window.fetch.restore();
177 });
178
179 it('does not refetch when server response finishes', async () => {
180 const response = new window.Response('{"mstones": [{"mstone": 86}]}', {
181 status: 200,
182 headers: {
183 'Content-type': 'application/json',
184 },
185 });
186
187 window.fetch.returns(Promise.resolve(response));
188
189 element._fieldValueMap = new Map([['m-target beta', ['86']]]);
190 element.phaseName = 'Beta';
191
192 await element.updateComplete;
193
194 sinon.assert.calledWith(element.fetchMilestoneData, '86');
195
196 assert.isTrue(element._isFetchingMilestone);
197
198 await element._fetchMilestoneComplete;
199
200 assert.deepEqual(element._milestoneData, {'mstones': [{'mstone': 86}]});
201 assert.equal(element._fetchedMilestone, '86');
202 assert.isFalse(element._isFetchingMilestone);
203
204 await element.updateComplete;
205
206 sinon.assert.calledOnce(element.fetchMilestoneData);
207 });
208 });
209});