diff --git a/web/elm/src/Pipeline.elm b/web/elm/src/Pipeline.elm index f4f754f7e7c..3dab00d7f79 100644 --- a/web/elm/src/Pipeline.elm +++ b/web/elm/src/Pipeline.elm @@ -1,4 +1,4 @@ -port module Pipeline exposing (Model, Msg(..), Flags, init, update, updateWithMessage, view, subscriptions, changeToPipelineAndGroups, resetPipelineFocus) +port module Pipeline exposing (Flags, Model, Msg(..), changeToPipelineAndGroups, init, resetPipelineFocus, subscriptions, update, updateWithMessage, view) import Char import Colors @@ -8,8 +8,9 @@ import Concourse.Info import Concourse.Job import Concourse.Pipeline import Concourse.Resource +import Dashboard.Styles exposing (infoCliIcon) import Html exposing (Html) -import Html.Attributes exposing (class, href, id, style, src, width, height) +import Html.Attributes exposing (class, height, href, id, src, style, width) import Html.Attributes.Aria exposing (ariaLabel) import Http import Json.Decode @@ -110,7 +111,7 @@ init ports flags = , hideLegendCounter = 0 } in - loadPipeline pipelineLocator model + loadPipeline pipelineLocator model changeToPipelineAndGroups : Flags -> Model -> ( Model, Cmd Msg ) @@ -121,10 +122,11 @@ changeToPipelineAndGroups flags model = , pipelineName = flags.pipelineName } in - if model.pipelineLocator == pid then - renderIfNeeded { model | selectedGroups = queryGroupsForRoute flags.route } - else - init model.ports flags + if model.pipelineLocator == pid then + renderIfNeeded { model | selectedGroups = queryGroupsForRoute flags.route } + + else + init model.ports flags loadPipeline : Concourse.PipelineIdentifier -> Model -> ( Model, Cmd Msg ) @@ -146,12 +148,12 @@ updateWithMessage message model = ( mdl, msg ) = update message model in - case mdl.pipeline of - RemoteData.Failure _ -> - ( mdl, msg, Just UpdateMsg.NotFound ) + case mdl.pipeline of + RemoteData.Failure _ -> + ( mdl, msg, Just UpdateMsg.NotFound ) - _ -> - ( mdl, msg, Nothing ) + _ -> + ( mdl, msg, Nothing ) timeUntilHidden : Time @@ -175,6 +177,7 @@ update msg model = ( { model | hideLegend = True } , Cmd.none ) + else ( { model | hideLegendCounter = model.hideLegendCounter + timeUntilHiddenCheckInterval } , Cmd.none @@ -190,6 +193,7 @@ update msg model = ( model , resetPipelineFocus () ) + else ( model , Cmd.none @@ -220,8 +224,10 @@ update msg model = Http.BadStatus { status } -> if status.code == 401 then ( model, LoginRedirect.requestLoginRedirect "" ) + else if status.code == 404 then ( { model | pipeline = RemoteData.Failure err }, Cmd.none ) + else ( model, Cmd.none ) @@ -236,6 +242,7 @@ update msg model = Http.BadStatus { status } -> if status.code == 401 then ( model, LoginRedirect.requestLoginRedirect "" ) + else ( model, Cmd.none ) @@ -250,6 +257,7 @@ update msg model = Http.BadStatus { status } -> if status.code == 401 then ( model, LoginRedirect.requestLoginRedirect "" ) + else ( model, Cmd.none ) @@ -260,7 +268,7 @@ update msg model = ( { model | concourseVersion = version, experiencingTurbulence = False }, Cmd.none ) VersionFetched (Err err) -> - flip always (Debug.log ("failed to fetch version") (err)) <| + flip always (Debug.log "failed to fetch version" err) <| ( { model | experiencingTurbulence = True }, Cmd.none ) ToggleGroup group -> @@ -275,7 +283,7 @@ subscriptions model = Sub.batch [ autoupdateVersionTimer , Time.every (5 * Time.second) AutoupdateTimerTicked - , Time.every (timeUntilHiddenCheckInterval) HideLegendTimerTicked + , Time.every timeUntilHiddenCheckInterval HideLegendTimerTicked , Mouse.moves (\_ -> ShowLegend) , Keyboard.presses (\_ -> ShowLegend) , Mouse.clicks (\_ -> ShowLegend) @@ -299,15 +307,16 @@ view model = _ -> [] in - Html.ul - [ class - (if List.isEmpty groupList then - "hidden" - else - "groups" - ) - ] - groupList + Html.ul + [ class + (if List.isEmpty groupList then + "hidden" + + else + "groups" + ) + ] + groupList ] , Html.div [ class "pipeline-content" ] [ Svg.svg @@ -317,6 +326,7 @@ view model = , Html.div [ if model.experiencingTurbulence then class "error-message" + else class "error-message hidden" ] @@ -329,6 +339,7 @@ view model = , Html.dl [ if model.hideLegend then class "legend hidden" + else class "legend" ] @@ -360,18 +371,39 @@ view model = [ Html.ul [ class "cli-downloads" ] [ Html.li [] [ Html.a - [ href (Concourse.Cli.downloadUrl "amd64" "darwin"), ariaLabel "Download OS X CLI" ] - [ Html.i [ class "fa fa-apple" ] [] ] + [ href <| + Concourse.Cli.downloadUrl + "amd64" + "darwin" + , ariaLabel "Download OS X CLI" + , Html.Attributes.style <| + cliIcon "apple" + ] + [] ] , Html.li [] [ Html.a - [ href (Concourse.Cli.downloadUrl "amd64" "windows"), ariaLabel "Download Windows CLI" ] - [ Html.i [ class "fa fa-windows" ] [] ] + [ href <| + Concourse.Cli.downloadUrl + "amd64" + "windows" + , ariaLabel "Download Windows CLI" + , Html.Attributes.style <| + cliIcon "windows" + ] + [] ] , Html.li [] [ Html.a - [ href (Concourse.Cli.downloadUrl "amd64" "linux"), ariaLabel "Download Linux CLI" ] - [ Html.i [ class "fa fa-linux" ] [] ] + [ href <| + Concourse.Cli.downloadUrl + "amd64" + "linux" + , ariaLabel "Download Linux CLI" + , Html.Attributes.style <| + cliIcon "linux" + ] + [] ] ] ] @@ -395,6 +427,7 @@ viewGroup selectedGroups url grp = Html.li [ if List.member grp.name selectedGroups then class "main active" + else class "main" ] @@ -417,13 +450,13 @@ jobAppearsInGroups groupNames pi jobJson = concourseJob = Json.Decode.decodeValue (Concourse.decodeJob pi) jobJson in - case concourseJob of - Ok cj -> - anyIntersect cj.groups groupNames + case concourseJob of + Ok cj -> + anyIntersect cj.groups groupNames - Err err -> - flip always (Debug.log ("failed to check if job is in group") (err)) <| - False + Err err -> + flip always (Debug.log "failed to check if job is in group" err) <| + False expandJsonList : Json.Encode.Value -> List Json.Decode.Value @@ -432,12 +465,12 @@ expandJsonList flatList = result = Json.Decode.decodeValue (Json.Decode.list Json.Decode.value) flatList in - case result of - Ok res -> - res + case result of + Ok res -> + res - Err err -> - [] + Err err -> + [] filterJobs : Model -> Json.Encode.Value -> Json.Encode.Value @@ -466,25 +499,16 @@ renderIfNeeded model = filteredFetchedJobs = if List.isEmpty (activeGroups model) then fetchedJobs + else filterJobs model fetchedJobs in - case ( model.renderedResources, model.renderedJobs ) of - ( Just renderedResources, Just renderedJobs ) -> - if - (expandJsonList renderedJobs /= expandJsonList filteredFetchedJobs) - || (expandJsonList renderedResources /= expandJsonList fetchedResources) - then - ( { model - | renderedJobs = Just filteredFetchedJobs - , renderedResources = Just fetchedResources - } - , model.ports.render ( filteredFetchedJobs, fetchedResources ) - ) - else - ( model, Cmd.none ) - - _ -> + case ( model.renderedResources, model.renderedJobs ) of + ( Just renderedResources, Just renderedJobs ) -> + if + (expandJsonList renderedJobs /= expandJsonList filteredFetchedJobs) + || (expandJsonList renderedResources /= expandJsonList fetchedResources) + then ( { model | renderedJobs = Just filteredFetchedJobs , renderedResources = Just fetchedResources @@ -492,6 +516,17 @@ renderIfNeeded model = , model.ports.render ( filteredFetchedJobs, fetchedResources ) ) + else + ( model, Cmd.none ) + + _ -> + ( { model + | renderedJobs = Just filteredFetchedJobs + , renderedResources = Just fetchedResources + } + , model.ports.render ( filteredFetchedJobs, fetchedResources ) + ) + _ -> ( model, Cmd.none ) @@ -509,7 +544,7 @@ fetchJobs pid = fetchVersion : Cmd Msg fetchVersion = Concourse.Info.fetch - |> Task.map (.version) + |> Task.map .version |> Task.attempt VersionFetched @@ -528,6 +563,7 @@ anyIntersect list1 list2 = first :: rest -> if List.member first list2 then True + else anyIntersect rest list2 @@ -536,8 +572,10 @@ toggleGroup : Concourse.PipelineGroup -> List String -> WebData Concourse.Pipeli toggleGroup grp names mpipeline = if List.member grp.name names then List.filter ((/=) grp.name) names + else if List.isEmpty names then grp.name :: getDefaultSelectedGroups mpipeline + else grp.name :: names @@ -546,6 +584,7 @@ getSelectedGroupsForRoute : Model -> List String getSelectedGroupsForRoute model = if List.isEmpty model.selectedGroups then getDefaultSelectedGroups model.pipeline + else model.selectedGroups @@ -572,7 +611,7 @@ setGroups newGroups model = pidToUrl (pipelineIdentifierFromModel model) <| setGroupsInLocation model.route newGroups in - ( model, Navigation.newUrl newUrl ) + ( model, Navigation.newUrl newUrl ) setGroupsInLocation : Routes.ConcourseRoute -> List String -> Routes.ConcourseRoute @@ -581,15 +620,16 @@ setGroupsInLocation loc groups = updatedUrl = if List.isEmpty groups then QueryString.remove "groups" loc.queries + else List.foldr (QueryString.add "groups") QueryString.empty groups in - { loc - | queries = updatedUrl - } + { loc + | queries = updatedUrl + } pidToUrl : Maybe Concourse.PipelineIdentifier -> Routes.ConcourseRoute -> String @@ -618,3 +658,15 @@ pipelineIdentifierFromModel model = _ -> Nothing + + +cliIcon : String -> List ( String, String ) +cliIcon image = + [ ( "width", "12px" ) + , ( "height", "12px" ) + , ( "background-image", "url(/public/images/" ++ image ++ "_logo.svg)" ) + , ( "background-repeat", "no-repeat" ) + , ( "background-position", "50% 50%" ) + , ( "background-size", "contain" ) + , ( "display", "inline-block" ) + ] diff --git a/web/elm/tests/PipelineTests.elm b/web/elm/tests/PipelineTests.elm index 451d81be8e8..c2540e2638c 100644 --- a/web/elm/tests/PipelineTests.elm +++ b/web/elm/tests/PipelineTests.elm @@ -1,11 +1,12 @@ -module PipelineTests exposing (..) +module PipelineTests exposing (all, givenMultiplePinnedResources, givenPinnedResource, init, it, jobBreadcrumbSelector, pinBadgeSelector, pipelineBreadcrumbSelector, resourceBreadcrumbSelector, rspecStyleDescribe) import Char +import DashboardTests exposing (iconSelector) import Expect exposing (..) import Html.Attributes as Attr import Json.Encode import Layout -import Pipeline exposing (update, Msg(..)) +import Pipeline exposing (Msg(..), update) import QueryString import Routes import SubPage @@ -35,12 +36,12 @@ all = [ describe "update" <| let resetFocus = - (\_ -> Cmd.map (\_ -> Noop) Cmd.none) + \_ -> Cmd.map (\_ -> Noop) Cmd.none defaultModel : Pipeline.Model defaultModel = Pipeline.init - { render = (\( _, _ ) -> Cmd.none), title = (\_ -> Cmd.none) } + { render = \( _, _ ) -> Cmd.none, title = \_ -> Cmd.none } { teamName = "some-team" , pipelineName = "some-pipeline" , turbulenceImgSrc = "some-turbulence-img-src" @@ -48,768 +49,810 @@ all = } |> Tuple.first in - [ test "HideLegendTimerTicked" <| - \_ -> - defaultModel - |> update (HideLegendTimerTicked 0) - |> Tuple.first - |> .hideLegendCounter - |> Expect.equal (1 * Time.second) - , test "HideLegendTimeTicked reaches timeout" <| - \_ -> - { defaultModel | hideLegendCounter = 10 * Time.second } - |> update (HideLegendTimerTicked 0) - |> Tuple.first - |> .hideLegend - |> Expect.equal True - , test "ShowLegend" <| - \_ -> - (init "/teams/team/pipelines/pipeline") - |> Layout.view - |> Query.fromHtml - |> Query.find [ class "legend" ] - |> Query.children [] - |> Expect.all - [ Query.count (Expect.equal 20) - , Query.index 1 >> Query.has [ text "succeeded" ] - , Query.index 3 >> Query.has [ text "errored" ] - , Query.index 5 >> Query.has [ text "aborted" ] - , Query.index 7 >> Query.has [ text "paused" ] - , Query.index 8 >> Query.has [ style [ ( "background-color", "#5C3BD1" ) ] ] - , Query.index 9 >> Query.has [ text "pinned" ] - , Query.index 11 >> Query.has [ text "failed" ] - , Query.index 13 >> Query.has [ text "pending" ] - , Query.index 15 >> Query.has [ text "started" ] - , Query.index 17 >> Query.has [ text "dependency" ] - , Query.index 19 >> Query.has [ text "dependency (trigger)" ] - ] - , test "Legend has definition for pinned resource color" <| - \_ -> - { defaultModel | hideLegend = True, hideLegendCounter = 3 * Time.second } - |> update (ShowLegend) - |> Tuple.first - |> Expect.all - [ (\m -> m.hideLegend |> Expect.equal False) - , (\m -> m.hideLegendCounter |> Expect.equal 0) - ] - , test "KeyPressed" <| - \_ -> - defaultModel - |> update (KeyPressed (Char.toCode 'a')) - |> Expect.equal ( defaultModel, Cmd.none ) - , test "KeyPressed f" <| - \_ -> - defaultModel - |> update (KeyPressed (Char.toCode 'f')) - |> Expect.notEqual ( defaultModel, Cmd.none ) - , rspecStyleDescribe "when on pipeline page" - (init "/teams/team/pipelines/pipeline") - [ it "shows a pin icon on top bar" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.has [ id "pin-icon" ] - , it "top bar is 56px tall with dark grey background" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.has [ style [ ( "background-color", "#1e1d1d" ), ( "height", "56px" ) ] ] - , it "top bar lays out contents horizontally" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.has [ style [ ( "display", "flex" ) ] ] - , it "top bar centers contents vertically" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.has [ style [ ( "align-items", "center" ) ] ] - , it "top bar maximizes spacing between the left and right navs" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.has [ style [ ( "justify-content", "space-between" ) ] ] - , it "both navs are laid out horizontally" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.children [] - >> Query.each - (Query.has [ style [ ( "display", "flex" ) ] ]) - , it "top bar has a square concourse logo on the left" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.children [] - >> Query.first - >> Query.has - [ style - [ ( "background-image", "url(/public/images/concourse_logo_white.svg)" ) - , ( "background-position", "50% 50%" ) - , ( "background-repeat", "no-repeat" ) - , ( "background-size", "42px 42px" ) - , ( "width", "54px" ) - , ( "height", "54px" ) - ] - ] - , it "concourse logo on the left is a link to homepage" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.children [] - >> Query.first - >> Query.has [ tag "a", attribute <| Attr.href "/" ] - , it "pin icon has a pin background" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.has [ style [ ( "background-image", "url(/public/images/pin_ic_grey.svg)" ) ] ] - , it "mousing over pin icon does nothing if there are no pinned resources" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.children [] - >> Query.first - >> Event.simulate Event.mouseEnter - >> Event.toResult - >> Expect.err - , it "there is some space between the pin icon and the user menu" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.has [ style [ ( "margin-right", "15px" ) ] ] - , it "pin icon has relative positioning" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.has [ style [ ( "position", "relative" ) ] ] - , it "pin icon does not have circular background" <| - Layout.view - >> Query.fromHtml - >> Query.findAll - [ id "pin-icon" - , style - [ ( "border-radius", "50%" ) - ] - ] - >> Query.count (Expect.equal 0) - , it "pin icon has white color when pipeline has pinned resources" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.has [ style [ ( "background-image", "url(/public/images/pin_ic_white.svg)" ) ] ] - , it "pin icon has pin badge when pipeline has pinned resources" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.has pinBadgeSelector - , it "pin badge is purple" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.has - [ style [ ( "background-color", "#5C3BD1" ) ] ] - , it "pin badge is circular" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.has - [ style - [ ( "border-radius", "50%" ) - , ( "width", "15px" ) - , ( "height", "15px" ) + [ test "CLI icons at bottom right" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ class "cli-downloads" ] + |> Query.children [] + |> Expect.all + [ Query.index 0 + >> Query.has + [ style + [ ( "background-image", "url(/public/images/apple_logo.svg)" ) + , ( "background-position", "50% 50%" ) + , ( "background-repeat", "no-repeat" ) + , ( "width", "12px" ) + , ( "height", "12px" ) + , ( "display", "inline-block" ) + ] ] - ] - , it "pin badge is near the top right of the pin icon" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.has - [ style - [ ( "position", "absolute" ) - , ( "top", "3px" ) - , ( "right", "3px" ) + , Query.index 1 + >> Query.has + [ style + [ ( "background-image", "url(/public/images/windows_logo.svg)" ) + , ( "background-position", "50% 50%" ) + , ( "background-repeat", "no-repeat" ) + , ( "width", "12px" ) + , ( "height", "12px" ) + , ( "display", "inline-block" ) + ] ] - ] - , it "content inside pin badge is centered horizontally and vertically" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.has - [ style - [ ( "display", "flex" ) - , ( "align-items", "center" ) - , ( "justify-content", "center" ) + , Query.index 2 + >> Query.has + [ style + [ ( "background-image", "url(/public/images/linux_logo.svg)" ) + , ( "background-position", "50% 50%" ) + , ( "background-repeat", "no-repeat" ) + , ( "width", "12px" ) + , ( "height", "12px" ) + , ( "display", "inline-block" ) + ] ] + ] + , test "HideLegendTimerTicked" <| + \_ -> + defaultModel + |> update (HideLegendTimerTicked 0) + |> Tuple.first + |> .hideLegendCounter + |> Expect.equal (1 * Time.second) + , test "HideLegendTimeTicked reaches timeout" <| + \_ -> + { defaultModel | hideLegendCounter = 10 * Time.second } + |> update (HideLegendTimerTicked 0) + |> Tuple.first + |> .hideLegend + |> Expect.equal True + , test "ShowLegend" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ class "legend" ] + |> Query.children [] + |> Expect.all + [ Query.count (Expect.equal 20) + , Query.index 1 >> Query.has [ text "succeeded" ] + , Query.index 3 >> Query.has [ text "errored" ] + , Query.index 5 >> Query.has [ text "aborted" ] + , Query.index 7 >> Query.has [ text "paused" ] + , Query.index 8 >> Query.has [ style [ ( "background-color", "#5C3BD1" ) ] ] + , Query.index 9 >> Query.has [ text "pinned" ] + , Query.index 11 >> Query.has [ text "failed" ] + , Query.index 13 >> Query.has [ text "pending" ] + , Query.index 15 >> Query.has [ text "started" ] + , Query.index 17 >> Query.has [ text "dependency" ] + , Query.index 19 >> Query.has [ text "dependency (trigger)" ] + ] + , test "Legend has definition for pinned resource color" <| + \_ -> + { defaultModel | hideLegend = True, hideLegendCounter = 3 * Time.second } + |> update ShowLegend + |> Tuple.first + |> Expect.all + [ \m -> m.hideLegend |> Expect.equal False + , \m -> m.hideLegendCounter |> Expect.equal 0 + ] + , test "KeyPressed" <| + \_ -> + defaultModel + |> update (KeyPressed (Char.toCode 'a')) + |> Expect.equal ( defaultModel, Cmd.none ) + , test "KeyPressed f" <| + \_ -> + defaultModel + |> update (KeyPressed (Char.toCode 'f')) + |> Expect.notEqual ( defaultModel, Cmd.none ) + , rspecStyleDescribe "when on pipeline page" + (init "/teams/team/pipelines/pipeline") + [ it "shows a pin icon on top bar" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.has [ id "pin-icon" ] + , it "top bar is 56px tall with dark grey background" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.has [ style [ ( "background-color", "#1e1d1d" ), ( "height", "56px" ) ] ] + , it "top bar lays out contents horizontally" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.has [ style [ ( "display", "flex" ) ] ] + , it "top bar centers contents vertically" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.has [ style [ ( "align-items", "center" ) ] ] + , it "top bar maximizes spacing between the left and right navs" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.has [ style [ ( "justify-content", "space-between" ) ] ] + , it "both navs are laid out horizontally" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.children [] + >> Query.each + (Query.has [ style [ ( "display", "flex" ) ] ]) + , it "top bar has a square concourse logo on the left" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.children [] + >> Query.first + >> Query.has + [ style + [ ( "background-image", "url(/public/images/concourse_logo_white.svg)" ) + , ( "background-position", "50% 50%" ) + , ( "background-repeat", "no-repeat" ) + , ( "background-size", "42px 42px" ) + , ( "width", "54px" ) + , ( "height", "54px" ) ] - , it "pin badge shows count of pinned resources, centered" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.findAll [ tag "div", containing [ text "1" ] ] - >> Query.count (Expect.equal 1) - , it "pin badge has no other children" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.children [] - >> Query.count (Expect.equal 1) - , it "pin counter works with multiple pinned resources" <| - givenMultiplePinnedResources - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.findAll [ tag "div", containing [ text "2" ] ] - >> Query.count (Expect.equal 1) - , it "before TogglePinIconDropdown msg no list of pinned resources is visible" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.hasNot [ tag "ul" ] - , it "mousing over pin icon sends TogglePinIconDropdown msg" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.children [] - >> Query.first - >> Event.simulate Event.mouseEnter - >> Event.expect (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - , it "TogglePinIconDropdown msg causes pin icon to have light grey circular background" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "pin-icon" ] - >> Query.has - [ style - [ ( "background-color", "#3d3c3c" ) - , ( "border-radius", "50%" ) - ] + ] + , it "concourse logo on the left is a link to homepage" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.children [] + >> Query.first + >> Query.has [ tag "a", attribute <| Attr.href "/" ] + , it "pin icon has a pin background" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.has [ style [ ( "background-image", "url(/public/images/pin_ic_grey.svg)" ) ] ] + , it "mousing over pin icon does nothing if there are no pinned resources" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.children [] + >> Query.first + >> Event.simulate Event.mouseEnter + >> Event.toResult + >> Expect.err + , it "there is some space between the pin icon and the user menu" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.has [ style [ ( "margin-right", "15px" ) ] ] + , it "pin icon has relative positioning" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.has [ style [ ( "position", "relative" ) ] ] + , it "pin icon does not have circular background" <| + Layout.view + >> Query.fromHtml + >> Query.findAll + [ id "pin-icon" + , style + [ ( "border-radius", "50%" ) ] - , it "TogglePinIconDropdown msg causes dropdown list of pinned resources to appear" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "pin-icon" ] - >> Query.children [ tag "ul" ] - >> Query.count (Expect.equal 1) - , it "on TogglePinIconDropdown, pin badge has no other children" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find pinBadgeSelector - >> Query.children [] - >> Query.count (Expect.equal 1) - , it "dropdown list of pinned resources contains resource name" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has [ tag "li", containing [ text "resource" ] ] - , it "dropdown list of pinned resources shows resource names in bold" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.find [ tag "li", containing [ text "resource" ] ] - >> Query.findAll [ tag "div", containing [ text "resource" ], style [ ( "font-weight", "700" ) ] ] - >> Query.count (Expect.equal 1) - , it "dropdown list of pinned resources shows pinned version of each resource" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.find [ tag "li", containing [ text "resource" ] ] - >> Query.has [ tag "table", containing [ text "v1" ] ] - , it "dropdown list of pinned resources has white background" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has [ style [ ( "background-color", "#fff" ) ] ] - , it "dropdown list of pinned resources is drawn over other elements on the page" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has [ style [ ( "z-index", "1" ) ] ] - , it "dropdown list of pinned resources has dark grey text" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has [ style [ ( "color", "#1e1d1d" ) ] ] - , it "dropdown list has upward-pointing arrow" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.children - [ style - [ ( "border-width", "5px" ) - , ( "border-style", "solid" ) - , ( "border-color", "transparent transparent #fff transparent" ) - ] + ] + >> Query.count (Expect.equal 0) + , it "pin icon has white color when pipeline has pinned resources" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.has [ style [ ( "background-image", "url(/public/images/pin_ic_white.svg)" ) ] ] + , it "pin icon has pin badge when pipeline has pinned resources" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.has pinBadgeSelector + , it "pin badge is purple" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.has + [ style [ ( "background-color", "#5C3BD1" ) ] ] + , it "pin badge is circular" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.has + [ style + [ ( "border-radius", "50%" ) + , ( "width", "15px" ) + , ( "height", "15px" ) ] - >> Query.count (Expect.equal 1) - , it "dropdown list of pinned resources is offset below and left of the pin icon" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has - [ style - [ ( "position", "absolute" ) - , ( "top", "100%" ) - , ( "right", "0" ) - , ( "margin-top", "0" ) - ] + ] + , it "pin badge is near the top right of the pin icon" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.has + [ style + [ ( "position", "absolute" ) + , ( "top", "3px" ) + , ( "right", "3px" ) ] - , it "dropdown list of pinned resources stretches horizontally to fit content" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has - [ style - [ ( "white-space", "nowrap" ) ] + ] + , it "content inside pin badge is centered horizontally and vertically" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.has + [ style + [ ( "display", "flex" ) + , ( "align-items", "center" ) + , ( "justify-content", "center" ) ] - , it "dropdown list of pinned resources has no bullet points" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has - [ style - [ ( "list-style-type", "none" ) ] + ] + , it "pin badge shows count of pinned resources, centered" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.findAll [ tag "div", containing [ text "1" ] ] + >> Query.count (Expect.equal 1) + , it "pin badge has no other children" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.children [] + >> Query.count (Expect.equal 1) + , it "pin counter works with multiple pinned resources" <| + givenMultiplePinnedResources + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.findAll [ tag "div", containing [ text "2" ] ] + >> Query.count (Expect.equal 1) + , it "before TogglePinIconDropdown msg no list of pinned resources is visible" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.hasNot [ tag "ul" ] + , it "mousing over pin icon sends TogglePinIconDropdown msg" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.children [] + >> Query.first + >> Event.simulate Event.mouseEnter + >> Event.expect (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + , it "TogglePinIconDropdown msg causes pin icon to have light grey circular background" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "pin-icon" ] + >> Query.has + [ style + [ ( "background-color", "#3d3c3c" ) + , ( "border-radius", "50%" ) ] - , it "dropdown list has comfortable padding" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Query.has - [ style - [ ( "padding", "10px" ) ] + ] + , it "TogglePinIconDropdown msg causes dropdown list of pinned resources to appear" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "pin-icon" ] + >> Query.children [ tag "ul" ] + >> Query.count (Expect.equal 1) + , it "on TogglePinIconDropdown, pin badge has no other children" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find pinBadgeSelector + >> Query.children [] + >> Query.count (Expect.equal 1) + , it "dropdown list of pinned resources contains resource name" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has [ tag "li", containing [ text "resource" ] ] + , it "dropdown list of pinned resources shows resource names in bold" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.find [ tag "li", containing [ text "resource" ] ] + >> Query.findAll [ tag "div", containing [ text "resource" ], style [ ( "font-weight", "700" ) ] ] + >> Query.count (Expect.equal 1) + , it "dropdown list of pinned resources shows pinned version of each resource" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.find [ tag "li", containing [ text "resource" ] ] + >> Query.has [ tag "table", containing [ text "v1" ] ] + , it "dropdown list of pinned resources has white background" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has [ style [ ( "background-color", "#fff" ) ] ] + , it "dropdown list of pinned resources is drawn over other elements on the page" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has [ style [ ( "z-index", "1" ) ] ] + , it "dropdown list of pinned resources has dark grey text" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has [ style [ ( "color", "#1e1d1d" ) ] ] + , it "dropdown list has upward-pointing arrow" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.children + [ style + [ ( "border-width", "5px" ) + , ( "border-style", "solid" ) + , ( "border-color", "transparent transparent #fff transparent" ) ] - , it "dropdown list arrow is centered below the pin icon above the list" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.children - [ style - [ ( "border-width", "5px" ) - , ( "border-style", "solid" ) - , ( "border-color", "transparent transparent #fff transparent" ) - ] + ] + >> Query.count (Expect.equal 1) + , it "dropdown list of pinned resources is offset below and left of the pin icon" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has + [ style + [ ( "position", "absolute" ) + , ( "top", "100%" ) + , ( "right", "0" ) + , ( "margin-top", "0" ) ] - >> Query.first - >> Query.has - [ style - [ ( "top", "100%" ) - , ( "right", "50%" ) - , ( "margin-right", "-5px" ) - , ( "margin-top", "-10px" ) - , ( "position", "absolute" ) - ] + ] + , it "dropdown list of pinned resources stretches horizontally to fit content" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has + [ style + [ ( "white-space", "nowrap" ) ] + ] + , it "dropdown list of pinned resources has no bullet points" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has + [ style + [ ( "list-style-type", "none" ) ] + ] + , it "dropdown list has comfortable padding" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Query.has + [ style + [ ( "padding", "10px" ) ] + ] + , it "dropdown list arrow is centered below the pin icon above the list" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.children + [ style + [ ( "border-width", "5px" ) + , ( "border-style", "solid" ) + , ( "border-color", "transparent transparent #fff transparent" ) ] - , it "mousing off the pin icon sends TogglePinIconDropdown msg" <| - givenPinnedResource - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.children [] - >> Query.first - >> Event.simulate Event.mouseLeave - >> Event.expect (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - , it "clicking a pinned resource sends a Navigation Msg" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "li" ] - >> Event.simulate Event.click - >> Event.expect (Layout.TopMsg 1 (TopBar.GoToPinnedResource "resource")) - , it "TogglePinIconDropdown msg causes dropdown list of pinned resources to disappear" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.find [ id "pin-icon" ] - >> Query.hasNot [ tag "ul" ] - , it "pinned resources in the dropdown should have a pointer cursor" <| - givenPinnedResource - >> Layout.update - (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) - >> Tuple.first - >> Layout.view - >> Query.fromHtml - >> Query.find [ id "pin-icon" ] - >> Query.find [ tag "ul" ] - >> Expect.all - [ Query.findAll [ tag "li" ] - >> Query.each (Query.has [ style [ ( "cursor", "pointer" ) ] ]) - , Query.findAll [ style [ ( "cursor", "pointer" ) ] ] - >> Query.each (Query.has [ tag "li" ]) + ] + >> Query.first + >> Query.has + [ style + [ ( "top", "100%" ) + , ( "right", "50%" ) + , ( "margin-right", "-5px" ) + , ( "margin-top", "-10px" ) + , ( "position", "absolute" ) ] - ] - , test "top bar lays out contents horizontally" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.has [ style [ ( "display", "inline-block" ) ] ] - , test "top bar centers contents vertically" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.has [ style [ ( "align-items", "center" ) ] ] - , test "top bar maximizes spacing between the left and right navs" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.has [ style [ ( "justify-content", "space-between" ), ( "left", "0" ), ( "right", "0" ) ] ] - , test "top bar is sticky" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.has [ style [ ( "z-index", "100" ), ( "position", "fixed" ) ] ] - , test "breadcrumb items are laid out horizontally" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.each - (Query.has [ style [ ( "display", "inline-block" ) ] ]) - , rspecStyleDescribe "when on job page" - (init "/teams/team/pipeline/pipeline/jobs/job/builds/1") - [ it "shows no pin icon on top bar when viewing build page" <| - Layout.view - >> Query.fromHtml - >> Query.find [ id "top-bar-app" ] - >> Query.hasNot [ id "pin-icon" ] - ] - , test "top nav bar is blue when pipeline is paused" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.update - (Layout.TopMsg 1 - (TopBar.PipelineFetched - (Ok - { id = 0 - , name = "pipeline" - , paused = True - , public = True - , teamName = "team" - , groups = [] - } - ) + ] + , it "mousing off the pin icon sends TogglePinIconDropdown msg" <| + givenPinnedResource + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.children [] + >> Query.first + >> Event.simulate Event.mouseLeave + >> Event.expect (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + , it "clicking a pinned resource sends a Navigation Msg" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "li" ] + >> Event.simulate Event.click + >> Event.expect (Layout.TopMsg 1 (TopBar.GoToPinnedResource "resource")) + , it "TogglePinIconDropdown msg causes dropdown list of pinned resources to disappear" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.find [ id "pin-icon" ] + >> Query.hasNot [ tag "ul" ] + , it "pinned resources in the dropdown should have a pointer cursor" <| + givenPinnedResource + >> Layout.update + (Layout.TopMsg 1 TopBar.TogglePinIconDropdown) + >> Tuple.first + >> Layout.view + >> Query.fromHtml + >> Query.find [ id "pin-icon" ] + >> Query.find [ tag "ul" ] + >> Expect.all + [ Query.findAll [ tag "li" ] + >> Query.each (Query.has [ style [ ( "cursor", "pointer" ) ] ]) + , Query.findAll [ style [ ( "cursor", "pointer" ) ] ] + >> Query.each (Query.has [ tag "li" ]) + ] + ] + , test "top bar lays out contents horizontally" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.has [ style [ ( "display", "inline-block" ) ] ] + , test "top bar centers contents vertically" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.has [ style [ ( "align-items", "center" ) ] ] + , test "top bar maximizes spacing between the left and right navs" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.has [ style [ ( "justify-content", "space-between" ), ( "left", "0" ), ( "right", "0" ) ] ] + , test "top bar is sticky" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.has [ style [ ( "z-index", "100" ), ( "position", "fixed" ) ] ] + , test "breadcrumb items are laid out horizontally" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.each + (Query.has [ style [ ( "display", "inline-block" ) ] ]) + , rspecStyleDescribe "when on job page" + (init "/teams/team/pipeline/pipeline/jobs/job/builds/1") + [ it "shows no pin icon on top bar when viewing build page" <| + Layout.view + >> Query.fromHtml + >> Query.find [ id "top-bar-app" ] + >> Query.hasNot [ id "pin-icon" ] + ] + , test "top nav bar is blue when pipeline is paused" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.update + (Layout.TopMsg 1 + (TopBar.PipelineFetched + (Ok + { id = 0 + , name = "pipeline" + , paused = True + , public = True + , teamName = "team" + , groups = [] + } ) ) - |> Tuple.first - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.has - [ style - [ ( "background-color", "#3498db" ) ] - ] - , test "breadcrumb list is laid out horizontally" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "ul" ] - |> Query.first - |> Query.has [ style [ ( "display", "inline-block" ), ( "padding", "0 10px" ) ] ] - , test "pipeline breadcrumb is laid out horizontally" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.find [ attribute <| Attr.href "/teams/team/pipelines/pipeline" ] - |> Query.has [ style [ ( "display", "inline-block" ) ] ] - , test "top bar has pipeline breadcrumb with icon rendered first" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.find [ attribute <| Attr.href "/teams/team/pipelines/pipeline" ] - |> Query.children [] - |> Query.first - |> Query.has pipelineBreadcrumbSelector - , test "top bar has pipeline name after pipeline icon" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.find [ attribute <| Attr.href "/teams/team/pipelines/pipeline" ] - |> Query.children [] - |> Query.index 1 - |> Query.has - [ text "pipeline" ] - , test "pipeline breadcrumb should have a link to the pipeline page" <| - \_ -> - init "/teams/team/pipelines/pipeline" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.first - |> Query.has [ tag "a", attribute <| Attr.href "/teams/team/pipelines/pipeline" ] - , test "pipeline breadcrumb should have a link to the pipeline page when viewing build details" <| - \_ -> - init "/teams/team/pipelines/pipeline/jobs/build/builds/1" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.children [] - |> Query.index 1 - |> Query.has [ tag "a", attribute <| Attr.href "/teams/team/pipelines/pipeline" ] - , test "pipeline breadcrumb should have a link to the pipeline page when viewing resource details" <| - \_ -> - init "/teams/team/pipelines/pipeline/resources/resource" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.children [] - |> Query.index 1 - |> Query.has [ tag "a", attribute <| Attr.href "/teams/team/pipelines/pipeline" ] - , test "there should be a / between pipeline and job in breadcrumb" <| - \_ -> - init "/teams/team/pipelines/pipeline/jobs/build/builds/1" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.children [] - |> Query.index 1 - |> Query.has [ text "/" ] - , test "job breadcrumb is laid out horizontally with appropriate spacing" <| - \_ -> - init "/teams/team/pipelines/pipeline/jobs/build/builds/1" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.index 2 - |> Query.has [ style [ ( "display", "inline-block" ), ( "padding", "0 10px" ) ] ] - , test "top bar has job breadcrumb with job icon rendered first" <| - \_ -> - init "/teams/team/pipelines/pipeline/jobs/job/builds/1" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.index 2 - |> Query.has jobBreadcrumbSelector - , test "top bar has build name after job icon" <| - \_ -> - init "/teams/team/pipelines/pipeline/jobs/job/builds/1" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.index 2 - |> Query.children [] - |> Query.index 1 - |> Query.has - [ text "job" ] - , test "there should be a / between pipeline and resource in breadcrumb" <| - \_ -> - init "/teams/team/pipelines/pipeline/resources/resource" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.children [] - |> Query.index 1 - |> Query.has [ text "/" ] - , test "resource breadcrumb is laid out horizontally with appropriate spacing" <| - \_ -> - init "/teams/team/pipelines/pipeline/resources/resource" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.index 2 - |> Query.has [ style [ ( "display", "inline-block" ), ( "padding", "0 10px" ) ] ] - , test "top bar has resource breadcrumb with resource icon rendered first" <| - \_ -> - init "/teams/team/pipelines/pipeline/resources/resource" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.index 2 - |> Query.has resourceBreadcrumbSelector - , test "top bar has resource name after resource icon" <| - \_ -> - init "/teams/team/pipelines/pipeline/resources/resource" - |> Layout.view - |> Query.fromHtml - |> Query.find [ id "top-bar-app" ] - |> Query.findAll [ tag "nav" ] - |> Query.first - |> Query.find [ tag "ul" ] - |> Query.children [] - |> Query.index 2 - |> Query.children [] - |> Query.index 1 - |> Query.has - [ text "resource" ] - ] + ) + |> Tuple.first + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.has + [ style + [ ( "background-color", "#3498db" ) ] + ] + , test "breadcrumb list is laid out horizontally" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "ul" ] + |> Query.first + |> Query.has [ style [ ( "display", "inline-block" ), ( "padding", "0 10px" ) ] ] + , test "pipeline breadcrumb is laid out horizontally" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.find [ attribute <| Attr.href "/teams/team/pipelines/pipeline" ] + |> Query.has [ style [ ( "display", "inline-block" ) ] ] + , test "top bar has pipeline breadcrumb with icon rendered first" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.find [ attribute <| Attr.href "/teams/team/pipelines/pipeline" ] + |> Query.children [] + |> Query.first + |> Query.has pipelineBreadcrumbSelector + , test "top bar has pipeline name after pipeline icon" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.find [ attribute <| Attr.href "/teams/team/pipelines/pipeline" ] + |> Query.children [] + |> Query.index 1 + |> Query.has + [ text "pipeline" ] + , test "pipeline breadcrumb should have a link to the pipeline page" <| + \_ -> + init "/teams/team/pipelines/pipeline" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.first + |> Query.has [ tag "a", attribute <| Attr.href "/teams/team/pipelines/pipeline" ] + , test "pipeline breadcrumb should have a link to the pipeline page when viewing build details" <| + \_ -> + init "/teams/team/pipelines/pipeline/jobs/build/builds/1" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.children [] + |> Query.index 1 + |> Query.has [ tag "a", attribute <| Attr.href "/teams/team/pipelines/pipeline" ] + , test "pipeline breadcrumb should have a link to the pipeline page when viewing resource details" <| + \_ -> + init "/teams/team/pipelines/pipeline/resources/resource" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.children [] + |> Query.index 1 + |> Query.has [ tag "a", attribute <| Attr.href "/teams/team/pipelines/pipeline" ] + , test "there should be a / between pipeline and job in breadcrumb" <| + \_ -> + init "/teams/team/pipelines/pipeline/jobs/build/builds/1" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.children [] + |> Query.index 1 + |> Query.has [ text "/" ] + , test "job breadcrumb is laid out horizontally with appropriate spacing" <| + \_ -> + init "/teams/team/pipelines/pipeline/jobs/build/builds/1" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.index 2 + |> Query.has [ style [ ( "display", "inline-block" ), ( "padding", "0 10px" ) ] ] + , test "top bar has job breadcrumb with job icon rendered first" <| + \_ -> + init "/teams/team/pipelines/pipeline/jobs/job/builds/1" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.index 2 + |> Query.has jobBreadcrumbSelector + , test "top bar has build name after job icon" <| + \_ -> + init "/teams/team/pipelines/pipeline/jobs/job/builds/1" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.index 2 + |> Query.children [] + |> Query.index 1 + |> Query.has + [ text "job" ] + , test "there should be a / between pipeline and resource in breadcrumb" <| + \_ -> + init "/teams/team/pipelines/pipeline/resources/resource" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.children [] + |> Query.index 1 + |> Query.has [ text "/" ] + , test "resource breadcrumb is laid out horizontally with appropriate spacing" <| + \_ -> + init "/teams/team/pipelines/pipeline/resources/resource" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.index 2 + |> Query.has [ style [ ( "display", "inline-block" ), ( "padding", "0 10px" ) ] ] + , test "top bar has resource breadcrumb with resource icon rendered first" <| + \_ -> + init "/teams/team/pipelines/pipeline/resources/resource" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.index 2 + |> Query.has resourceBreadcrumbSelector + , test "top bar has resource name after resource icon" <| + \_ -> + init "/teams/team/pipelines/pipeline/resources/resource" + |> Layout.view + |> Query.fromHtml + |> Query.find [ id "top-bar-app" ] + |> Query.findAll [ tag "nav" ] + |> Query.first + |> Query.find [ tag "ul" ] + |> Query.children [] + |> Query.index 2 + |> Query.children [] + |> Query.index 1 + |> Query.has + [ text "resource" ] + ] ]