/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.server.presentation.models; import com.thoughtworks.go.config.Agents; import com.thoughtworks.go.config.CaseInsensitiveString; import com.thoughtworks.go.config.StageConfig; import com.thoughtworks.go.config.TrackingTool; import com.thoughtworks.go.domain.*; import com.thoughtworks.go.domain.buildcause.BuildCause; import com.thoughtworks.go.domain.label.PipelineLabel; import com.thoughtworks.go.domain.materials.Modification; import com.thoughtworks.go.dto.DurationBean; import com.thoughtworks.go.dto.DurationBeans; import com.thoughtworks.go.helper.*; import com.thoughtworks.go.server.domain.Username; import com.thoughtworks.go.util.*; import org.apache.commons.lang.StringEscapeUtils; import org.junit.Before; import org.junit.Test; import java.util.Date; import java.util.List; import java.util.Map; import static com.thoughtworks.go.helper.ModificationsMother.multipleModifications; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; public class StageJsonPresentationModelTest { private Pipeline pipeline; private static final int PIPELINE_ID = 1111; private Stage stage; private BuildCause modifications; @Before public void setUp() { MaterialRevisions materialRevisions = multipleModifications(); stage = StageMother.withOneScheduledBuild("stage", "job-that-will-fail", "job-that-will-pass", 1); modifications = BuildCause.createWithModifications(materialRevisions, ""); pipeline = new Pipeline("pipeline", PipelineLabel.COUNT_TEMPLATE, modifications, stage); stage.setIdentifier(new StageIdentifier(pipeline, stage)); for (JobInstance job : stage.getJobInstances()) { job.setIdentifier(new JobIdentifier(pipeline, stage, job)); } pipeline.setId(PIPELINE_ID); pipeline.updateCounter(9); } @Test public void shouldGetAPresenterWithLabelAndRelevantBuildPlansAndPipelineNameAndId() throws Exception { StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, null, new Agents()); Map json = presenter.toJson(); new JsonTester(json).shouldContain( "{ 'pipelineName' : 'pipeline'," + " 'stageName' : 'stage'," + " 'builds' : [" + " { 'name' : 'job-that-will-fail' }," + " { 'name' : 'job-that-will-pass' }," + " { 'name' : 'scheduledBuild' }" + " ]," + " 'current_label' : '" + pipeline.getLabel() + "', " + " 'pipelineCounter' : '" + pipeline.getCounter() + "', " + " 'pipelineCounterOrLabel' : '" + pipeline.getIdentifier().instanceIdentifier() + "', " + " 'id' : '1' " + "}" ); assertFalse("JSON shouldn't contain last_successful_label", json.toString().contains("last_successful_label")); } @Test public void shouldGetAPresenterWithLabelAndRelevantBuildPlans() throws Exception { DurationBeans durations = new DurationBeans( new DurationBean(stage.getJobInstances().getByName("job-that-will-fail").getId(), 12L)); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, null, new Agents(), durations, new TrackingTool()); Map json = presenter.toJson(); new JsonTester(json).shouldContain( "{ 'stageName' : 'stage'," + " 'builds' : [" + " { 'name' : 'job-that-will-fail', 'last_build_duration' : '12' }," + " { 'name' : 'job-that-will-pass' }, " + " { 'name' : 'scheduledBuild' }" + " ]," + " 'current_label' : '" + pipeline.getLabel() + "'," + " 'id' : '1' " + "}" ); assertFalse("JSON shouldn't contain last_successful_label", json.toString().contains("last_successful_label")); } @Test public void shouldReturnBuildingStatusIfAnyBuildsAreScheduled() throws Exception { StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, null, new Agents()); Map json = presenter.toJson(); new JsonTester(json).shouldContain( "{ 'current_status' : 'failing' }" ); } @Test public void shouldReturnJsonWithModifications() throws Exception { StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, null, new Agents()); Map json = presenter.toJson(); JsonValue jsonValue = JsonUtils.from(json); JsonValue revision = jsonValue.getObject("materialRevisions", 0); //TODO: TRAINWRECK! WE should fix this when we re-do the JSON. We don't think this test will last long in the new UI String expected = modifications .getMaterialRevisions() .getMaterialRevision(0) .getModifications().get(0).getRevision(); assertThat(revision.getString("revision"), is(expected)); assertThat(revision.getString("user"), is(ModificationsMother.MOD_USER_WITH_HTML_CHAR)); assertThat(revision.getString("date"), is(DateUtils.formatISO8601(ModificationsMother.TODAY_CHECKIN))); } @Test public void shouldReturnJsonForNullStage() throws Exception { final StageConfig config = StageConfigMother.oneBuildPlanWithResourcesAndMaterials("newStage"); StageJsonPresentationModel presenter = new StageJsonPresentationModel( pipeline, NullStage.createNullStage(config), null, new Agents()); Map json = presenter.toJson(); new JsonTester((List)json.get("builds")).shouldContain( "[{ 'current_status' : 'unknown' }]" ); } @Test public void shouldReturnLastSuccesfulLabel() throws Exception { StageIdentifier successfulStage = new StageIdentifier(pipeline.getName(), 1, "LABEL:1", stage.getName(), "1"); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, successfulStage, new Agents()); Map json = presenter.toJson(); new JsonTester(json).shouldContain( "{ 'last_successful_label' : 'LABEL:1', 'last_successful_stage_locator' : '" + String.format("%s/%s/%s/%s", pipeline.getName(), "1", stage.getName(), "1") + "' }" ); } @Test public void shouldGetAPresenterWithCanRunStatus() throws Exception { StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, null, new Agents()); presenter.setCanRun(true); Map json = presenter.toJson(); new JsonTester(json).shouldContain("{ 'getCanRun' : 'true' }"); } @Test public void shouldGetAPresenterWithCanCancelStatus() throws Exception { StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, null, new Agents()); presenter.setCanCancel(true); Map json = presenter.toJson(); new JsonTester(json).shouldContain("{ 'getCanCancel' : 'true' }"); } @Test public void shouldSetCanRunToFalseForANullStage() throws Exception { Stage unscheduled = new NullStage("unscheduled"); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, unscheduled, null, new Agents()); Map json = presenter.toJson(); new JsonTester(json).shouldContain("{ 'getCanRun' : 'false' }"); } @Test public void shouldEscapeBuildCauseMessage() throws Exception { String userWithHtmlCharacters = "<user>"; pipeline.setBuildCause(BuildCause.createManualForced(materialRevisions(userWithHtmlCharacters), new Username(new CaseInsensitiveString(userWithHtmlCharacters)))); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage, null, new Agents()); JsonTester jsonTester = new JsonTester(presenter.toJson()); String expected = StringEscapeUtils.escapeHtml(userWithHtmlCharacters); jsonTester.shouldContain("{'buildCause':'Forced by " + expected + "'}"); } @Test public void shouldEncodeStageLocator() throws Exception { Stage stage1 = new Stage("stage-c%d", new JobInstances(), GoConstants.DEFAULT_APPROVED_BY, "manual", new TimeProvider()); stage1.setIdentifier(new StageIdentifier("pipeline-a%b", 1, "label-1", "stage-c%d", "1")); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage1, null, new Agents()); Map json = presenter.toJson(); assertThat(JsonUtils.from(json).getString("stageLocator"), is("pipeline-a%25b/1/stage-c%25d/1")); } @Test public void shouldIncludeStageLocatorForDisplay() throws Exception { Stage stage1 = new Stage("stage-c%d", new JobInstances(), GoConstants.DEFAULT_APPROVED_BY, "manual", new TimeProvider()); stage1.setIdentifier(new StageIdentifier("pipeline-a%b", 1, "label-1", "stage-c%d", "1")); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage1, null, new Agents()); Map json = presenter.toJson(); assertThat(JsonUtils.from(json).getString("stageLocatorForDisplay"), is("pipeline-a%b/label-1/stage-c%d/1")); } @Test public void shouldEncodeBuildLocator() throws Exception { JobInstance job = JobInstanceMother.assigned("job-%"); Stage stage1 = new Stage("stage-c%d", new JobInstances(job), GoConstants.DEFAULT_APPROVED_BY, "manual", new TimeProvider()); stage1.setIdentifier(new StageIdentifier("pipeline-a%b", 1, "label-1", "stage-c%d", "1")); job.setIdentifier(new JobIdentifier("pipeline-a%b", 1, "label-1", "stage-c%d", "1", "job-%", 0L)); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage1, null, new Agents()); Map json = presenter.toJson(); assertThat(JsonUtils.from(json).getString("builds", 0, "buildLocator"), is("pipeline-a%25b/1/stage-c%25d/1/job-%25")); } private MaterialRevisions materialRevisions(String userWithHtmlCharacters) { MaterialRevisions revisions = new MaterialRevisions(); revisions.addRevision(MaterialsMother.svnMaterial(), new Modification(userWithHtmlCharacters, "comment", "email", new Date(), "r1")); return revisions; } }