Project import generated by Copybara.

GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/elements/framework/mr-issue-slo/slo-rules.test.js b/static_src/elements/framework/mr-issue-slo/slo-rules.test.js
new file mode 100644
index 0000000..a48e5e2
--- /dev/null
+++ b/static_src/elements/framework/mr-issue-slo/slo-rules.test.js
@@ -0,0 +1,152 @@
+// 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 {_CROS_CLOSURE_SLO, _CROS_CLOSURE_SLO_DAYS_BY_PRIORITY,
+  _isCrosClosureEligible, SloCompletionStatus, determineSloStatus}
+  from './slo-rules.js';
+
+const P1_FIELD_VALUE = Object.freeze({
+  fieldRef: {
+    fieldId: 1,
+    fieldName: 'Pri',
+    type: 'ENUM_TYPE',
+  },
+  value: '1'});
+
+// TODO(crbug.com/monorail/7843): Separate testing of determineSloStatus from
+// testing of specific SLO Rules. Add testing for a rule that throws an error.
+describe('determineSloStatus', () => {
+  it('returns null for ineligible issues', () => {
+    const ineligibleIssue = {
+      componentRefs: [{path: 'Some>Other>Component'}],
+      fieldValues: [P1_FIELD_VALUE],
+      labelRefs: [],
+      localId: 1,
+      projectName: 'x',
+    };
+    assert.isNull(determineSloStatus(ineligibleIssue));
+  });
+
+  it('returns null for eligible issues without defined priority', () => {
+    const ineligibleIssue = {
+      componentRefs: [{path: 'OS>Systems>CrashReporting'}],
+      fieldValues: [],
+      labelRefs: [],
+      localId: 1,
+      projectName: 'x',
+    };
+    assert.isNull(determineSloStatus(ineligibleIssue));
+  });
+
+  it('returns SloStatus with target for incomplete eligible issues', () => {
+    const openedTimestamp = 1412362587;
+    const eligibleIssue = {
+      componentRefs: [{path: 'OS>Systems>CrashReporting'}],
+      fieldValues: [P1_FIELD_VALUE],
+      labelRefs: [],
+      localId: 1,
+      openedTimestamp: openedTimestamp,
+      projectName: 'x',
+    };
+    const status = determineSloStatus(eligibleIssue);
+
+    const expectedTarget = new Date(openedTimestamp * 1000);
+    expectedTarget.setDate(
+        expectedTarget.getDate() + _CROS_CLOSURE_SLO_DAYS_BY_PRIORITY['1']);
+
+    assert.equal(status.target.valueOf(), expectedTarget.valueOf());
+    assert.equal(status.completion, SloCompletionStatus.INCOMPLETE);
+    assert.equal(status.rule, _CROS_CLOSURE_SLO);
+  });
+
+  it('returns SloStatus without target for complete eligible issues', () => {
+    const eligibleIssue = {
+      componentRefs: [{path: 'OS>Systems>CrashReporting'}],
+      fieldValues: [P1_FIELD_VALUE],
+      labelRefs: [],
+      localId: 1,
+      projectName: 'x',
+      statusRef: {status: 'Closed', meansOpen: false},
+    };
+    const status = determineSloStatus(eligibleIssue);
+    assert.isNull(status.target);
+    assert.equal(status.completion, SloCompletionStatus.COMPLETE);
+    assert.equal(status.rule, _CROS_CLOSURE_SLO);
+  });
+});
+
+describe('_isCrosClosureEligible', () => {
+  let crosIssue;
+  beforeEach(() => {
+    crosIssue = {
+      componentRefs: [{path: 'OS>Systems>CrashReporting'}],
+      fieldValues: [],
+      labelRefs: [],
+      localId: 1,
+      projectName: 'x',
+    };
+  });
+
+  it('returns true when eligible', () => {
+    assert.isTrue(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns true if at least one eligible component', () => {
+    crosIssue.componentRefs.push({path: 'Some>Other>Component'});
+    assert.isTrue(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns false for issues in wrong component', () => {
+    crosIssue.componentRefs = [{path: 'Some>Other>Component'}];
+    assert.isFalse(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns false for Feature', () => {
+    crosIssue.fieldValues.push(
+        {fieldRef: {fieldName: 'Type'}, value: 'Feature'});
+    assert.isFalse(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns false for FLT-Launch', () => {
+    crosIssue.fieldValues.push(
+        {fieldRef: {fieldName: 'Type'}, value: 'FLT-Launch'});
+    assert.isFalse(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns false for Postmortem-Followup', () => {
+    crosIssue.fieldValues.push(
+        {fieldRef: {fieldName: 'Type'}, value: 'Postmortem-Followup'});
+    assert.isFalse(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns false for Design-Review', () => {
+    crosIssue.fieldValues.push(
+        {fieldRef: {fieldName: 'Type'}, value: 'Design-Review'});
+    assert.isFalse(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns true for other types', () => {
+    crosIssue.fieldValues.push(
+        {fieldRef: {fieldName: 'type'}, value: 'Any-Other-Type'});
+    assert.isTrue(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns false for p1 with milestone', () => {
+    crosIssue.fieldValues.push(P1_FIELD_VALUE);
+    crosIssue.fieldValues.push({fieldRef: {fieldName: 'M'}, value: 'any'});
+    assert.isFalse(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns true for p1 without milestone', () => {
+    crosIssue.fieldValues.push(P1_FIELD_VALUE);
+    crosIssue.fieldValues.push({fieldRef: {fieldName: 'Other'}, value: 'any'});
+    assert.isTrue(_isCrosClosureEligible(crosIssue));
+  });
+
+  it('returns false for ChromeOS_No_SLO label', () => {
+    crosIssue.labelRefs.push({label: 'ChromeOS_No_SLO'});
+    assert.isFalse(_isCrosClosureEligible(crosIssue));
+  });
+});