From 727018f18fa5a67a28ea8623271758a701fbfa26 Mon Sep 17 00:00:00 2001 From: Orlando Hohmeier Date: Fri, 22 Jan 2016 12:58:35 +0100 Subject: [PATCH 1/2] Fix app health detail calculations Ensure that none of the values is divided by 0. Closes mesosphere/marathon#3063 --- .../components/AppHealthDetailComponent.jsx | 2 +- src/test/apps.test.js | 549 +++++++++++++----- 2 files changed, 409 insertions(+), 142 deletions(-) diff --git a/src/js/components/AppHealthDetailComponent.jsx b/src/js/components/AppHealthDetailComponent.jsx index 5d10ae6a9..116326d5d 100644 --- a/src/js/components/AppHealthDetailComponent.jsx +++ b/src/js/components/AppHealthDetailComponent.jsx @@ -43,7 +43,7 @@ var AppHealthDetailComponent = React.createClass({ renderItem: function (state) { var health = this.getHealth(state); - var totalInstances = this.props.model.instances; + var totalInstances = this.props.model.instances || 1; var instances = health.quantity; var percentage = Math.round((instances / totalInstances) * 100); var label = healthStatusLabels[state]; diff --git a/src/test/apps.test.js b/src/test/apps.test.js index 5c89b1bad..400313ae9 100644 --- a/src/test/apps.test.js +++ b/src/test/apps.test.js @@ -1174,88 +1174,90 @@ describe("App List component", function () { describe("App Health Bar", function () { - var model = { - id: "app-123", - instances: 5, - health: [ - {state: HealthStatus.HEALTHY, quantity: 2}, - {state: HealthStatus.UNHEALTHY, quantity: 2}, - {state: HealthStatus.UNKNOWN, quantity: 1}, - {state: HealthStatus.STAGED, quantity: 1}, - {state: HealthStatus.OVERCAPACITY, quantity: 2}, - {state: HealthStatus.UNSCHEDULED, quantity: 2} - ] - }; + describe("running app with 5 instances", function () { - before(function () { - this.component = shallow(); - }); + var model = { + id: "app-123", + instances: 5, + health: [ + {state: HealthStatus.HEALTHY, quantity: 2}, + {state: HealthStatus.UNHEALTHY, quantity: 2}, + {state: HealthStatus.UNKNOWN, quantity: 1}, + {state: HealthStatus.STAGED, quantity: 1}, + {state: HealthStatus.OVERCAPACITY, quantity: 2}, + {state: HealthStatus.UNSCHEDULED, quantity: 2} + ] + }; - after(function () { - this.component = null; - }); + before(function () { + this.component = shallow(); + }); - it("health bar for healthy tasks has correct width", function () { - var width = this.component - .find(".progress-bar") - .at(0) - .props() - .style.width; - expect(width).to.equal("20%"); - }); + after(function () { + this.component = null; + }); - it("health bar for unhealthy tasks has correct width", function () { - var width = this.component - .find(".progress-bar") - .at(1) - .props() - .style.width; - expect(width).to.equal("20%"); - }); + it("health bar for healthy tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(0) + .props() + .style.width; + expect(width).to.equal("20%"); + }); - it("health bar for running tasks has correct width", function () { - var width = this.component - .find(".progress-bar") - .at(2) - .props() - .style.width; - expect(width).to.equal("10%"); - }); + it("health bar for unhealthy tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(1) + .props() + .style.width; + expect(width).to.equal("20%"); + }); - it("health bar for staged tasks has correct width", function () { - var width = this.component - .find(".progress-bar") - .at(3) - .props() - .style.width; - expect(width).to.equal("10%"); - }); + it("health bar for running tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(2) + .props() + .style.width; + expect(width).to.equal("10%"); + }); - it("health bar for over capacity tasks has correct width", function () { - var width = this.component - .find(".progress-bar") - .at(4) - .props() - .style.width; - expect(width).to.equal("20%"); - }); + it("health bar for staged tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(3) + .props() + .style.width; + expect(width).to.equal("10%"); + }); - it("health bar for unscheduled tasks has correct width", function () { - var width = this.component - .find(".progress-bar") - .at(5) - .props() - .style.width; - expect(width).to.equal("20%"); - }); + it("health bar for over capacity tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(4) + .props() + .style.width; + expect(width).to.equal("20%"); + }); - describe("detail", function () { + it("health bar for unscheduled tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(5) + .props() + .style.width; + expect(width).to.equal("20%"); + }); - before(function () { - this.component = shallow( - - ); - }); + model={model}/> + ); + }); - after(function () { - this.component = null; - }); + after(function () { + this.component = null; + }); - it("Healthy tasks are reported correctly", function () { - expect( - this.component.find(".health-breakdown-item-healthy") - .text() - ).to.equal("2 Healthy(40%)"); - }); + it("Healthy tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-healthy") + .text() + ).to.equal("2 Healthy(40%)"); + }); + + it("Unhealthy tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-unhealthy") + .text() + ).to.equal("2 Unhealthy(40%)"); + }); - it("Unhealthy tasks are reported correctly", function () { - expect( - this.component.find(".health-breakdown-item-unhealthy") - .text() - ).to.equal("2 Unhealthy(40%)"); + it("Unknown tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-unknown") + .text() + ).to.equal("1 Unknown(20%)"); + }); }); - it("Unknown tasks are reported correctly", function () { - expect( - this.component.find(".health-breakdown-item-unknown") - .text() - ).to.equal("1 Unknown(20%)"); + describe("with tooltip", function () { + + before(function () { + this.component = mount( + + ); + }); + + after(function () { + React.unmountComponentAtNode(this.component.instance().getDOMNode()); + }); + + it("has healthbar", function () { + expect(this.component + .find(AppHealthBarComponent) + .length + ).to.equal(1); + }); + + it("shows the popover with health details on hover", function () { + this.component.simulate("mouseOver"); + expect(this.component + .find(AppHealthDetailComponent) + .length + ).to.equal(1) + }); }); }); + describe("running app scaled down to 0 instances from 2", + function () { - describe("with tooltip", function () { + var model = { + id: "app-123", + instances: 0, + health: [ + {state: HealthStatus.HEALTHY, quantity: 2}, + {state: HealthStatus.UNHEALTHY, quantity: 0}, + {state: HealthStatus.UNKNOWN, quantity: 0}, + {state: HealthStatus.STAGED, quantity: 0}, + {state: HealthStatus.OVERCAPACITY, quantity: 2}, + {state: HealthStatus.UNSCHEDULED, quantity: 0} + ] + }; - before(function () { - this.component = mount( - - ); - }); + before(function () { + this.component = shallow(); + }); - after(function () { - React.unmountComponentAtNode(this.component.instance().getDOMNode()); - }); + after(function () { + this.component = null; + }); - it("has healthbar", function () { - expect(this.component - .find(AppHealthBarComponent) - .length - ).to.equal(1); - }); + it("health bar for healthy tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(0) + .props() + .style.width; + expect(width).to.equal("50%"); + }); - it("shows the popover with health details on hover", function () { - this.component.simulate("mouseOver"); - expect(this.component - .find(AppHealthDetailComponent) - .length - ).to.equal(1) - }); + it("health bar for unhealthy tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(1) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + it("health bar for running tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(2) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + it("health bar for staged tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(3) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + it("health bar for over capacity tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(4) + .props() + .style.width; + expect(width).to.equal("50%"); + }); + + it("health bar for unscheduled tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(5) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + describe("detail", function () { + + before(function () { + this.component = shallow( + + ); + }); + + after(function () { + this.component = null; + }); + + it("Healthy tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-healthy") + .text() + ).to.equal("2 Healthy(200%)"); + }); + + it("Unhealthy tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-unhealthy") + .text() + ).to.equal("0 Unhealthy(0%)"); + }); + + it("Unknown tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-unknown") + .text() + ).to.equal("0 Unknown(0%)"); + }); + + it("Overcapacity tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-over-capacity") + .text() + ).to.equal("2 Over Capacity(200%)"); + }); + + }); + + } + ); + describe("running app scaled down to 5 instances from 10", + function () { + + var model = { + id: "app-123", + instances: 5, + health: [ + {state: HealthStatus.HEALTHY, quantity: 10}, + {state: HealthStatus.UNHEALTHY, quantity: 0}, + {state: HealthStatus.UNKNOWN, quantity: 0}, + {state: HealthStatus.STAGED, quantity: 0}, + {state: HealthStatus.OVERCAPACITY, quantity: 5}, + {state: HealthStatus.UNSCHEDULED, quantity: 0} + ] + }; + + before(function () { + this.component = shallow(); + }); + + after(function () { + this.component = null; + }); + + it("health bar for healthy tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(0) + .props() + .style.width; + expect(width).to.equal("66.666%"); + }); + + it("health bar for unhealthy tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(1) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + it("health bar for running tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(2) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + it("health bar for staged tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(3) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + it("health bar for over capacity tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(4) + .props() + .style.width; + expect(width).to.equal("33.333%"); + }); + + it("health bar for unscheduled tasks has correct width", function () { + var width = this.component + .find(".progress-bar") + .at(5) + .props() + .style.width; + expect(width).to.equal("0%"); + }); + + describe("detail", function () { + + before(function () { + this.component = shallow( + + ); + }); + + after(function () { + this.component = null; + }); + + it("Healthy tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-healthy") + .text() + ).to.equal("10 Healthy(200%)"); + }); + + it("Unhealthy tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-unhealthy") + .text() + ).to.equal("0 Unhealthy(0%)"); + }); + + it("Unknown tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-unknown") + .text() + ).to.equal("0 Unknown(0%)"); + }); + + it("Overcapacity tasks are reported correctly", function () { + expect( + this.component.find(".health-breakdown-item-over-capacity") + .text() + ).to.equal("5 Over Capacity(100%)"); + }); + + }); + + } + ); - }); }); describe("App Page component", function () { @@ -1376,34 +1643,34 @@ describe("App Page component", function () { }); it("returns the right shorthand health message for failing tasks", - function () { - expect(this.component - .instance() - .getTaskHealthMessage("test-task-1") - ).to.equal("Unhealthy"); - }); + function () { + expect(this.component + .instance() + .getTaskHealthMessage("test-task-1") + ).to.equal("Unhealthy"); + }); it("returns the right health message for tasks with unknown health", - function () { - var app = Util.extendObject(appScheme, { - id: "/test-app-1", - status: AppStatus.RUNNING, - tasks: [ - { - id: "test-task-1", - appId: "/test-app-1", - healthStatus: HealthStatus.UNKNOWN - } - ] - }); + function () { + var app = Util.extendObject(appScheme, { + id: "/test-app-1", + status: AppStatus.RUNNING, + tasks: [ + { + id: "test-task-1", + appId: "/test-app-1", + healthStatus: HealthStatus.UNKNOWN + } + ] + }); - AppsStore.apps = [app]; + AppsStore.apps = [app]; - expect(this.component - .instance() - .getTaskHealthMessage("test-task-1") - ).to.equal("Unknown"); - }); + expect(this.component + .instance() + .getTaskHealthMessage("test-task-1") + ).to.equal("Unknown"); + }); it("returns the right health message for healthy tasks", function () { var app = Util.extendObject(appScheme, { From 3340137b8eebd9f40ce174db956ca5c7a472ad69 Mon Sep 17 00:00:00 2001 From: Orlando Hohmeier Date: Fri, 22 Jan 2016 13:06:50 +0100 Subject: [PATCH 2/2] Add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bedb4cbda..001376ed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - \#3054 - Empty - non set- application attributes are accidentaly submited by the UI - \#3064 - Labels dropdown menu not showing up +- \#3063 - After scaling a healthy app to 0, it appears to be Infinity% + overcapacity ## 0.15.0 - 2016-01-20 ### Added