github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/web/elm/tests/BuildStepTests.elm (about)

     1  module BuildStepTests exposing (all)
     2  
     3  import Application.Application as Application
     4  import Array
     5  import Assets
     6  import Build.StepTree.Models exposing (BuildEvent(..))
     7  import Colors
     8  import Common
     9      exposing
    10          ( defineHoverBehaviour
    11          , given
    12          , iOpenTheBuildPage
    13          , myBrowserFetchedTheBuild
    14          , then_
    15          , when
    16          )
    17  import Concourse exposing (JsonValue(..))
    18  import Concourse.BuildStatus exposing (BuildStatus(..))
    19  import DashboardTests exposing (iconSelector)
    20  import Dict
    21  import Expect
    22  import Json.Encode
    23  import Message.Callback as Callback
    24  import Message.Effects as Effects
    25  import Message.Message as Message exposing (DomID(..))
    26  import Message.Subscription exposing (Delivery(..), Interval(..))
    27  import Message.TopLevelMessage exposing (TopLevelMessage(..))
    28  import Routes
    29  import Test exposing (Test, describe, test)
    30  import Test.Html.Event as Event
    31  import Test.Html.Query as Query
    32  import Test.Html.Selector exposing (class, containing, style, tag, text)
    33  import Time
    34  import Views.Styles
    35  
    36  
    37  all : Test
    38  all =
    39      describe "build steps"
    40          [ describe "get step metadata"
    41              [ test "has a table that left aligns text in cells" <|
    42                  given iVisitABuildWithAGetStep
    43                      >> given theGetStepIsExpanded
    44                      >> when iAmLookingAtTheStepBody
    45                      >> when iAmLookingAtTheMetadataTableCells
    46                      >> then_ iSeeTheyLeftAlignText
    47              , test "has a table that top aligns text in cells" <|
    48                  given iVisitABuildWithAGetStep
    49                      >> given theGetStepIsExpanded
    50                      >> when iAmLookingAtTheStepBody
    51                      >> when iAmLookingAtTheMetadataTableCells
    52                      >> then_ iSeeTheyTopAlignText
    53              , test "has a table that padds in cells" <|
    54                  given iVisitABuildWithAGetStep
    55                      >> given theGetStepIsExpanded
    56                      >> when iAmLookingAtTheStepBody
    57                      >> when iAmLookingAtTheMetadataTableCells
    58                      >> then_ iSeeTheyHavePaddingAllAround
    59              , test "has a table that has a bottom margin to let content (logs) underneath breathe" <|
    60                  given iVisitABuildWithAGetStep
    61                      >> given theGetStepIsExpanded
    62                      >> when iAmLookingAtTheStepBody
    63                      >> when iAmLookingAtTheMetadataTable
    64                      >> then_ iSeeABottomMargin
    65              , test "has a table that has cells with bottom borders" <|
    66                  given iVisitABuildWithAGetStep
    67                      >> given theGetStepIsExpanded
    68                      >> when iAmLookingAtTheStepBody
    69                      >> when iAmLookingAtTheMetadataTableCells
    70                      >> then_ iSeeLightGrayBottomBorder
    71              , test "has a table with cells that don't have a shared border" <|
    72                  given iVisitABuildWithAGetStep
    73                      >> given theGetStepIsExpanded
    74                      >> when iAmLookingAtTheStepBody
    75                      >> when iAmLookingAtTheMetadataTable
    76                      >> then_ iSeeATableWithBorderCollapse
    77              , test "has a table that colors key cells light gray" <|
    78                  given iVisitABuildWithAGetStep
    79                      >> given theGetStepIsExpanded
    80                      >> when iAmLookingAtTheStepBody
    81                      >> when iAmLookingAtTheMetadataTableKeyCell
    82                      >> then_ iSeeLightGrayCellBackground
    83              , test "has a table that colors value cells dark gray" <|
    84                  given iVisitABuildWithAGetStep
    85                      >> given theGetStepIsExpanded
    86                      >> when iAmLookingAtTheStepBody
    87                      >> when iAmLookingAtTheMetadataTableValueCell
    88                      >> then_ iSeeDarkGrayCellBackground
    89              ]
    90          , describe "retry step"
    91              [ test "has tab list above" <|
    92                  given iVisitABuildWithARetryStep
    93                      >> when iAmLookingAtTheRetryStepInTheBuildOutput
    94                      >> then_ iSeeTwoChildren
    95              , describe "tab list"
    96                  [ test "is a list" <|
    97                      given iVisitABuildWithARetryStep
    98                          >> when iAmLookingAtTheTabList
    99                          >> then_ iSeeItIsAList
   100                  , test "does not have the default vertical margins" <|
   101                      given iVisitABuildWithARetryStep
   102                          >> when iAmLookingAtTheTabList
   103                          >> then_ iSeeNoMargin
   104                  , test "has large font" <|
   105                      given iVisitABuildWithARetryStep
   106                          >> when iAmLookingAtTheTabList
   107                          >> then_ iSeeLargeFont
   108                  , test "has tall lines" <|
   109                      given iVisitABuildWithARetryStep
   110                          >> when iAmLookingAtTheTabList
   111                          >> then_ iSeeTallLines
   112                  , test "has grey background" <|
   113                      given iVisitABuildWithARetryStep
   114                          >> when iAmLookingAtTheTabList
   115                          >> then_ iSeeAGreyBackground
   116                  , test "has as many tabs as retries" <|
   117                      given iVisitABuildWithARetryStep
   118                          >> when iAmLookingAtTheTabList
   119                          >> then_ iSeeTwoChildren
   120                  , describe "tabs"
   121                      [ test "lay out horizontally" <|
   122                          given iVisitABuildWithARetryStep
   123                              >> when iAmLookingAtTheTabList
   124                              >> then_ iSeeItLaysOutHorizontally
   125                      , test "have default font weight" <|
   126                          given iVisitABuildWithARetryStep
   127                              >> when iAmLookingAtTheFirstTab
   128                              >> then_ iSeeDefaultFontWeight
   129                      , test "have pointer cursor" <|
   130                          given iVisitABuildWithARetryStep
   131                              >> when iAmLookingAtTheFirstTab
   132                              >> then_ iSeePointerCursor
   133                      , test "have light grey text" <|
   134                          given iVisitABuildWithARetryStep
   135                              >> when iAmLookingAtTheFirstTab
   136                              >> then_ iSeeLightGreyText
   137                      , defineHoverBehaviour
   138                          { name = "build tab"
   139                          , setup = iVisitABuildWithARetryStep () |> Tuple.first
   140                          , query = (\m -> ( m, [] )) >> iAmLookingAtTheSecondTab
   141                          , unhoveredSelector =
   142                              { description = "grey background"
   143                              , selector =
   144                                  [ style "background-color" Colors.background ]
   145                              }
   146                          , hoverable = StepTab "retryStepId" 1
   147                          , hoveredSelector =
   148                              { description = "lighter grey background"
   149                              , selector =
   150                                  [ style "background-color" Colors.paginationHover ]
   151                              }
   152                          }
   153                      , test "have click handlers" <|
   154                          given iVisitABuildWithARetryStep
   155                              >> when iAmLookingAtTheFirstTab
   156                              >> then_ (itIsClickable <| StepTab "retryStepId" 0)
   157                      , test "have horizontal spacing" <|
   158                          given iVisitABuildWithARetryStep
   159                              >> when iAmLookingAtTheFirstTab
   160                              >> then_ itHasHorizontalSpacing
   161                      , describe "pending selected attempt"
   162                          [ test "has lighter grey background" <|
   163                              given iVisitABuildWithARetryStep
   164                                  >> when iAmLookingAtTheFirstTab
   165                                  >> then_ iSeeALighterGreyBackground
   166                          , test "is transparent" <|
   167                              given iVisitABuildWithARetryStep
   168                                  >> when iAmLookingAtTheFirstTab
   169                                  >> then_ iSeeItIsTransparent
   170                          ]
   171                      , describe "started selected attempt"
   172                          [ test "has lighter grey background" <|
   173                              given iVisitABuildWithARetryStep
   174                                  >> given theFirstAttemptInitialized
   175                                  >> when iAmLookingAtTheFirstTab
   176                                  >> then_ iSeeALighterGreyBackground
   177                          , test "is opaque" <|
   178                              given iVisitABuildWithARetryStep
   179                                  >> given theFirstAttemptInitialized
   180                                  >> when iAmLookingAtTheFirstTab
   181                                  >> then_ iSeeItIsOpaque
   182                          ]
   183                      , describe "pending unselected attempt"
   184                          [ test "has grey background" <|
   185                              given iVisitABuildWithARetryStep
   186                                  >> when iAmLookingAtTheSecondTab
   187                                  >> then_ iSeeAGreyBackground
   188                          , test "is transparent" <|
   189                              given iVisitABuildWithARetryStep
   190                                  >> when iAmLookingAtTheSecondTab
   191                                  >> then_ iSeeItIsTransparent
   192                          ]
   193                      , describe "started unselected attempt"
   194                          [ test "has lighter grey background" <|
   195                              given iVisitABuildWithARetryStep
   196                                  >> given theSecondAttemptInitialized
   197                                  >> when iAmLookingAtTheFirstTab
   198                                  >> then_ iSeeAGreyBackground
   199                          , test "is opaque" <|
   200                              given iVisitABuildWithARetryStep
   201                                  >> given theSecondAttemptInitialized
   202                                  >> when iAmLookingAtTheSecondTab
   203                                  >> then_ iSeeItIsOpaque
   204                          ]
   205                      , describe "cancelled unselected attempt" <|
   206                          [ test "is transparent" <|
   207                              given iVisitABuildWithARetryStep
   208                                  >> given theBuildFinished
   209                                  >> when iAmLookingAtTheSecondTab
   210                                  >> then_ iSeeItIsTransparent
   211                          ]
   212                      ]
   213                  ]
   214              ]
   215          , describe "across step"
   216              [ test "shows var names" <|
   217                  given iVisitABuildWithAnAcrossStep
   218                      >> when iAmLookingAtTheAcrossStepInTheBuildOutput
   219                      >> then_ iSeeTheVarNames
   220              , describe "sub headers"
   221                  [ test "has as many sub headers as sub steps" <|
   222                      given iVisitABuildWithAnAcrossStep
   223                          >> given theAcrossStepIsExpanded
   224                          >> when iAmLookingAtTheAcrossSubHeaders
   225                          >> then_ iSeeFourOfThem
   226                  , test "appears behind top-level headers" <|
   227                      given iVisitABuildWithAnAcrossStep
   228                          >> given theAcrossStepIsExpanded
   229                          >> when iAmLookingAtTheFirstAcrossSubHeader
   230                          >> then_ iSeeItAppearsBehindTopLevelHeaders
   231                  , test "have key-value pairs for the vars" <|
   232                      given iVisitABuildWithAnAcrossStep
   233                          >> given theAcrossStepIsExpanded
   234                          >> when iAmLookingAtTheAcrossSubHeaders
   235                          >> then_ iSeeTheKeyValuePairs
   236                  , test "display subtree when expanded" <|
   237                      given iVisitABuildWithAnAcrossStep
   238                          >> given theAcrossStepIsExpanded
   239                          >> given theFirstAcrossSubHeaderIsExpanded
   240                          >> when iAmLookingAtTheAcrossStepInTheBuildOutput
   241                          >> then_ iSeeATaskHeader
   242                  , describe "shows status of subtree"
   243                      [ test "pending" <|
   244                          given iVisitABuildWithAnAcrossStep
   245                              >> given theAcrossStepIsExpanded
   246                              >> when iAmLookingAtTheFirstAcrossSubHeader
   247                              >> then_ (iSeeStatusIcon Assets.PendingIcon)
   248                      , test "running" <|
   249                          given iVisitABuildWithAnAcrossStep
   250                              >> given theAcrossStepIsExpanded
   251                              >> given theFirstTaskInitialized
   252                              >> when iAmLookingAtTheFirstAcrossSubHeader
   253                              >> then_ iSeeASpinner
   254                      , test "succeeded" <|
   255                          given iVisitABuildWithAnAcrossStep
   256                              >> given theAcrossStepIsExpanded
   257                              >> given theFirstTaskSucceeded
   258                              >> when iAmLookingAtTheFirstAcrossSubHeader
   259                              >> then_ (iSeeStatusIcon Assets.SuccessCheckIcon)
   260                      , test "failed" <|
   261                          given iVisitABuildWithAnAcrossStep
   262                              >> given theAcrossStepIsExpanded
   263                              >> given theFirstTaskFailed
   264                              >> when iAmLookingAtTheFirstAcrossSubHeader
   265                              >> then_ (iSeeStatusIcon Assets.FailureTimesIcon)
   266                      , test "errored" <|
   267                          given iVisitABuildWithAnAcrossStep
   268                              >> given theAcrossStepIsExpanded
   269                              >> given theFirstTaskErrored
   270                              >> when iAmLookingAtTheFirstAcrossSubHeader
   271                              >> then_ (iSeeStatusIcon Assets.ExclamationTriangleIcon)
   272                      , test "interrupted" <|
   273                          given iVisitABuildWithAnAcrossStep
   274                              >> given theAcrossStepIsExpanded
   275                              >> given theFirstTaskIsInterrupted
   276                              >> when iAmLookingAtTheFirstAcrossSubHeader
   277                              >> then_ (iSeeStatusIcon Assets.InterruptedIcon)
   278                      , test "cancelled" <|
   279                          given iVisitABuildWithAnAcrossStep
   280                              >> given theAcrossStepIsExpanded
   281                              >> given theFirstTaskIsCancelled
   282                              >> when iAmLookingAtTheFirstAcrossSubHeader
   283                              >> then_ (iSeeStatusIcon Assets.CancelledIcon)
   284                      , test "does not consider unreachable steps in retry" <|
   285                          given iVisitABuildWithAnAcrossStepWrappingARetryStep
   286                              >> given theAcrossStepIsExpanded
   287                              >> given theFirstAttemptSucceeded
   288                              >> when iAmLookingAtTheFirstAcrossSubHeader
   289                              >> then_ (iSeeStatusIcon Assets.SuccessCheckIcon)
   290                      , test "does not consider unreachable hook in on_failure" <|
   291                          given (iVisitABuildWithAnAcrossStepWrappingAHook Concourse.BuildStepOnFailure)
   292                              >> given theAcrossStepIsExpanded
   293                              >> given theStepSucceeded
   294                              >> when iAmLookingAtTheFirstAcrossSubHeader
   295                              >> then_ (iSeeStatusIcon Assets.SuccessCheckIcon)
   296                      , test "does not consider unreachable hook in on_error" <|
   297                          given (iVisitABuildWithAnAcrossStepWrappingAHook Concourse.BuildStepOnError)
   298                              >> given theAcrossStepIsExpanded
   299                              >> given theStepSucceeded
   300                              >> when iAmLookingAtTheFirstAcrossSubHeader
   301                              >> then_ (iSeeStatusIcon Assets.SuccessCheckIcon)
   302                      , test "does not consider unreachable hook in on_abort" <|
   303                          given (iVisitABuildWithAnAcrossStepWrappingAHook Concourse.BuildStepOnAbort)
   304                              >> given theAcrossStepIsExpanded
   305                              >> given theStepSucceeded
   306                              >> when iAmLookingAtTheFirstAcrossSubHeader
   307                              >> then_ (iSeeStatusIcon Assets.SuccessCheckIcon)
   308                      ]
   309                  , describe "complex values"
   310                      [ test "displays object fields with dot notation" <|
   311                          given iVisitABuildWithAnAcrossStepWithComplexValues
   312                              >> given theAcrossStepIsExpanded
   313                              >> when iAmLookingAtTheFirstAcrossSubHeader
   314                              >> then_ iSeeTheObjectKeyValuePairs
   315                      , test "displays array fields with index notation" <|
   316                          given iVisitABuildWithAnAcrossStepWithComplexValues
   317                              >> given theAcrossStepIsExpanded
   318                              >> when iAmLookingAtTheSecondAcrossSubHeader
   319                              >> then_ iSeeTheArrayKeyValuePairs
   320                      ]
   321                  ]
   322              ]
   323          , describe "task step"
   324              [ test "logs show timestamps" <|
   325                  given iVisitABuildWithATaskStep
   326                      >> given (thereIsALog taskStepId)
   327                      >> given theTaskStepIsExpanded
   328                      >> when iAmLookingAtTheStepBody
   329                      >> then_ iSeeATimestamp
   330              , test "shows image check sub-step" <|
   331                  given iVisitABuildWithATaskStep
   332                      >> given (thereIsAnImageCheckStep taskStepId)
   333                      >> given (thereIsALog imageCheckStepId)
   334                      >> given theTaskInitializationIsExpanded
   335                      >> given theImageCheckStepIsExpanded
   336                      >> when iAmLookingAtTheStepBody
   337                      >> then_ iSeeTheLogOutput
   338              , test "shows image get sub-step" <|
   339                  given iVisitABuildWithATaskStep
   340                      >> given (thereIsAnImageGetStep taskStepId)
   341                      >> given (thereIsALog imageGetStepId)
   342                      >> given theTaskInitializationIsExpanded
   343                      >> given theImageGetStepIsExpanded
   344                      >> when iAmLookingAtTheStepBody
   345                      >> then_ iSeeTheLogOutput
   346              , test "initialization toggle gets viewport for tooltip" <|
   347                  given iVisitABuildWithATaskStep
   348                      >> given (thereIsAnImageGetStep taskStepId)
   349                      >> given iHoverOverInitializationToggle
   350                      >> given timeElapses
   351                      >> then_ (itGetsViewportOf initializationToggleID)
   352              , test "initialization toggle shows tooltip" <|
   353                  given iVisitABuildWithATaskStep
   354                      >> given (thereIsAnImageGetStep taskStepId)
   355                      >> given iHoverOverInitializationToggle
   356                      >> given (gotViewportAndElementOf initializationToggleID)
   357                      >> then_ (iSeeText "image fetching")
   358              ]
   359          , describe "check step"
   360              [ test "should show resource name" <|
   361                  given iVisitABuildWithACheckStep
   362                      >> given theCheckStepIsExpanded
   363                      >> when iAmLookingAtTheStepBody
   364                      >> then_ iSeeTheResourceName
   365              ]
   366          , describe "set-pipeline step"
   367              [ test "should show pipeline name" <|
   368                  given iVisitABuildWithASetPipelineStep
   369                      >> given theSetPipelineStepIsExpanded
   370                      >> when iAmLookingAtTheStepBody
   371                      >> then_ iSeeThePipelineName
   372              ]
   373          , describe "load_var step"
   374              [ test "should show var name" <|
   375                  given iVisitABuildWithALoadVarStep
   376                      >> given theLoadVarStepIsExpanded
   377                      >> when iAmLookingAtTheStepBody
   378                      >> then_ iSeeTheLoadVarName
   379              ]
   380          ]
   381  
   382  
   383  gotViewportAndElementOf domID =
   384      Tuple.first
   385          >> Application.handleCallback
   386              (Callback.GotViewport domID <|
   387                  Ok
   388                      { scene =
   389                          { width = 1
   390                          , height = 0
   391                          }
   392                      , viewport =
   393                          { width = 1
   394                          , height = 0
   395                          , x = 0
   396                          , y = 0
   397                          }
   398                      }
   399              )
   400          >> Tuple.first
   401          >> Application.handleCallback
   402              (Callback.GotElement <|
   403                  Ok
   404                      { scene =
   405                          { width = 0
   406                          , height = 0
   407                          }
   408                      , viewport =
   409                          { width = 0
   410                          , height = 0
   411                          , x = 0
   412                          , y = 0
   413                          }
   414                      , element =
   415                          { x = 0
   416                          , y = 0
   417                          , width = 1
   418                          , height = 1
   419                          }
   420                      }
   421              )
   422  
   423  
   424  iHoverOverInitializationToggle =
   425      Tuple.first
   426          >> Application.update
   427              (Update <| Message.Hover <| Just initializationToggleID)
   428  
   429  
   430  timeElapses =
   431      Tuple.first
   432          >> Application.handleDelivery
   433              (ClockTicked OneSecond <|
   434                  Time.millisToPosix 0
   435              )
   436  
   437  
   438  itGetsViewportOf domID =
   439      Tuple.second
   440          >> Common.contains (Effects.GetViewportOf domID)
   441  
   442  
   443  initializationToggleID =
   444      Message.StepInitialization "foo"
   445  
   446  
   447  iVisitABuildWithARetryStep =
   448      iOpenTheBuildPage
   449          >> myBrowserFetchedTheBuild
   450          >> thePlanContainsARetryStep
   451  
   452  
   453  iVisitABuildWithAnAcrossStep =
   454      iOpenTheBuildPage
   455          >> myBrowserFetchedTheBuild
   456          >> thePlanContainsAnAcrossStep
   457  
   458  
   459  iVisitABuildWithAnAcrossStepWrappingARetryStep =
   460      iOpenTheBuildPage
   461          >> myBrowserFetchedTheBuild
   462          >> thePlanContainsAnAcrossStepWithSubplan
   463              { id = "retryStepId"
   464              , step =
   465                  Concourse.BuildStepRetry
   466                      (Array.fromList
   467                          [ { id = "attempt1Id"
   468                            , step =
   469                                  Concourse.BuildStepTask
   470                                      "taskName"
   471                            }
   472                          , { id = "attempt2Id"
   473                            , step =
   474                                  Concourse.BuildStepTask
   475                                      "taskName"
   476                            }
   477                          ]
   478                      )
   479              }
   480  
   481  
   482  iVisitABuildWithAnAcrossStepWrappingAHook hook =
   483      iOpenTheBuildPage
   484          >> myBrowserFetchedTheBuild
   485          >> thePlanContainsAnAcrossStepWithSubplan
   486              { id = "retryStepId"
   487              , step =
   488                  hook
   489                      { step =
   490                          { id = "stepId"
   491                          , step =
   492                              Concourse.BuildStepTask
   493                                  "taskName"
   494                          }
   495                      , hook =
   496                          { id = "hookId"
   497                          , step =
   498                              Concourse.BuildStepTask
   499                                  "taskName"
   500                          }
   501                      }
   502              }
   503  
   504  
   505  iVisitABuildWithAnAcrossStepWithComplexValues =
   506      iOpenTheBuildPage
   507          >> myBrowserFetchedTheBuild
   508          >> thePlanContainsAnAcrossStepWithComplexValues
   509  
   510  
   511  iVisitABuildWithATaskStep =
   512      iOpenTheBuildPage
   513          >> myBrowserFetchedTheBuild
   514          >> thePlanContainsATaskStep
   515  
   516  
   517  iVisitABuildWithAGetStep =
   518      iOpenTheBuildPage
   519          >> myBrowserFetchedTheBuild
   520          >> thePlanContainsAGetStep
   521          >> theGetStepReturnsMetadata
   522  
   523  
   524  iVisitABuildWithASetPipelineStep =
   525      iOpenTheBuildPage
   526          >> myBrowserFetchedTheBuild
   527          >> thePlanContainsASetPipelineStep
   528  
   529  
   530  iVisitABuildWithACheckStep =
   531      iOpenTheBuildPage
   532          >> myBrowserFetchedTheBuild
   533          >> thePlanContainsACheckStep
   534  
   535  
   536  iVisitABuildWithALoadVarStep =
   537      iOpenTheBuildPage
   538          >> myBrowserFetchedTheBuild
   539          >> thePlanContainsALoadVarStep
   540  
   541  
   542  theGetStepIsExpanded =
   543      Tuple.first
   544          >> Application.update (Update <| Message.Click <| StepHeader "getStepId")
   545  
   546  
   547  theTaskStepIsExpanded =
   548      Tuple.first
   549          >> Application.update (Update <| Message.Click <| StepHeader taskStepId)
   550  
   551  
   552  theTaskInitializationIsExpanded =
   553      Tuple.first
   554          >> Application.update (Update <| Message.Click <| StepInitialization taskStepId)
   555  
   556  
   557  theImageCheckStepIsExpanded =
   558      Tuple.first
   559          >> Application.update (Update <| Message.Click <| StepHeader imageCheckStepId)
   560  
   561  
   562  theImageGetStepIsExpanded =
   563      Tuple.first
   564          >> Application.update (Update <| Message.Click <| StepHeader imageGetStepId)
   565  
   566  
   567  theSetPipelineStepIsExpanded =
   568      Tuple.first
   569          >> Application.update (Update <| Message.Click <| StepHeader setPipelineStepId)
   570  
   571  
   572  theCheckStepIsExpanded =
   573      Tuple.first
   574          >> Application.update (Update <| Message.Click <| StepHeader checkStepId)
   575  
   576  
   577  theLoadVarStepIsExpanded =
   578      Tuple.first
   579          >> Application.update (Update <| Message.Click <| StepHeader setLoadVarStepId)
   580  
   581  
   582  theAcrossStepIsExpanded =
   583      Tuple.first
   584          >> Application.update (Update <| Message.Click <| StepHeader acrossStepId)
   585  
   586  
   587  thePlanContainsARetryStep =
   588      Tuple.first
   589          >> Application.handleCallback
   590              (Callback.PlanAndResourcesFetched 1 <|
   591                  Ok
   592                      ( { id = "retryStepId"
   593                        , step =
   594                              Concourse.BuildStepRetry
   595                                  (Array.fromList
   596                                      [ { id = "attempt1Id"
   597                                        , step =
   598                                              Concourse.BuildStepTask
   599                                                  "taskName"
   600                                        }
   601                                      , { id = "attempt2Id"
   602                                        , step =
   603                                              Concourse.BuildStepTask
   604                                                  "taskName"
   605                                        }
   606                                      ]
   607                                  )
   608                        }
   609                      , { inputs = []
   610                        , outputs = []
   611                        }
   612                      )
   613              )
   614  
   615  
   616  thePlanContainsAnAcrossStep =
   617      Tuple.first
   618          >> Application.handleCallback
   619              (Callback.PlanAndResourcesFetched 1 <|
   620                  Ok
   621                      ( { id = acrossStepId
   622                        , step =
   623                              Concourse.BuildStepAcross
   624                                  { vars = [ "var1", "var2" ]
   625                                  , steps =
   626                                      [ ( [ JsonString "a1", JsonString "b1" ]
   627                                        , { id = "task1Id"
   628                                          , step =
   629                                              Concourse.BuildStepTask
   630                                                  "taskName"
   631                                          }
   632                                        )
   633                                      , ( [ JsonString "a1", JsonString "b2" ]
   634                                        , { id = "task2Id"
   635                                          , step =
   636                                              Concourse.BuildStepTask
   637                                                  "taskName"
   638                                          }
   639                                        )
   640                                      , ( [ JsonString "a2", JsonString "b1" ]
   641                                        , { id = "task3Id"
   642                                          , step =
   643                                              Concourse.BuildStepTask
   644                                                  "taskName"
   645                                          }
   646                                        )
   647                                      , ( [ JsonString "a2", JsonString "b2" ]
   648                                        , { id = "task4Id"
   649                                          , step =
   650                                              Concourse.BuildStepTask
   651                                                  "taskName"
   652                                          }
   653                                        )
   654                                      ]
   655                                  }
   656                        }
   657                      , { inputs = []
   658                        , outputs = []
   659                        }
   660                      )
   661              )
   662  
   663  
   664  thePlanContainsAnAcrossStepWithSubplan plan =
   665      Tuple.first
   666          >> Application.handleCallback
   667              (Callback.PlanAndResourcesFetched 1 <|
   668                  Ok
   669                      ( { id = acrossStepId
   670                        , step =
   671                              Concourse.BuildStepAcross
   672                                  { vars = [ "var1" ]
   673                                  , steps = [ ( [ JsonString "a1" ], plan ) ]
   674                                  }
   675                        }
   676                      , { inputs = []
   677                        , outputs = []
   678                        }
   679                      )
   680              )
   681  
   682  
   683  thePlanContainsAnAcrossStepWithComplexValues =
   684      Tuple.first
   685          >> Application.handleCallback
   686              (Callback.PlanAndResourcesFetched 1 <|
   687                  Ok
   688                      ( { id = acrossStepId
   689                        , step =
   690                              Concourse.BuildStepAcross
   691                                  { vars = [ "var1" ]
   692                                  , steps =
   693                                      [ ( [ JsonObject
   694                                              [ ( "f1", JsonString "v1" )
   695                                              , ( "f2", JsonNumber 1 )
   696                                              , ( "f3"
   697                                                , JsonRaw
   698                                                      (Json.Encode.object
   699                                                          [ ( "abc", Json.Encode.int 123 ) ]
   700                                                      )
   701                                                )
   702                                              ]
   703                                          ]
   704                                        , { id = "task1Id"
   705                                          , step =
   706                                              Concourse.BuildStepTask
   707                                                  "taskName"
   708                                          }
   709                                        )
   710                                      , ( [ JsonArray
   711                                              [ JsonString "v1"
   712                                              , JsonNumber 1
   713                                              ]
   714                                          ]
   715                                        , { id = "task2Id"
   716                                          , step =
   717                                              Concourse.BuildStepTask
   718                                                  "taskName"
   719                                          }
   720                                        )
   721                                      ]
   722                                  }
   723                        }
   724                      , { inputs = []
   725                        , outputs = []
   726                        }
   727                      )
   728              )
   729  
   730  
   731  thePlanContainsATaskStep =
   732      Tuple.first
   733          >> Application.handleCallback
   734              (Callback.PlanAndResourcesFetched 1 <|
   735                  Ok
   736                      ( { id = taskStepId
   737                        , step = Concourse.BuildStepTask "task-name"
   738                        }
   739                      , { inputs = []
   740                        , outputs = []
   741                        }
   742                      )
   743              )
   744  
   745  
   746  taskStepId =
   747      "taskStepId"
   748  
   749  
   750  imageCheckStepId =
   751      "imageCheckStepId"
   752  
   753  
   754  imageGetStepId =
   755      "imageGetStepId"
   756  
   757  
   758  thePlanContainsASetPipelineStep =
   759      Tuple.first
   760          >> Application.handleCallback
   761              (Callback.PlanAndResourcesFetched 1 <|
   762                  Ok
   763                      ( { id = setPipelineStepId
   764                        , step = Concourse.BuildStepSetPipeline "pipeline-name"
   765                        }
   766                      , { inputs = []
   767                        , outputs = []
   768                        }
   769                      )
   770              )
   771  
   772  
   773  setPipelineStepId =
   774      "setPipelineStep"
   775  
   776  
   777  thePlanContainsACheckStep =
   778      Tuple.first
   779          >> Application.handleCallback
   780              (Callback.PlanAndResourcesFetched 1 <|
   781                  Ok
   782                      ( { id = checkStepId
   783                        , step = Concourse.BuildStepCheck "resource-name"
   784                        }
   785                      , { inputs = []
   786                        , outputs = []
   787                        }
   788                      )
   789              )
   790  
   791  
   792  checkStepId =
   793      "checkStep"
   794  
   795  
   796  thePlanContainsALoadVarStep =
   797      Tuple.first
   798          >> Application.handleCallback
   799              (Callback.PlanAndResourcesFetched 1 <|
   800                  Ok
   801                      ( { id = setLoadVarStepId
   802                        , step = Concourse.BuildStepLoadVar "var-name"
   803                        }
   804                      , { inputs = []
   805                        , outputs = []
   806                        }
   807                      )
   808              )
   809  
   810  
   811  setLoadVarStepId =
   812      "loadVarStep"
   813  
   814  
   815  acrossStepId =
   816      "acrossStep"
   817  
   818  
   819  thePlanContainsAGetStep =
   820      Tuple.first
   821          >> Application.handleCallback
   822              (Callback.PlanAndResourcesFetched 1 <|
   823                  Ok
   824                      ( { id = "getStepId"
   825                        , step =
   826                              Concourse.BuildStepGet
   827                                  "the-git-resource"
   828                                  (Just (Dict.fromList [ ( "ref", "abc123" ) ]))
   829                        }
   830                      , { inputs = []
   831                        , outputs = []
   832                        }
   833                      )
   834              )
   835  
   836  
   837  theGetStepReturnsMetadata =
   838      Tuple.first
   839          >> Application.update
   840              (DeliveryReceived <|
   841                  EventsReceived <|
   842                      Ok <|
   843                          [ { url = "http://localhost:8080/api/v1/builds/1/events"
   844                            , data =
   845                                  FinishGet
   846                                      { source = "stdout"
   847                                      , id = "getStepId"
   848                                      }
   849                                      1
   850                                      (Dict.fromList [ ( "ref", "abc123" ) ])
   851                                      [ { name = "metadata-field"
   852                                        , value = "metadata-value"
   853                                        }
   854                                      ]
   855                                      Nothing
   856                            }
   857                          ]
   858              )
   859  
   860  
   861  iSeeText str =
   862      Tuple.first
   863          >> Common.queryView
   864          >> Query.findAll [ text str ]
   865          >> Query.count (Expect.equal 1)
   866  
   867  
   868  iAmLookingAtTheRetryStepInTheBuildOutput =
   869      Tuple.first
   870          >> Common.queryView
   871          >> Query.find [ class "retry" ]
   872  
   873  
   874  iAmLookingAtTheAcrossStepInTheBuildOutput =
   875      Tuple.first
   876          >> Common.queryView
   877          >> Query.find [ class "build-step", containing [ text "across:" ] ]
   878  
   879  
   880  iAmLookingAtTheStepBody =
   881      Tuple.first
   882          >> Common.queryView
   883          >> Query.findAll [ class "build-step" ]
   884          >> Query.first
   885  
   886  
   887  iSeeTwoChildren =
   888      Query.children [] >> Query.count (Expect.equal 2)
   889  
   890  
   891  iSeeFourOfThem =
   892      Query.count (Expect.equal 4)
   893  
   894  
   895  iAmLookingAtTheMetadataTable =
   896      Query.find [ class "step-body" ]
   897          >> Query.find [ tag "table" ]
   898  
   899  
   900  iAmLookingAtTheMetadataTableCells =
   901      Query.find [ class "step-body" ]
   902          >> Query.find [ tag "table" ]
   903          >> Query.findAll [ tag "td" ]
   904  
   905  
   906  iAmLookingAtTheMetadataTableKeyCell =
   907      Query.find [ class "step-body" ]
   908          >> Query.find [ tag "table" ]
   909          >> Query.findAll [ tag "td" ]
   910          >> Query.first
   911  
   912  
   913  iAmLookingAtTheMetadataTableValueCell =
   914      Query.find [ class "step-body" ]
   915          >> Query.find [ tag "table" ]
   916          >> Query.findAll [ tag "td" ]
   917          >> Query.index 1
   918  
   919  
   920  iSeeTheyLeftAlignText =
   921      Query.each (Query.has [ style "text-align" "left" ])
   922  
   923  
   924  iSeeTheyTopAlignText =
   925      Query.each (Query.has [ style "vertical-align" "top" ])
   926  
   927  
   928  iSeeLightGrayCellBackground =
   929      Query.has [ style "background-color" "rgb(45,45,45)" ]
   930  
   931  
   932  iSeeDarkGrayCellBackground =
   933      Query.has [ style "background-color" "rgb(30,30,30)" ]
   934  
   935  
   936  iSeeATableWithBorderCollapse =
   937      Query.has [ style "border-collapse" "collapse" ]
   938  
   939  
   940  iSeeABottomMargin =
   941      Query.has [ style "margin-bottom" "5px" ]
   942  
   943  
   944  iSeeLightGrayBottomBorder =
   945      Query.each (Query.has [ style "border-bottom" "5px solid rgb(45,45,45)" ])
   946  
   947  
   948  iSeeTheyHavePaddingAllAround =
   949      Query.each (Query.has [ style "padding" "5px" ])
   950  
   951  
   952  iAmLookingAtTheTabList =
   953      iAmLookingAtTheRetryStepInTheBuildOutput
   954          >> Query.children []
   955          >> Query.first
   956  
   957  
   958  iAmLookingAtTheAcrossSubHeaders =
   959      iAmLookingAtTheAcrossStepInTheBuildOutput
   960          >> Query.findAll [ class "sub-header" ]
   961  
   962  
   963  kvPair k v =
   964      [ containing [ text k ], containing [ text v ] ]
   965  
   966  
   967  iSeeTheKeyValuePairs =
   968      Expect.all
   969          [ Query.index 0 >> Query.has (kvPair "var1" "a1" ++ kvPair "var2" "b1")
   970          , Query.index 1 >> Query.has (kvPair "var1" "a1" ++ kvPair "var2" "b2")
   971          , Query.index 2 >> Query.has (kvPair "var1" "a2" ++ kvPair "var2" "b1")
   972          , Query.index 3 >> Query.has (kvPair "var1" "a2" ++ kvPair "var2" "b2")
   973          ]
   974  
   975  
   976  iSeeTheObjectKeyValuePairs =
   977      Query.has
   978          (kvPair "var1.f1" "v1"
   979              ++ kvPair "var1.f2" "1"
   980              ++ kvPair "var1.f3" "{\"abc\":123}"
   981          )
   982  
   983  
   984  iSeeTheArrayKeyValuePairs =
   985      Query.has
   986          (kvPair "var1[0]" "v1"
   987              ++ kvPair "var1[1]" "1"
   988          )
   989  
   990  
   991  iAmLookingAtTheFirstAcrossSubHeader =
   992      iAmLookingAtTheAcrossSubHeaders >> Query.first
   993  
   994  
   995  iSeeItAppearsBehindTopLevelHeaders =
   996      Query.has [ style "z-index" "9" ]
   997  
   998  
   999  iAmLookingAtTheSecondAcrossSubHeader =
  1000      iAmLookingAtTheAcrossSubHeaders >> Query.index 1
  1001  
  1002  
  1003  theFirstAcrossSubHeaderIsExpanded =
  1004      Tuple.first
  1005          >> Application.update
  1006              (Update <|
  1007                  Message.Click <|
  1008                      StepSubHeader acrossStepId 0
  1009              )
  1010  
  1011  
  1012  iSeeATaskHeader =
  1013      Query.has [ class "header", containing [ text "task" ] ]
  1014  
  1015  
  1016  iSeeASpinner =
  1017      Query.has
  1018          [ style "animation" "container-rotate 1568ms linear infinite"
  1019          , style "height" "14px"
  1020          , style "width" "14px"
  1021          ]
  1022  
  1023  
  1024  iSeeStatusIcon asset =
  1025      Query.has
  1026          (iconSelector
  1027              { size = "28px"
  1028              , image = asset
  1029              }
  1030          )
  1031  
  1032  
  1033  iSeeItIsAList =
  1034      Query.has [ tag "ul" ]
  1035  
  1036  
  1037  iSeeNoMargin =
  1038      Query.has [ style "margin" "0" ]
  1039  
  1040  
  1041  iSeeLargeFont =
  1042      Query.has [ style "font-size" "16px" ]
  1043  
  1044  
  1045  iSeeTallLines =
  1046      Query.has [ style "line-height" "26px" ]
  1047  
  1048  
  1049  iSeeAGreyBackground =
  1050      Query.has [ style "background-color" Colors.background ]
  1051  
  1052  
  1053  iSeeItLaysOutHorizontally =
  1054      Query.children []
  1055          >> Query.each (Query.has [ style "display" "inline-block" ])
  1056  
  1057  
  1058  iAmLookingAtTheFirstTab =
  1059      iAmLookingAtTheTabList
  1060          >> Query.children []
  1061          >> Query.first
  1062  
  1063  
  1064  iSeeDefaultFontWeight =
  1065      Query.has [ style "font-weight" Views.Styles.fontWeightDefault ]
  1066  
  1067  
  1068  iSeePointerCursor =
  1069      Query.has [ style "cursor" "pointer" ]
  1070  
  1071  
  1072  iSeeLightGreyText =
  1073      Query.has [ style "color" "#f5f5f5" ]
  1074  
  1075  
  1076  itIsClickable domID =
  1077      Event.simulate Event.click
  1078          >> Event.expect (Update <| Message.Click domID)
  1079  
  1080  
  1081  iSeeALighterGreyBackground =
  1082      Query.has [ style "background-color" Colors.paginationHover ]
  1083  
  1084  
  1085  iSeeItIsSelected =
  1086      iSeeALighterGreyBackground
  1087  
  1088  
  1089  iSeeTheSuccessColor =
  1090      Query.has [ style "background-color" Colors.success ]
  1091  
  1092  
  1093  iSeeTheFailureColor =
  1094      Query.has [ style "background-color" Colors.failure ]
  1095  
  1096  
  1097  iSeeTheStartedColor =
  1098      Query.has [ style "background-color" Colors.started ]
  1099  
  1100  
  1101  iSeeTheErrorColor =
  1102      Query.has [ style "background-color" Colors.error ]
  1103  
  1104  
  1105  iSeeItIsTransparent =
  1106      Query.has [ style "opacity" "0.5" ]
  1107  
  1108  
  1109  iSeeATimestamp =
  1110      Query.has [ text "00:00:01" ]
  1111  
  1112  
  1113  iSeeThePipelineName =
  1114      Query.has [ text "pipeline-name" ]
  1115  
  1116  
  1117  iSeeTheResourceName =
  1118      Query.has [ text "resource-name" ]
  1119  
  1120  
  1121  iSeeTheLogOutput =
  1122      Query.has [ text "the log output" ]
  1123  
  1124  
  1125  iSeeTheLoadVarName =
  1126      Query.has [ text "var-name" ]
  1127  
  1128  
  1129  iSeeTheVarNames =
  1130      Query.has [ text "var1, var2" ]
  1131  
  1132  
  1133  iAmLookingAtTheSecondTab =
  1134      iAmLookingAtTheTabList >> Query.children [] >> Query.index 1
  1135  
  1136  
  1137  theFirstAttemptInitialized =
  1138      taskInitialized "attempt1Id"
  1139  
  1140  
  1141  theFirstAttemptSucceeded =
  1142      taskFinished "attempt1Id" 0
  1143  
  1144  
  1145  theSecondAttemptInitialized =
  1146      taskInitialized "attempt2Id"
  1147  
  1148  
  1149  theFirstTaskInitialized =
  1150      taskInitialized "task1Id"
  1151  
  1152  
  1153  theSecondTaskInitialized =
  1154      taskInitialized "task2Id"
  1155  
  1156  
  1157  theFirstTaskSucceeded =
  1158      taskFinished "task1Id" 0
  1159  
  1160  
  1161  theFirstTaskFailed =
  1162      taskFinished "task1Id" 1
  1163  
  1164  
  1165  theFirstTaskErrored =
  1166      taskErrored "task1Id"
  1167  
  1168  
  1169  theStepSucceeded =
  1170      taskFinished "stepId" 0
  1171  
  1172  
  1173  theFirstTaskIsInterrupted =
  1174      thereIsALog "task1Id" >> buildAborted
  1175  
  1176  
  1177  theFirstTaskIsCancelled =
  1178      buildAborted
  1179  
  1180  
  1181  buildAborted =
  1182      taskEvent <|
  1183          BuildStatus BuildStatusAborted (Time.millisToPosix 0)
  1184  
  1185  
  1186  taskEvent event =
  1187      Tuple.first
  1188          >> Application.handleDelivery
  1189              (EventsReceived <|
  1190                  Ok
  1191                      [ { data = event
  1192                        , url = "http://localhost:8080/api/v1/builds/1/events"
  1193                        }
  1194                      ]
  1195              )
  1196  
  1197  
  1198  taskInitialized stepId =
  1199      taskEvent <|
  1200          InitializeTask
  1201              { source = "stdout"
  1202              , id = stepId
  1203              }
  1204              (Time.millisToPosix 0)
  1205  
  1206  
  1207  taskFinished stepId exitCode =
  1208      taskEvent <|
  1209          FinishTask
  1210              { source = "stdout"
  1211              , id = stepId
  1212              }
  1213              exitCode
  1214              (Time.millisToPosix 0)
  1215  
  1216  
  1217  taskErrored stepId =
  1218      taskEvent <|
  1219          Error
  1220              { source = "stdout"
  1221              , id = stepId
  1222              }
  1223              "errored"
  1224              (Time.millisToPosix 0)
  1225  
  1226  
  1227  eventsUrl =
  1228      "http://localhost:8080/api/v1/builds/1/events"
  1229  
  1230  
  1231  thereIsALog stepId =
  1232      Tuple.first
  1233          >> Application.handleDelivery
  1234              (EventsReceived <|
  1235                  Ok
  1236                      [ { data =
  1237                              InitializeTask
  1238                                  { source = "stdout"
  1239                                  , id = stepId
  1240                                  }
  1241                                  (Time.millisToPosix 0)
  1242                        , url = eventsUrl
  1243                        }
  1244                      , { data =
  1245                              StartTask
  1246                                  { source = "stdout"
  1247                                  , id = stepId
  1248                                  }
  1249                                  (Time.millisToPosix 0)
  1250                        , url = eventsUrl
  1251                        }
  1252                      , { data =
  1253                              Log
  1254                                  { source = "stdout"
  1255                                  , id = stepId
  1256                                  }
  1257                                  "the log output"
  1258                                  (Just <| Time.millisToPosix 1000)
  1259                        , url = eventsUrl
  1260                        }
  1261                      ]
  1262              )
  1263  
  1264  
  1265  thereIsAnImageCheckStep stepId =
  1266      Tuple.first
  1267          >> Application.handleDelivery
  1268              (EventsReceived <|
  1269                  Ok
  1270                      [ { data =
  1271                              ImageCheck
  1272                                  { source = ""
  1273                                  , id = stepId
  1274                                  }
  1275                                  (Concourse.BuildPlan imageCheckStepId (Concourse.BuildStepCheck "image"))
  1276                        , url = "http://localhost:8080/api/v1/builds/1/events"
  1277                        }
  1278                      ]
  1279              )
  1280  
  1281  
  1282  thereIsAnImageGetStep stepId =
  1283      Tuple.first
  1284          >> Application.handleDelivery
  1285              (EventsReceived <|
  1286                  Ok
  1287                      [ { data =
  1288                              ImageGet
  1289                                  { source = ""
  1290                                  , id = stepId
  1291                                  }
  1292                                  (Concourse.BuildPlan imageGetStepId (Concourse.BuildStepGet "image" Nothing))
  1293                        , url = "http://localhost:8080/api/v1/builds/1/events"
  1294                        }
  1295                      ]
  1296              )
  1297  
  1298  
  1299  theBuildFinished =
  1300      Tuple.first
  1301          >> Application.handleDelivery
  1302              (EventsReceived <|
  1303                  Ok
  1304                      [ { data =
  1305                              BuildStatus
  1306                                  BuildStatusAborted
  1307                                  (Time.millisToPosix 0)
  1308                        , url = "http://localhost:8080/api/v1/builds/1/events"
  1309                        }
  1310                      ]
  1311              )
  1312  
  1313  
  1314  iSeeItIsOpaque =
  1315      Query.has [ style "opacity" "1" ]
  1316  
  1317  
  1318  itHasHorizontalSpacing =
  1319      Query.has [ style "padding" "0 5px" ]