blob: a48e5e2950ec8f81fe6034e3a68b391b9e07e681 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001// Copyright 2020 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 {_CROS_CLOSURE_SLO, _CROS_CLOSURE_SLO_DAYS_BY_PRIORITY,
7 _isCrosClosureEligible, SloCompletionStatus, determineSloStatus}
8 from './slo-rules.js';
9
10const P1_FIELD_VALUE = Object.freeze({
11 fieldRef: {
12 fieldId: 1,
13 fieldName: 'Pri',
14 type: 'ENUM_TYPE',
15 },
16 value: '1'});
17
18// TODO(crbug.com/monorail/7843): Separate testing of determineSloStatus from
19// testing of specific SLO Rules. Add testing for a rule that throws an error.
20describe('determineSloStatus', () => {
21 it('returns null for ineligible issues', () => {
22 const ineligibleIssue = {
23 componentRefs: [{path: 'Some>Other>Component'}],
24 fieldValues: [P1_FIELD_VALUE],
25 labelRefs: [],
26 localId: 1,
27 projectName: 'x',
28 };
29 assert.isNull(determineSloStatus(ineligibleIssue));
30 });
31
32 it('returns null for eligible issues without defined priority', () => {
33 const ineligibleIssue = {
34 componentRefs: [{path: 'OS>Systems>CrashReporting'}],
35 fieldValues: [],
36 labelRefs: [],
37 localId: 1,
38 projectName: 'x',
39 };
40 assert.isNull(determineSloStatus(ineligibleIssue));
41 });
42
43 it('returns SloStatus with target for incomplete eligible issues', () => {
44 const openedTimestamp = 1412362587;
45 const eligibleIssue = {
46 componentRefs: [{path: 'OS>Systems>CrashReporting'}],
47 fieldValues: [P1_FIELD_VALUE],
48 labelRefs: [],
49 localId: 1,
50 openedTimestamp: openedTimestamp,
51 projectName: 'x',
52 };
53 const status = determineSloStatus(eligibleIssue);
54
55 const expectedTarget = new Date(openedTimestamp * 1000);
56 expectedTarget.setDate(
57 expectedTarget.getDate() + _CROS_CLOSURE_SLO_DAYS_BY_PRIORITY['1']);
58
59 assert.equal(status.target.valueOf(), expectedTarget.valueOf());
60 assert.equal(status.completion, SloCompletionStatus.INCOMPLETE);
61 assert.equal(status.rule, _CROS_CLOSURE_SLO);
62 });
63
64 it('returns SloStatus without target for complete eligible issues', () => {
65 const eligibleIssue = {
66 componentRefs: [{path: 'OS>Systems>CrashReporting'}],
67 fieldValues: [P1_FIELD_VALUE],
68 labelRefs: [],
69 localId: 1,
70 projectName: 'x',
71 statusRef: {status: 'Closed', meansOpen: false},
72 };
73 const status = determineSloStatus(eligibleIssue);
74 assert.isNull(status.target);
75 assert.equal(status.completion, SloCompletionStatus.COMPLETE);
76 assert.equal(status.rule, _CROS_CLOSURE_SLO);
77 });
78});
79
80describe('_isCrosClosureEligible', () => {
81 let crosIssue;
82 beforeEach(() => {
83 crosIssue = {
84 componentRefs: [{path: 'OS>Systems>CrashReporting'}],
85 fieldValues: [],
86 labelRefs: [],
87 localId: 1,
88 projectName: 'x',
89 };
90 });
91
92 it('returns true when eligible', () => {
93 assert.isTrue(_isCrosClosureEligible(crosIssue));
94 });
95
96 it('returns true if at least one eligible component', () => {
97 crosIssue.componentRefs.push({path: 'Some>Other>Component'});
98 assert.isTrue(_isCrosClosureEligible(crosIssue));
99 });
100
101 it('returns false for issues in wrong component', () => {
102 crosIssue.componentRefs = [{path: 'Some>Other>Component'}];
103 assert.isFalse(_isCrosClosureEligible(crosIssue));
104 });
105
106 it('returns false for Feature', () => {
107 crosIssue.fieldValues.push(
108 {fieldRef: {fieldName: 'Type'}, value: 'Feature'});
109 assert.isFalse(_isCrosClosureEligible(crosIssue));
110 });
111
112 it('returns false for FLT-Launch', () => {
113 crosIssue.fieldValues.push(
114 {fieldRef: {fieldName: 'Type'}, value: 'FLT-Launch'});
115 assert.isFalse(_isCrosClosureEligible(crosIssue));
116 });
117
118 it('returns false for Postmortem-Followup', () => {
119 crosIssue.fieldValues.push(
120 {fieldRef: {fieldName: 'Type'}, value: 'Postmortem-Followup'});
121 assert.isFalse(_isCrosClosureEligible(crosIssue));
122 });
123
124 it('returns false for Design-Review', () => {
125 crosIssue.fieldValues.push(
126 {fieldRef: {fieldName: 'Type'}, value: 'Design-Review'});
127 assert.isFalse(_isCrosClosureEligible(crosIssue));
128 });
129
130 it('returns true for other types', () => {
131 crosIssue.fieldValues.push(
132 {fieldRef: {fieldName: 'type'}, value: 'Any-Other-Type'});
133 assert.isTrue(_isCrosClosureEligible(crosIssue));
134 });
135
136 it('returns false for p1 with milestone', () => {
137 crosIssue.fieldValues.push(P1_FIELD_VALUE);
138 crosIssue.fieldValues.push({fieldRef: {fieldName: 'M'}, value: 'any'});
139 assert.isFalse(_isCrosClosureEligible(crosIssue));
140 });
141
142 it('returns true for p1 without milestone', () => {
143 crosIssue.fieldValues.push(P1_FIELD_VALUE);
144 crosIssue.fieldValues.push({fieldRef: {fieldName: 'Other'}, value: 'any'});
145 assert.isTrue(_isCrosClosureEligible(crosIssue));
146 });
147
148 it('returns false for ChromeOS_No_SLO label', () => {
149 crosIssue.labelRefs.push({label: 'ChromeOS_No_SLO'});
150 assert.isFalse(_isCrosClosureEligible(crosIssue));
151 });
152});