diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 99850f362..5cade0f21 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -37,6 +37,8 @@ global_job_config: - 'if [ -f out/dependency-scan-trivy.json ]; then CHECK_TYPE=deps make check.generate-report; fi' - 'if [ -f out/security-export.json ]; then artifact push workflow out/security-export.json -d scans/$SEMAPHORE_JOB_ID.json; fi' - 'if [ -f out/security-summary.md ]; then artifact push job out/security-summary.md -d .semaphore/REPORT.md; fi' + - 'if [ -d out/screenshots ] && [ "$(ls -A out/screenshots)" ]; then artifact push workflow out/screenshots -d screenshots; fi' + after_pipeline: task: diff --git a/front/AGENTS.md b/front/AGENTS.md index 8ac5862da..24d5db7cd 100644 --- a/front/AGENTS.md +++ b/front/AGENTS.md @@ -24,9 +24,18 @@ ## Testing Guidelines - Keep unit tests close to their modules and name `describe` blocks after the function under test. - Wallaby browser specs need the Docker stack running; execute with `mix test test/browser`. +- Prefer the helpers in `Support.Browser`/`Support.Browser.Assertions` (`assert_stable/2`, `assert_flash_notice/2`, etc.) instead of calling `assert_text/2` or `assert_has/2` directly—these wrappers handle stale DOM retries and should be the default in new tests. +- When a flow depends on flashes or full-page redirects, assert against deterministic selectors (e.g., `#changes-notification p[data-test=...]`) rather than generic text nodes, and wait for the new page before chaining more actions. +- Seed every browser test with the features and permissions it needs (usually via `Support.Stubs.Feature.enable_feature/3` and `Support.Stubs.PermissionPatrol.allow_everything/2`) so the UI renders the buttons you intend to click. +- Keep destructive test fixtures scoped: create orgs/projects/users per test module using the stubs in `test/support/stubs`, and add explicit waits if a change propagates asynchronously (e.g., retention policies or self-hosted agents). - Generate coverage with `mix coveralls.html` and `npm run coverage`. - Update fixtures in `test/fixture` when workflow, API, or UI contracts change. +## Browser Testing Notes +- Use the `browser_test` macro from `FrontWeb.WallabyCase` for every Wallaby spec. It handles screenshot capture, session cleanup, and tags so failures are easier to debug. +- Chrome/Chromedriver now refuse to click invisible elements; always wait until the target button/link is visible (`assert_stable/2`, `assert_stable_text/2`) before clicking, and prefer selectors that match the final rendered node (not a parent wrapper). +- For modals, redirects, and flash messages, re-sync the page via `Support.Browser.assert_flash_notice/2` or another deterministic element to avoid stale references after navigation. + ## Commit & Pull Request Guidelines - Commits follow `type(scope): message (#issue)` (e.g., `fix(front): adjust mermaid rendering (#621)`). - Each commit should bundle code, schema, and tests for a single concern. diff --git a/front/Dockerfile b/front/Dockerfile index 7765b402d..f02f5e6b9 100644 --- a/front/Dockerfile +++ b/front/Dockerfile @@ -1,6 +1,6 @@ ARG ELIXIR_VERSION=1.14.5 ARG OTP_VERSION=25.3.2.21 -ARG ALPINE_VERSION=3.19.7 +ARG ALPINE_VERSION=3.22.2 ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-alpine-${ALPINE_VERSION}" ARG RUNNER_IMAGE="alpine:${ALPINE_VERSION}" diff --git a/front/config/test.exs b/front/config/test.exs index bb11a5d99..06b699a59 100644 --- a/front/config/test.exs +++ b/front/config/test.exs @@ -19,9 +19,9 @@ config :front, docs_domain: "docs.semaphoretest.test", start_reactor: true -config :wallaby, screenshot_dir: System.get_env("WALLABY_SCREENSHOTS") || "./out" +config :wallaby, screenshot_dir: System.get_env("WALLABY_SCREENSHOTS") || "./out/screenshots" config :wallaby, screenshot_on_failure: true -config :wallaby, driver: Wallaby.Experimental.Chrome +config :wallaby, driver: Wallaby.Chrome config :wallaby, max_wait_time: 10_000 config :joken, current_time_adapter: Support.TimeMock diff --git a/front/mix.exs b/front/mix.exs index 9474d2f4e..8d12285c9 100644 --- a/front/mix.exs +++ b/front/mix.exs @@ -51,7 +51,7 @@ defmodule Front.Mixfile do {:tentacat, github: "renderedtext/tentacat"}, {:httpoison, ">= 0.0.0"}, {:uuid, "~> 1.1"}, - {:wallaby, "~> 0.23.0", runtime: false, only: [:dev, :test]}, + {:wallaby, "~> 0.30", runtime: false, only: [:dev, :test]}, {:fun_registry, github: "renderedtext/fun-registry", only: [:dev, :test]}, {:grpc_mock, github: "renderedtext/grpc-mock", only: [:dev, :test]}, {:yaml_elixir, "~> 2.4"}, diff --git a/front/mix.lock b/front/mix.lock index 8fa920c77..f14cb18eb 100644 --- a/front/mix.lock +++ b/front/mix.lock @@ -5,7 +5,7 @@ "cacheman": {:git, "https://github.com/renderedtext/ex-cacheman.git", "0a40c2f73800755f10ba511263e156f360dd3759", []}, "cachex": {:hex, :cachex, "3.4.0", "868b2959ea4aeb328c6b60ff66c8d5123c083466ad3c33d3d8b5f142e13101fb", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "370123b1ab4fba4d2965fb18f87fd758325709787c8c5fce35b3fe80645ccbe5"}, "castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"}, - "certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"}, + "certifi": {:hex, :certifi, "2.15.0", "0e6e882fcdaaa0a5a9f2b3db55b1394dba07e8d6d9bcad08318fb604c6839712", [:rebar3], [], "hexpm", "b147ed22ce71d72eafdad94f055165c1c182f61a2ff49df28bcc71d1d5b94a60"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"}, @@ -29,7 +29,7 @@ "grpc": {:hex, :grpc, "0.5.0-beta.1", "7d43f52e138fe261f5b4981f1ada515dfc2e1bfa9dc92c7022e8f41e7e49b571", [:mix], [{:cowboy, "~> 2.7.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:gun, "~> 2.0.0", [hex: :grpc_gun, repo: "hexpm", optional: false]}, {:protobuf, "~> 0.5", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "fbbf8872935c295b7575435fe4128372c23c6ded89c2ef8058af3c6167bb3f65"}, "grpc_mock": {:git, "https://github.com/renderedtext/grpc-mock.git", "6e07ae8d1cda90af54f2f886cc47a176a65e8345", []}, "gun": {:hex, :grpc_gun, "2.0.0", "f99678a2ab975e74372a756c86ec30a8384d3ac8a8b86c7ed6243ef4e61d2729", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "03dbbca1a9c604a0267a40ea1d69986225091acb822de0b2dbea21d5815e410b"}, - "hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"}, + "hackney": {:hex, :hackney, "1.25.0", "390e9b83f31e5b325b9f43b76e1a785cbdb69b5b6cd4e079aa67835ded046867", [:rebar3], [{:certifi, "~> 2.15.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.4", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "7209bfd75fd1f42467211ff8f59ea74d6f2a9e81cbcee95a56711ee79fd6b1d4"}, "httpoison": {:hex, :httpoison, "1.3.1", "7ac607311f5f706b44e8b3fab736d0737f2f62a31910ccd9afe7227b43edb7f0", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "971cb2eb672d9df45963b8ffacb45f54e2327eccd264c0d45a9cb6458ed54cc0"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, @@ -41,7 +41,7 @@ "meck": {:hex, :meck, "0.9.2", "85ccbab053f1db86c7ca240e9fc718170ee5bda03810a6292b5306bf31bae5f5", [:rebar3], [], "hexpm", "81344f561357dc40a8344afa53767c32669153355b626ea9fcbc8da6b3045826"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"}, - "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, + "mimerl": {:hex, :mimerl, "1.4.0", "3882a5ca67fbbe7117ba8947f27643557adec38fa2307490c4c4207624cb213b", [:rebar3], [], "hexpm", "13af15f9f68c65884ecca3a3891d50a7b57d82152792f3e19d88650aa126b144"}, "mix_audit": {:hex, :mix_audit, "0.1.4", "35c424173a574436a80ad7f63cf014a7d9ce727de8cd4e7b4138d90b11aec043", [:make, :mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.4.0", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "7a43fee661bcadbad31aa04a86d33a890421c174723814b8a3a7f0e7076936a1"}, "mock": {:hex, :mock, "0.3.8", "7046a306b71db2488ef54395eeb74df0a7f335a7caca4a3d3875d1fc81c884dd", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "7fa82364c97617d79bb7d15571193fc0c4fe5afd0c932cef09426b3ee6fe2022"}, "money": {:hex, :money, "1.12.4", "9d9817aa79d1317871f6b006721c264bf1910fb28ba2af50746514f0d7e8ddbe", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "87e4bb907df1da184cb4640569d8df99ee6d88c84ce4f5da03cb2fab8d433eb9"}, @@ -49,7 +49,7 @@ "nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"}, "nimble_ownership": {:hex, :nimble_ownership, "1.0.1", "f69fae0cdd451b1614364013544e66e4f5d25f36a2056a9698b793305c5aa3a6", [:mix], [], "hexpm", "3825e461025464f519f3f3e4a1f9b68c47dc151369611629ad08b636b73bb22d"}, "parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"}, - "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, + "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.6.16", "e5bdd18c7a06da5852a25c7befb72246de4ddc289182285f8685a40b7b5f5451", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e15989ff34f670a96b95ef6d1d25bad0d9c50df5df40b671d8f4a669e050ac39"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "fe15d9fee5b82f5e64800502011ffe530650d42e1710ae9b14bc4c9be38bf303"}, "phoenix_html": {:hex, :phoenix_html, "3.0.4", "232d41884fe6a9c42d09f48397c175cd6f0d443aaa34c7424da47604201df2e1", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "ce17fd3cf815b2ed874114073e743507704b1f5288bb03c304a77458485efc8b"}, @@ -72,22 +72,24 @@ "sentry": {:hex, :sentry, "8.0.5", "5ca922b9238a50c7258b52f47364b2d545beda5e436c7a43965b34577f1ef61f", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "4972839fdbf52e886d7b3e694c8adf421f764f2fa79036b88fb4742049bd4b7c"}, "sleeplocks": {:hex, :sleeplocks, "1.1.1", "3d462a0639a6ef36cc75d6038b7393ae537ab394641beb59830a1b8271faeed3", [:rebar3], [], "hexpm", "84ee37aeff4d0d92b290fff986d6a95ac5eedf9b383fadfd1d88e9b84a1c02e1"}, "sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stream_data": {:hex, :stream_data, "0.5.0", "b27641e58941685c75b353577dc602c9d2c12292dd84babf506c2033cd97893e", [:mix], [], "hexpm", "012bd2eec069ada4db3411f9115ccafa38540a3c78c4c0349f151fc761b9e271"}, "tackle": {:git, "https://github.com/renderedtext/ex-tackle.git", "5bc3fecbed818960e082091c44dc8d679aa347d7", [tag: "v0.2.3"]}, "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, "telemetry_registry": {:hex, :telemetry_registry, "0.2.1", "fe648a691f2128e4279d993cd010994c67f282354dc061e697bf070d4b87b480", [:mix, :rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4221cefbcadd0b3e7076960339223742d973f1371bc20f3826af640257bc3690"}, "tentacat": {:git, "https://github.com/renderedtext/tentacat.git", "cace77bcaeaeb839175db8e490a2d1a5d02ed652", []}, + "tesla": {:hex, :tesla, "1.15.3", "3a2b5c37f09629b8dcf5d028fbafc9143c0099753559d7fe567eaabfbd9b8663", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.21", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:mox, "~> 1.0", [hex: :mox, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "98bb3d4558abc67b92fb7be4cd31bb57ca8d80792de26870d362974b58caeda7"}, "timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "f354efb2400dd7a80fd9eb6c8419068c4f632da4ac47f3d8822d6e33f08bc852"}, "traceman": {:git, "https://github.com/renderedtext/traceman.git", "12707bcde797bcb984571c321331c0f760652bae", []}, "typed_struct": {:hex, :typed_struct, "0.1.4", "25971ce73a8b336dedf2f80e4dafaab111af127ba4773955b66805c89e197f6a", [:mix], [], "hexpm", "c48b743b1812189431e0280941790af150ae5372f7ac51e7097c03a261a35bd6"}, "tzdata": {:hex, :tzdata, "1.0.1", "f6027a331af7d837471248e62733c6ebee86a72e57c613aa071ebb1f750fc71a", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "cf1345dfbce6acdfd4e23cbb36e96e53d1981bc89181cd0b936f4f398f4c0b78"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.1", "a48703a25c170eedadca83b11e88985af08d35f37c6f664d6dcfb106a97782fc", [:rebar3], [], "hexpm", "b3a917854ce3ae233619744ad1e0102e05673136776fb2fa76234f3e03b23642"}, "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"}, "util": {:git, "https://github.com/renderedtext/elixir-util.git", "c4a58718b9e7c704d877b75550696c352289014e", []}, "uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm", "c790593b4c3b601f5dc2378baae7efaf5b3d73c4c6456ba85759905be792f2ac"}, - "wallaby": {:hex, :wallaby, "0.23.0", "4100a43ad0d2bc60491871ae7556ac17d454ff53815ab87a8b9fea3b00e98cec", [:mix], [{:httpoison, "~> 0.12 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "4ee4f3b1860b24982a691c2c97c518e635b4b8bd5aea580c11183442ab05f70c"}, + "wallaby": {:hex, :wallaby, "0.30.11", "93b635bb3d01b11b5a80f83a5d9be59e87ccc8c8390136b7c526dd4fc7e485e3", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.2.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "407b50972e3827ce77e3b8292c36dcbd6b21b6837cc4f12ee8767e92a72610ac"}, "watchman": {:git, "https://github.com/renderedtext/ex-watchman.git", "e813e1a78799e95f2ecd80ad17b95722fd122da5", []}, + "web_driver_client": {:hex, :web_driver_client, "0.2.0", "63b76cd9eb3b0716ec5467a0f8bead73d3d9612e63f7560d21357f03ad86e31a", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.3", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "83cc6092bc3e74926d1c8455f0ce927d5d1d36707b74d9a65e38c084aab0350f"}, "wormhole": {:hex, :wormhole, "2.3.0", "5539d538b87fd70fd2b9cd95b8ce8b272c38aa4adf18690cbe8d1736c56054b6", [:mix], [], "hexpm", "5a82445fe84193adafe64eb2c144d703b93d3ddac8aa7e1b0ab0ce3968b22440"}, "yamerl": {:hex, :yamerl, "0.7.0", "e51dba652dce74c20a88294130b48051ebbbb0be7d76f22de064f0f3ccf0aaf5", [:rebar3], [], "hexpm", "cb5a4481e2e2ad36db83bd9962153e1a9208e2b2484185e33fc2caac6a50b108"}, "yaml_elixir": {:hex, :yaml_elixir, "2.4.0", "2f444abc3c994c902851fde56b6a9cb82895c291c05a0490a289035c2e62ae71", [:mix], [{:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "4e25a6d5c873e393689c6f1062c5ec90f6cd1be2527b073178ae37eae4c78bee"}, diff --git a/front/test/browser/account_test.exs b/front/test/browser/account_test.exs index a3b326dc1..8d481678a 100644 --- a/front/test/browser/account_test.exs +++ b/front/test/browser/account_test.exs @@ -19,13 +19,13 @@ defmodule Front.Browser.AccountTest do end describe "Okta welcome page" do - test "it welcomes the customer to semaphore", %{page_url: page_url, session: session} do + browser_test "it welcomes the customer to semaphore", %{page_url: page_url, session: session} do page = visit(session, page_url) assert_text(page, "Welcome") end - test "it asks the customer to connect to a git provider account", %{ + browser_test "it asks the customer to connect to a git provider account", %{ page_url: page_url, session: session } do diff --git a/front/test/browser/activity_monitor_test.exs b/front/test/browser/activity_monitor_test.exs index 3a9b66dc6..7a17d0483 100644 --- a/front/test/browser/activity_monitor_test.exs +++ b/front/test/browser/activity_monitor_test.exs @@ -17,19 +17,19 @@ defmodule Front.Browser.ActivityMonitorTest do {:ok, %{page: page}} end - test "active pipelines are displayed on the activity monitor page", %{page: page} do + browser_test "active pipelines are displayed on the activity monitor page", %{page: page} do FrontWeb.Plugs.Development.ActivityMonitor.running_pipelines() |> Enum.each(fn p -> assert_text(page, p.commit_message) end) end - test "queuing pipelines are displayed on the activity monitor page", %{page: page} do + browser_test "queuing pipelines are displayed on the activity monitor page", %{page: page} do assert_text(page, "Lobby") assert_text(page, "(1)") end - test "usage gauge for machines are presented on the activity monitor", %{page: page} do + browser_test "usage gauge for machines are presented on the activity monitor", %{page: page} do assert_text(page, "e1-standard-2") assert_text(page, "4/8") end diff --git a/front/test/browser/audit_logs_test.exs b/front/test/browser/audit_logs_test.exs index 08c66629d..1d45da0a5 100644 --- a/front/test/browser/audit_logs_test.exs +++ b/front/test/browser/audit_logs_test.exs @@ -5,7 +5,7 @@ defmodule Front.Browser.AuditLogsTest do import Wallaby.Query, only: [link: 1] - test "viewing audit logs that have project details", %{session: session} do + browser_test "viewing audit logs that have project details", %{session: session} do user = Stubs.User.create_default() org = Stubs.Organization.create_default() Support.Stubs.Feature.enable_feature(org.id, :audit_logs) @@ -83,7 +83,7 @@ defmodule Front.Browser.AuditLogsTest do }} end - test "project link is displayed", %{session: session, project: project} do + browser_test "project link is displayed", %{session: session, project: project} do page = open(session) assert_text(page, "Project:") @@ -94,7 +94,7 @@ defmodule Front.Browser.AuditLogsTest do assert Wallaby.Browser.current_path(page) == "/projects/#{project.name}" end - test "branch link is displayed", %{session: session, branch: branch} do + browser_test "branch link is displayed", %{session: session, branch: branch} do page = open(session) assert_text(page, "Branch:") @@ -105,7 +105,7 @@ defmodule Front.Browser.AuditLogsTest do assert Wallaby.Browser.current_path(page) == "/branches/#{branch.id}" end - test "workflow link is displayed", %{session: session, workflow: workflow, hook: hook} do + browser_test "workflow link is displayed", %{session: session, workflow: workflow, hook: hook} do page = open(session) assert_text(page, "Workflow:") @@ -116,7 +116,11 @@ defmodule Front.Browser.AuditLogsTest do assert Wallaby.Browser.current_path(page) == "/workflows/#{workflow.id}" end - test "pipeline link is displayed", %{session: session, workflow: workflow, pipeline: pipeline} do + browser_test "pipeline link is displayed", %{ + session: session, + workflow: workflow, + pipeline: pipeline + } do page = open(session) assert_text(page, "Pipeline:") @@ -127,13 +131,13 @@ defmodule Front.Browser.AuditLogsTest do assert Wallaby.Browser.current_path(page) == "/workflows/#{workflow.id}" end - test "event description is visible", %{session: session} do + browser_test "event description is visible", %{session: session} do page = open(session) assert_text(page, "Triggered a promotion to Production") end - test "agent name and IP address is visible", %{session: session} do + browser_test "agent name and IP address is visible", %{session: session} do page = open(session) assert_text(page, "s1-local-testing") diff --git a/front/test/browser/organization_settings/contacts_test.exs b/front/test/browser/organization_settings/contacts_test.exs index 8b8383ed0..7ceb8f09c 100644 --- a/front/test/browser/organization_settings/contacts_test.exs +++ b/front/test/browser/organization_settings/contacts_test.exs @@ -21,13 +21,16 @@ defmodule Front.Browser.OrganizationSettings.ContactsTest do end describe "form" do - test "when org does not have any contacts, it is empty", %{page: page} do + browser_test "when org does not have any contacts, it is empty", %{page: page} do page |> click(@contacts_tab) |> assert_contact_forms_are_shown() end - test "when org has only one contact set, display it's information", %{page: page, org: org} do + browser_test "when org has only one contact set, display it's information", %{ + page: page, + org: org + } do insert_contact(org.id, "CONTACT_TYPE_MAIN", "Joe") page @@ -35,7 +38,7 @@ defmodule Front.Browser.OrganizationSettings.ContactsTest do |> assert_contact_name_is_present("Joe") end - test "fill out financial contact info", %{page: page} do + browser_test "fill out financial contact info", %{page: page} do page |> click(@contacts_tab) |> submit_form() diff --git a/front/test/browser/organization_settings/ip_allow_list_test.exs b/front/test/browser/organization_settings/ip_allow_list_test.exs index c56b1143b..001cbde76 100644 --- a/front/test/browser/organization_settings/ip_allow_list_test.exs +++ b/front/test/browser/organization_settings/ip_allow_list_test.exs @@ -14,7 +14,7 @@ defmodule Front.Browser.OrganizationSettings.IpAllowListTest do {:ok, %{page: page}} end - test "IP allow list tab does not appear", %{page: page} do + browser_test "IP allow list tab does not appear", %{page: page} do page |> refute_has(Query.text("IP Allow List")) end end @@ -31,7 +31,7 @@ defmodule Front.Browser.OrganizationSettings.IpAllowListTest do {:ok, %{page: page}} end - test "IP allow list tab does not appear", %{page: page} do + browser_test "IP allow list tab does not appear", %{page: page} do page |> refute_has(Query.text("IP Allow List")) end end diff --git a/front/test/browser/organization_settings/okta_integration_test.exs b/front/test/browser/organization_settings/okta_integration_test.exs index e2c84b127..05fdedd97 100644 --- a/front/test/browser/organization_settings/okta_integration_test.exs +++ b/front/test/browser/organization_settings/okta_integration_test.exs @@ -1,12 +1,13 @@ defmodule Front.Browser.OrganizationSettings.OktaIntegrationTest do use FrontWeb.WallabyCase - alias Support.Stubs + alias Support.{Browser, Stubs} @page_header Query.css("h1", text: "Okta Integration") @setup_btn Query.css("a", text: "Set Up") @okta_tab Query.css("a", text: "Okta Integration") @okta_tab_active Query.css("a.bg-green", text: "Okta Integration") @save_btn Query.button("Save") + @edit_link Query.link("Edit") @saml_cert "---- BEGIN CERTIFICATE ---- \n .... \n ---- END CERTIFICATE ----" @@ -16,11 +17,7 @@ defmodule Front.Browser.OrganizationSettings.OktaIntegrationTest do Support.Stubs.Feature.enable_feature(org.id, :rbac__saml) Support.Stubs.Feature.enable_feature(org.id, :permission_patrol) - Support.Stubs.PermissionPatrol.add_permissions(org.id, user.id, [ - "organization.view", - "organization.okta.view", - "organization.okta.manage" - ]) + Support.Stubs.PermissionPatrol.allow_everything(org.id, user.id) page = visit(session, "/settings") @@ -28,7 +25,7 @@ defmodule Front.Browser.OrganizationSettings.OktaIntegrationTest do end describe "visiting empty state" do - test "it describes what is okta and shows a button for setting it up", %{page: page} do + browser_test "it describes what is okta and shows a button for setting it up", %{page: page} do page |> click(@okta_tab) |> assert_okta_tab_is_active() @@ -37,13 +34,13 @@ defmodule Front.Browser.OrganizationSettings.OktaIntegrationTest do end describe "setting up a new okta integration" do - test "it asks for saml issues and certificate", %{page: page} do + browser_test "it asks for saml issues and certificate", %{page: page} do page |> navigate_to_setup_form() |> assert_we_are_on_setup_form() end - test "it displays errors if issuer or certificate are not filled in", %{page: page} do + browser_test "it displays errors if issuer or certificate are not filled in", %{page: page} do page |> navigate_to_setup_form() |> submit_form() @@ -51,46 +48,48 @@ defmodule Front.Browser.OrganizationSettings.OktaIntegrationTest do |> assert_has(Query.text("Certificate can't be blank")) end - test "it redirects back to empty state if you hit cancel", %{page: page} do + browser_test "it redirects back to empty state if you hit cancel", %{page: page} do page |> navigate_to_setup_form() |> cancel_form() |> assert_we_are_on_zero_state() end - test "if the form is valid it completes the setup and shows the SCIM token", %{page: page} do + browser_test "if the form is valid it completes the setup and shows the SCIM token", %{ + page: page + } do page |> set_up() |> assert_has(Query.text("SCIM Authorization token")) |> click_view_integration() - |> assert_has(Query.css("div.bg-green", text: "Connected")) + |> Browser.assert_stable(Query.css("div.bg-green", text: "Connected")) end end describe "visiting an already set up integration" do - test "the page shows that okta is connected", %{page: page} do + browser_test "the page shows that okta is connected", %{page: page} do page |> set_up() |> visit("/settings/okta") - |> assert_has(Query.css("div.bg-green", text: "Connected")) + |> Browser.assert_stable(Query.css("div.bg-green", text: "Connected")) end end defp submit_form(page) do page - |> Support.Browser.scroll_into_view("button[type=submit]") + |> assert_has(@save_btn) |> click(@save_btn) end defp click_view_integration(page) do page - |> Support.Browser.scroll_into_view("a.btn-primary") + |> assert_has(Query.link("View Integration")) |> click(Query.link("View Integration")) end defp cancel_form(page) do page - |> Support.Browser.scroll_into_view("button[type=submit]") + |> assert_has(Query.link("Cancel")) |> click(Query.link("Cancel")) end @@ -109,9 +108,19 @@ defmodule Front.Browser.OrganizationSettings.OktaIntegrationTest do end defp navigate_to_setup_form(page) do - page - |> click(@okta_tab) - |> click(@setup_btn) + page = page |> click(@okta_tab) + + cond do + has_element?(page, @setup_btn) -> + page |> click(@setup_btn) + + has_element?(page, @edit_link) -> + page |> click(@edit_link) + + true -> + # force the helpful assertion error + assert_we_are_on_zero_state(page) + end end defp assert_okta_tab_is_active(page) do @@ -126,4 +135,8 @@ defmodule Front.Browser.OrganizationSettings.OktaIntegrationTest do |> fill_in(Query.text_field("SAML Certificate"), with: @saml_cert) |> submit_form() end + + defp has_element?(page, query) do + Browser.retry_on_stale(fn -> has?(page, query) end) + end end diff --git a/front/test/browser/organization_settings/pre_flight_checks_test.exs b/front/test/browser/organization_settings/pre_flight_checks_test.exs index f1825d2d8..a9d1af836 100644 --- a/front/test/browser/organization_settings/pre_flight_checks_test.exs +++ b/front/test/browser/organization_settings/pre_flight_checks_test.exs @@ -21,8 +21,8 @@ defmodule Front.Browser.OrganizationSettings.PreFlightChecksTest do {:ok, org_id: org_id, user_id: user_id} end - test "when user cannot view pre-flight checks then renders proper message", - %{session: session, org_id: org_id, user_id: user_id} do + browser_test "when user cannot view pre-flight checks then renders proper message", + %{session: session, org_id: org_id, user_id: user_id} do Support.Stubs.PermissionPatrol.remove_all_permissions() Support.Stubs.PermissionPatrol.add_permissions(org_id, user_id, [ @@ -35,8 +35,8 @@ defmodule Front.Browser.OrganizationSettings.PreFlightChecksTest do |> assert_has(Query.text("Sorry, you can’t access Initialization job agent configuration.")) end - test "when Linux & MAC machines are available then renders proper page without warning", - %{session: session, org_id: org_id} do + browser_test "when Linux & MAC machines are available then renders proper page without warning", + %{session: session, org_id: org_id} do Support.Stubs.Feature.enable_machine(org_id, "e1-standard-2") Support.Stubs.Feature.enable_machine(org_id, "a1-standard-4") @@ -48,8 +48,8 @@ defmodule Front.Browser.OrganizationSettings.PreFlightChecksTest do page |> refute_has(Query.text("No agent types available.")) end - test "when only Linux machines are available then renders proper page without warning", - %{session: session, org_id: org_id} do + browser_test "when only Linux machines are available then renders proper page without warning", + %{session: session, org_id: org_id} do Support.Stubs.Feature.enable_machine(org_id, "e1-standard-2") page = visit(session, "/pre_flight_checks") @@ -59,8 +59,8 @@ defmodule Front.Browser.OrganizationSettings.PreFlightChecksTest do page |> refute_has(Query.text("Mac Based Virtual Machine")) end - test "when only MAC machines are available then renders proper page without warning", - %{session: session, org_id: org_id} do + browser_test "when only MAC machines are available then renders proper page without warning", + %{session: session, org_id: org_id} do Support.Stubs.Feature.enable_machine(org_id, "a1-standard-4") page = visit(session, "/pre_flight_checks") @@ -70,8 +70,8 @@ defmodule Front.Browser.OrganizationSettings.PreFlightChecksTest do page |> assert_has(Query.text("Mac Based Virtual Machine")) end - test "when Linux & MAC machines are unavailable then renders proper page with warning", - %{session: session, org_id: _org_id} do + browser_test "when Linux & MAC machines are unavailable then renders proper page with warning", + %{session: session, org_id: _org_id} do page = visit(session, "/pre_flight_checks") page |> assert_has(Query.text("You can modify machine type and OS image")) @@ -95,12 +95,12 @@ defmodule Front.Browser.OrganizationSettings.PreFlightChecksTest do {:ok, org_id: org_id} end - test "Initialization jobs tab does appear", %{session: session} do + browser_test "Initialization jobs tab does appear", %{session: session} do page = visit(session, "/settings") page |> assert_has(Query.text("Initialization jobs")) end - test "Pre-flight checks page renders proper message", %{session: session} do + browser_test "Pre-flight checks page renders proper message", %{session: session} do page = visit(session, "/pre_flight_checks") page @@ -129,8 +129,8 @@ defmodule Front.Browser.OrganizationSettings.PreFlightChecksTest do {:ok, org_id: Stubs.Organization.default_org_id()} end - test "initialization jobs tab does appear", - %{session: session} do + browser_test "initialization jobs tab does appear", + %{session: session} do page = visit(session, "/settings") page |> assert_has(Query.text("Initialization jobs")) end diff --git a/front/test/browser/organization_settings/roles_test.exs b/front/test/browser/organization_settings/roles_test.exs index 9cd9d297f..851ae8d75 100644 --- a/front/test/browser/organization_settings/roles_test.exs +++ b/front/test/browser/organization_settings/roles_test.exs @@ -27,12 +27,14 @@ defmodule Front.Browser.OrganizationSettings.RolesTest do {:ok, ctx} end - test "access control roles tab does not appear", %{session: session} do + browser_test "access control roles tab does not appear", %{session: session} do page = visit(session, "/settings") page |> assert_has(Query.text("Roles")) end - test "access control roles page renders disabled 'New Role' button", %{session: session} do + browser_test "access control roles page renders disabled 'New Role' button", %{ + session: session + } do page = visit(session, "/roles") page |> assert_has(Query.button("New Role", count: 2)) page |> assert_has(Query.css("button[disabled]", count: 2)) @@ -45,12 +47,12 @@ defmodule Front.Browser.OrganizationSettings.RolesTest do {:ok, ctx} end - test "access control roles tab does appear", %{session: session} do + browser_test "access control roles tab does appear", %{session: session} do page = visit(session, "/settings") page |> assert_has(Query.text("Roles")) end - test "access control roles page renders proper message", %{session: session} do + browser_test "access control roles page renders proper message", %{session: session} do page = visit(session, "/roles/organization/new") prompt_text = "Sorry, your organization does not have access to manage roles." @@ -65,12 +67,12 @@ defmodule Front.Browser.OrganizationSettings.RolesTest do {:ok, ctx} end - test "access control roles tab does appear", %{session: session} do + browser_test "access control roles tab does appear", %{session: session} do page = visit(session, "/settings") page |> assert_has(Query.text("Roles")) end - test "access control roles page renders content", %{session: session} do + browser_test "access control roles page renders content", %{session: session} do page = visit(session, "/roles") page diff --git a/front/test/browser/people_test.exs b/front/test/browser/people_test.exs index 73b9add6b..8dbfd2938 100644 --- a/front/test/browser/people_test.exs +++ b/front/test/browser/people_test.exs @@ -19,16 +19,16 @@ defmodule Front.Browser.PeopleTest do describe "organization people" do setup [:setup_organization] - test "remove user", ctx do + browser_test "remove user", ctx do test_remove_user(ctx) end - test "change role", ctx do + browser_test "change role", ctx do test_change_role(ctx, "Member", "Admin") end - test "load more", ctx do - # this test works only if there is one member + browser_test "load more", ctx do + # this browser_testworks only if there is one member org = Support.Stubs.Organization.default() user = Support.Stubs.User.default() @@ -40,7 +40,7 @@ defmodule Front.Browser.PeopleTest do test_load_more(ctx) end - test "when user has multiple roles, show multiple labels", ctx do + browser_test "when user has multiple roles, show multiple labels", ctx do assign_role("Jacob Bannon", "Admin", ctx.org_id) assign_role("Jacob Bannon", "Member", ctx.org_id) {:ok, session} = Wallaby.start_session() @@ -64,7 +64,7 @@ defmodule Front.Browser.PeopleTest do describe "project people" do setup [:setup_project] - test "adding people", ctx do + browser_test "adding people", ctx do with_mocks([ { Front.Models.User, @@ -88,21 +88,21 @@ defmodule Front.Browser.PeopleTest do end end - test "remove user", ctx do + browser_test "remove user", ctx do test_remove_user(ctx) end - test "change role", ctx do + browser_test "change role", ctx do test_change_role(ctx, "Admin", "Contributor") end - test "load more", ctx do + browser_test "load more", ctx do # Adding another user to the projcet as well assign_role("Dimitri Minakakis", "Admin", ctx.stubs.org.id, ctx.stubs.project.id) test_load_more(ctx) end - test "when flag isn't enable, dont show remove button", ctx do + browser_test "when flag isn't enable, dont show remove button", ctx do Support.Stubs.Feature.disable_feature(ctx.stubs.org.id, :rbac__project_roles) Cachex.clear!(:feature_provider_cache) diff --git a/front/test/browser/project_deployments_test.exs b/front/test/browser/project_deployments_test.exs index 1abad2c98..c931ce53b 100644 --- a/front/test/browser/project_deployments_test.exs +++ b/front/test/browser/project_deployments_test.exs @@ -13,12 +13,12 @@ defmodule Front.Browser.ProjectDeploymentsTest do {:ok, context} end - test "Deployments tab does not appear", %{session: session, project: project} do + browser_test "Deployments tab does not appear", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}") page |> refute_has(Query.text("Deployments")) end - test "Deployments endpoint returns 404", %{session: session, project: project} do + browser_test "Deployments endpoint returns 404", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/deployments") page |> assert_has(Query.text("Page not found")) end @@ -36,15 +36,15 @@ defmodule Front.Browser.ProjectDeploymentsTest do {:ok, context} end - test "Deployments tab does appear", %{session: session, project: project} = ctx do + browser_test "Deployments tab does appear", %{session: session, project: project} = ctx do Support.Stubs.Feature.enable_feature(ctx.org.id, :permission_patrol) Support.Stubs.PermissionPatrol.allow_everything(ctx.org.id, ctx.user.id) page = visit(session, "/projects/#{project.name}") page |> assert_has(Query.text("Deployments")) end - test "when permissions are granted then deployments indexs renders proper page", - %{session: session, project: project} do + browser_test "when permissions are granted then deployments indexs renders proper page", + %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/deployments") message = @@ -54,8 +54,8 @@ defmodule Front.Browser.ProjectDeploymentsTest do page |> assert_has(Query.text(message)) end - test "when permissions are not granted then Deployments index renders proper message", - %{session: session, project: project} do + browser_test "when permissions are not granted then Deployments index renders proper message", + %{session: session, project: project} do org = Support.Stubs.Organization.default() user = Support.Stubs.User.default() @@ -70,8 +70,8 @@ defmodule Front.Browser.ProjectDeploymentsTest do page |> assert_has(Query.text("Sorry, you can’t access Deployment Targets.")) end - test "when permissions are not granted then Deployments new renders proper message", - %{session: session, project: project} do + browser_test "when permissions are not granted then Deployments new renders proper message", + %{session: session, project: project} do org = Support.Stubs.Organization.default() user = Support.Stubs.User.default() diff --git a/front/test/browser/project_onboarding_test.exs b/front/test/browser/project_onboarding_test.exs index a6fbd9ff1..a693a3909 100644 --- a/front/test/browser/project_onboarding_test.exs +++ b/front/test/browser/project_onboarding_test.exs @@ -11,12 +11,12 @@ defmodule Front.Browser.ProjectOnboardingTest do {:ok, %{session: session, org_id: org_id}} end - test "bitbucket tab is shown by default", %{session: session} do + browser_test "bitbucket tab is shown by default", %{session: session} do page = session |> visit("/choose_repository") assert_text(page, "Bitbucket") end - test "bitbucket tab is hiiden if bitbucket feature is disabled", %{ + browser_test "bitbucket tab is hiiden if bitbucket feature is disabled", %{ session: session, org_id: org_id } do diff --git a/front/test/browser/projects_settings/artifacts_test.exs b/front/test/browser/projects_settings/artifacts_test.exs index f0143a25e..2a3a2f64f 100644 --- a/front/test/browser/projects_settings/artifacts_test.exs +++ b/front/test/browser/projects_settings/artifacts_test.exs @@ -1,9 +1,9 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do use FrontWeb.WallabyCase - @project_policies Query.css("[data-container=project-policies]") - @workflow_policies Query.css("[data-container=workflow-policies]") - @job_policies Query.css("[data-container=job-policies]") + @project_policies Query.data("container", "project-policies") + @workflow_policies Query.data("container", "workflow-policies") + @job_policies Query.data("container", "job-policies") @add_policy_link Query.css("a", text: "+ Add retention policy") @last_input_field Query.css("[data-name=input-form]:last-child input") @@ -17,7 +17,7 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do {:ok, context} end - test "adding and removing policies", params do + browser_test "adding and removing policies", params do alias InternalApi.Artifacthub.RetentionPolicy, as: Policy alias InternalApi.Artifacthub.RetentionPolicy.RetentionPolicyRule, as: Rule @@ -48,7 +48,7 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do ] ) - assert last_saved_policy() == expected_policy + assert_policy_saved(expected_policy) params |> open() @@ -69,10 +69,10 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do ] ) - assert last_saved_policy() == expected_policy + assert_policy_saved(expected_policy) end - test "deleting all policies on a project", params do + browser_test "deleting all policies on a project", params do alias InternalApi.Artifacthub.RetentionPolicy, as: Policy alias InternalApi.Artifacthub.RetentionPolicy.RetentionPolicyRule, as: Rule @@ -96,10 +96,10 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do job_level_retention_policies: [] ) - assert last_saved_policy() == expected_policy + assert_policy_saved(expected_policy) end - test "empty rules are ignored", params do + browser_test "empty rules are ignored", params do alias InternalApi.Artifacthub.RetentionPolicy, as: Policy alias InternalApi.Artifacthub.RetentionPolicy.RetentionPolicyRule, as: Rule @@ -127,10 +127,10 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do ] ) - assert last_saved_policy() == expected_policy + assert_policy_saved(expected_policy) end - test "hitting the max limit for the number of defined policies", params do + browser_test "hitting the max limit for the number of defined policies", params do Support.Stubs.Feature.enable_feature(params.org.id, :permission_patrol) Support.Stubs.PermissionPatrol.allow_everything(params.org.id, params.user.id) @@ -157,6 +157,23 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do Support.Stubs.DB.last(:artifacts_retention_policies).api_model end + defp assert_policy_saved(expected_policy) do + assert_eventually(fn -> + assert last_saved_policy() == expected_policy + end) + end + + defp assert_eventually(fun, attempts \\ 20) + defp assert_eventually(fun, 0), do: fun.() + + defp assert_eventually(fun, attempts) do + fun.() + rescue + _error in [ExUnit.AssertionError, KeyError] -> + Process.sleep(100) + assert_eventually(fun, attempts - 1) + end + defp save(page) do page |> execute_script("window.confirm = function(){return true;}") @@ -176,16 +193,16 @@ defmodule Front.Browser.ProjectSettings.ArtifactsTest do defp remove_policy(page, section_selector, index: index) do find(page, section_selector, fn section -> - input_forms = all(section, Query.css("[data-name=input-form]")) + input_forms = all(section, Query.data("name", "input-form")) input_form = Enum.at(input_forms, index) - input_form |> click(Query.css("[data-action=remove-retention-policy]")) + input_form |> click(Query.data("action", "remove-retention-policy")) end) end defp open(params) do path = "/projects/#{params.project.name}/settings/artifacts" - params.session |> visit(path) |> Support.Browser.scroll_into_view("form") + params.session |> visit(path) end end diff --git a/front/test/browser/projects_settings/deployments_test.exs b/front/test/browser/projects_settings/deployments_test.exs index 5199e325d..0d95d194e 100644 --- a/front/test/browser/projects_settings/deployments_test.exs +++ b/front/test/browser/projects_settings/deployments_test.exs @@ -17,12 +17,12 @@ defmodule Front.Browser.ProjectSettings.DeploymentsTest do {:ok, context} end - test "deployment targets tab does not appear", %{session: session, project: project} do + browser_test "deployment targets tab does not appear", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/") page |> refute_has(Query.text("Deployments")) end - test "deployment targets page renders 404", %{session: session, project: project} do + browser_test "deployment targets page renders 404", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/deployments") page |> assert_has(Query.text("Page not found")) end @@ -44,14 +44,14 @@ defmodule Front.Browser.ProjectSettings.DeploymentsTest do {:ok, context} end - test "deployment targets tab appears", %{session: session, project: project} = ctx do + browser_test "deployment targets tab appears", %{session: session, project: project} = ctx do Support.Stubs.Feature.enable_feature(ctx.org.id, :permission_patrol) Support.Stubs.PermissionPatrol.allow_everything(ctx.org.id, ctx.user.id) page = visit(session, "/projects/#{project.name}/") page |> assert_has(Query.text("Deployments")) end - test "deployment targets page renders 404", %{session: session, project: project} do + browser_test "deployment targets page renders 404", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/deployments") page @@ -73,14 +73,18 @@ defmodule Front.Browser.ProjectSettings.DeploymentsTest do {:ok, context} end - test "deployment targets tab does appear", %{session: session, project: project} = ctx do + browser_test "deployment targets tab does appear", + %{session: session, project: project} = ctx do Support.Stubs.Feature.enable_feature(ctx.org.id, :permission_patrol) Support.Stubs.PermissionPatrol.allow_everything(ctx.org.id, ctx.user.id) page = visit(session, "/projects/#{project.name}/") page |> assert_has(Query.text("Deployments")) end - test "deployment targets page renders proper page", %{session: session, project: project} do + browser_test "deployment targets page renders proper page", %{ + session: session, + project: project + } do page = visit(session, "/projects/#{project.name}/deployments") page |> assert_has(Query.text("Deployment Targets", count: 3)) page |> assert_has(Query.text("Connect your servers and model the interaction")) diff --git a/front/test/browser/projects_settings/pre_flight_checks_test.exs b/front/test/browser/projects_settings/pre_flight_checks_test.exs index 5dd8efaa2..68044ed10 100644 --- a/front/test/browser/projects_settings/pre_flight_checks_test.exs +++ b/front/test/browser/projects_settings/pre_flight_checks_test.exs @@ -12,12 +12,15 @@ defmodule Front.Browser.ProjectSettings.PreFlightChecksTest do {:ok, context} end - test "Pre-flight checks tab does not appear", %{session: session, project: project} do + browser_test "Pre-flight checks tab does not appear", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/settings/general") page |> refute_has(Query.text("Pre-flight checks")) end - test "Pre-flight checks page renders proper message", %{session: session, project: project} do + browser_test "Pre-flight checks page renders proper message", %{ + session: session, + project: project + } do page = visit(session, "/projects/#{project.name}/settings/pre_flight_checks") message = "Sorry, your organization doesn't have Pre-flight checks enabled." page |> assert_has(Query.text(message)) @@ -37,12 +40,15 @@ defmodule Front.Browser.ProjectSettings.PreFlightChecksTest do {:ok, context} end - test "Pre-flight checks tab does appear", %{session: session, project: project} do + browser_test "Pre-flight checks tab does appear", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/settings/general") page |> assert_has(Query.text("Pre-flight checks")) end - test "Pre-flight checks page renders proper page", %{session: session, project: project} do + browser_test "Pre-flight checks page renders proper page", %{ + session: session, + project: project + } do page = visit(session, "/projects/#{project.name}/settings/pre_flight_checks") message = @@ -51,8 +57,8 @@ defmodule Front.Browser.ProjectSettings.PreFlightChecksTest do page |> assert_has(Query.text(message)) end - test "when Linux & MAC machines are available then renders proper page without warning", - %{session: session, org_id: org_id, project: project} do + browser_test "when Linux & MAC machines are available then renders proper page without warning", + %{session: session, org_id: org_id, project: project} do Support.Stubs.Feature.enable_machine(org_id, "e1-standard-2") Support.Stubs.Feature.enable_machine(org_id, "a1-standard-4") @@ -66,8 +72,8 @@ defmodule Front.Browser.ProjectSettings.PreFlightChecksTest do page |> refute_has(Query.text("No agent types available.")) end - test "when only Linux machines are available then renders proper page without warning", - %{session: session, org_id: org_id, project: project} do + browser_test "when only Linux machines are available then renders proper page without warning", + %{session: session, org_id: org_id, project: project} do Support.Stubs.Feature.enable_machine(org_id, "e1-standard-2") page = @@ -79,8 +85,8 @@ defmodule Front.Browser.ProjectSettings.PreFlightChecksTest do page |> refute_has(Query.text("Mac Based Virtual Machine")) end - test "when only MAC machines are available then renders proper page without warning", - %{session: session, org_id: org_id, project: project} do + browser_test "when only MAC machines are available then renders proper page without warning", + %{session: session, org_id: org_id, project: project} do Support.Stubs.Feature.enable_machine(org_id, "a1-standard-4") page = @@ -92,8 +98,8 @@ defmodule Front.Browser.ProjectSettings.PreFlightChecksTest do page |> assert_has(Query.text("Mac Based Virtual Machine")) end - test "when Linux & MAC machines are unavailable then renders proper page with warning", - %{session: session, org_id: _org_id, project: project} do + browser_test "when Linux & MAC machines are unavailable then renders proper page with warning", + %{session: session, org_id: _org_id, project: project} do page = visit(session, "/projects/#{project.name}/settings/pre_flight_checks") page |> assert_has(Query.text("Define commands and used secrets")) @@ -114,12 +120,15 @@ defmodule Front.Browser.ProjectSettings.PreFlightChecksTest do {:ok, context} end - test "Pre-flight checks tab does appear", %{session: session, project: project} do + browser_test "Pre-flight checks tab does appear", %{session: session, project: project} do page = visit(session, "/projects/#{project.name}/settings/general") page |> assert_has(Query.text("Pre-flight checks")) end - test "Pre-flight checks page renders proper page", %{session: session, project: project} do + browser_test "Pre-flight checks page renders proper page", %{ + session: session, + project: project + } do page = visit(session, "/projects/#{project.name}/settings/pre_flight_checks") page diff --git a/front/test/browser/projects_settings/schedulers_test.exs b/front/test/browser/projects_settings/schedulers_test.exs index e74727e63..9ea19967f 100644 --- a/front/test/browser/projects_settings/schedulers_test.exs +++ b/front/test/browser/projects_settings/schedulers_test.exs @@ -12,21 +12,21 @@ defmodule Front.Browser.ProjectSettings.SchedulersTest do {:ok, context} end - test "renders tasks' index page", - %{session: session, project: project, periodic: _periodic} do + browser_test "renders tasks' index page", + %{session: session, project: project, periodic: _periodic} do page = visit(session, "/projects/#{project.name}/schedulers") message = "Define tasks to trigger workflows according to your preference." page |> assert_has(Query.text(message)) end - test "renders tasks' new page", - %{session: session, project: project, periodic: _periodic} do + browser_test "renders tasks' new page", + %{session: session, project: project, periodic: _periodic} do page = visit(session, "/projects/#{project.name}/schedulers/new") page |> assert_has(Query.text("New Task")) end - test "renders tasks' edit page", - %{session: session, project: project, periodic: periodic} do + browser_test "renders tasks' edit page", + %{session: session, project: project, periodic: periodic} do page = visit(session, "/projects/#{project.name}/schedulers/#{periodic.id}/edit") page |> assert_has(Query.text("Edit Task")) end diff --git a/front/test/browser/projects_settings/secrets_test.exs b/front/test/browser/projects_settings/secrets_test.exs index b71a10be6..735419d31 100644 --- a/front/test/browser/projects_settings/secrets_test.exs +++ b/front/test/browser/projects_settings/secrets_test.exs @@ -16,7 +16,7 @@ defmodule Front.Browser.ProjectSettings.Secrets do {:ok, context} end - test "project level secrets just forwarding to manage org secrets", %{ + browser_test "project level secrets just forwarding to manage org secrets", %{ session: session, project: project } do @@ -43,11 +43,11 @@ defmodule Front.Browser.ProjectSettings.Secrets do {:ok, context} end - test "without project secrets => secrets renders proper page", - %{ - session: session, - project: project - } = ctx do + browser_test "without project secrets => secrets renders proper page", + %{ + session: session, + project: project + } = ctx do Support.Stubs.Feature.enable_feature(ctx.org.id, :permission_patrol) Support.Stubs.PermissionPatrol.allow_everything(ctx.org.id, ctx.user.id) page = visit(session, "/projects/#{project.name}/settings/secrets") diff --git a/front/test/browser/report_page_test.exs b/front/test/browser/report_page_test.exs index eef856411..c8f737e7f 100644 --- a/front/test/browser/report_page_test.exs +++ b/front/test/browser/report_page_test.exs @@ -25,7 +25,7 @@ defmodule Front.Browser.ReportPageTest do %{session: session, workflow: context.workflow, org: context.org, project: context.project} end - test "does not display a report tab on worklfow page", %{ + browser_test "does not display a report tab on worklfow page", %{ session: session, workflow: workflow } do @@ -34,7 +34,7 @@ defmodule Front.Browser.ReportPageTest do |> refute_has(Query.text("Report")) end - test "does not display a report tab on a job page", %{ + browser_test "does not display a report tab on a job page", %{ session: session } do job_id = @@ -46,7 +46,7 @@ defmodule Front.Browser.ReportPageTest do |> refute_has(Query.text("Report")) end - test "does not display a report tab on a project page", %{ + browser_test "does not display a report tab on a project page", %{ session: session } do project_name = @@ -73,7 +73,7 @@ defmodule Front.Browser.ReportPageTest do %{session: session, workflow: context.workflow, org: context.org, project: context.project} end - test "displays a report tab on a workflow page", %{ + browser_test "displays a report tab on a workflow page", %{ session: session, workflow: workflow } do @@ -82,7 +82,7 @@ defmodule Front.Browser.ReportPageTest do |> assert_has(Query.text("Report")) end - test "displays a report tab on a job page", %{ + browser_test "displays a report tab on a job page", %{ session: session } do job_id = @@ -94,7 +94,7 @@ defmodule Front.Browser.ReportPageTest do |> assert_has(Query.text("Report")) end - test "displays a report tab on a project page", %{ + browser_test "displays a report tab on a project page", %{ session: session } do project_name = diff --git a/front/test/browser/self_hosted_agents_test.exs b/front/test/browser/self_hosted_agents_test.exs index a554e6480..7b029a07d 100644 --- a/front/test/browser/self_hosted_agents_test.exs +++ b/front/test/browser/self_hosted_agents_test.exs @@ -1,6 +1,6 @@ defmodule Front.Browser.SelfHostedAgentsTest do use FrontWeb.WallabyCase - alias Support.Stubs + alias Support.{Browser, Stubs} setup %{session: session} do Stubs.init() @@ -17,20 +17,22 @@ defmodule Front.Browser.SelfHostedAgentsTest do {:ok, %{page: page, org: org}} end - test "adding first self-hosted agent type", %{page: page, org: org} do + browser_test "adding first self-hosted agent type", %{page: page, org: org} do page |> click_add_agent_type() |> set_agent_type_name("test-agent") |> click_register_agent_type() - |> assert_text("Follow the instructions and you should see the agent running here shortly.") + |> Browser.assert_stable_text( + "Follow the instructions and you should see the agent running here shortly." + ) simulate_booting_an_agent(org.id, "s1-test-agent", "s1-vagrant-23o8127381") :timer.sleep(3000) - page |> assert_text("s1-vagrant-23o8127381") + page |> Browser.assert_stable_text("s1-vagrant-23o8127381") end - test "listing existing agent types", %{page: page, org: org} do + browser_test "listing existing agent types", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") create_agent_type(org.id, "s1-test-2") @@ -40,14 +42,14 @@ defmodule Front.Browser.SelfHostedAgentsTest do page |> visit("/self_hosted_agents") - assert_text(page, "s1-test-1") - assert_text(page, "2 running agents") + Browser.assert_stable_text(page, "s1-test-1") + Browser.assert_stable_text(page, "2 running agents") - assert_text(page, "s1-test-2") - assert_text(page, "1 running agent") + Browser.assert_stable_text(page, "s1-test-2") + Browser.assert_stable_text(page, "1 running agent") end - test "viewing details about a self hosted agent type", %{page: page, org: org} do + browser_test "viewing details about a self hosted agent type", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") simulate_booting_an_agent(org.id, "s1-test-1", "s1-vagrant-23o8127381") @@ -57,12 +59,12 @@ defmodule Front.Browser.SelfHostedAgentsTest do |> visit("/self_hosted_agents") |> click(Query.text("s1-test-1")) - assert_text(page, "s1-vagrant-23o8127381") - assert_text(page, "s1-vagrant-hlakdjhfal") + Browser.assert_stable_text(page, "s1-vagrant-23o8127381") + Browser.assert_stable_text(page, "s1-vagrant-hlakdjhfal") end describe "deleting an agent type" do - test "deleting an agent type with no running agents", %{page: page, org: org} do + browser_test "deleting an agent type with no running agents", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") page @@ -70,15 +72,15 @@ defmodule Front.Browser.SelfHostedAgentsTest do |> click(Query.text("s1-test-1")) |> click(Query.link("Delete…")) - assert_text(page, "Delete s1-test-1") - assert_text(page, "This cannot be undone!") - - page |> click(Query.button("Delete")) + Browser.assert_stable_text(page, "Delete s1-test-1") + Browser.assert_stable_text(page, "This cannot be undone!") - assert_text(page, "Agent type s1-test-1 deleted") + page + |> click(Query.button("Delete")) + |> Browser.assert_flash_notice("Agent type s1-test-1 deleted") end - test "deleting an agent type with running agents", %{page: page, org: org} do + browser_test "deleting an agent type with running agents", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") simulate_booting_an_agent(org.id, "s1-test-1", "s1-vagrant-23o8127381") @@ -91,7 +93,7 @@ defmodule Front.Browser.SelfHostedAgentsTest do end end - test "reset token for an agent type", %{page: page, org: org} do + browser_test "reset token for an agent type", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") page @@ -99,18 +101,15 @@ defmodule Front.Browser.SelfHostedAgentsTest do |> click(Query.text("s1-test-1")) |> click(Query.link("Reset token…")) - assert_text(page, "Reset token for s1-test-1") - assert_text(page, "This cannot be undone!") + Browser.assert_stable_text(page, "Reset token for s1-test-1") + Browser.assert_stable_text(page, "This cannot be undone!") - page |> click(Query.button("Reset token")) - - assert_text( - page, - "The registration token was successfully reset for s1-test-1" - ) + page + |> click(Query.button("Reset token")) + |> Browser.assert_stable_text("The registration token was successfully reset for s1-test-1") end - test "disable an agent", %{page: page, org: org} do + browser_test "disable an agent", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") simulate_booting_an_agent(org.id, "s1-test-1", "s1-vagrant-23o8127381") @@ -120,15 +119,15 @@ defmodule Front.Browser.SelfHostedAgentsTest do |> click(Query.text("s1-test-1")) |> click_disconnect_link() - assert_text(page, "Disconnect s1-vagrant-23o8127381") - assert_text(page, "This cannot be undone!") + Browser.assert_stable_text(page, "Disconnect s1-vagrant-23o8127381") + Browser.assert_stable_text(page, "This cannot be undone!") - page |> click(Query.button("Disconnect")) - - assert_text(page, "Agent s1-vagrant-23o8127381 disconnected") + page + |> click(Query.button("Disconnect")) + |> Browser.assert_flash_notice("Agent s1-vagrant-23o8127381 disconnected") end - test "disable all agents", %{page: page, org: org} do + browser_test "disable all agents", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") simulate_booting_an_agent(org.id, "s1-test-1", "s1-vagrant-23o8127381") @@ -138,17 +137,16 @@ defmodule Front.Browser.SelfHostedAgentsTest do |> click(Query.text("s1-test-1")) |> click(Query.link("Disable all…")) - assert_text(page, "Disable agents for s1-test-1") - assert_text(page, "Proceed carefully, this cannot be undone!") + Browser.assert_stable_text(page, "Disable agents for s1-test-1") + Browser.assert_stable_text(page, "Proceed carefully, this cannot be undone!") page |> click(Query.radio_button("Disable all (some of them might be running jobs)")) |> click(Query.button("Disable agents")) - - assert_text(page, "All agents for s1-test-1 were disabled") + |> Browser.assert_flash_notice("All agents for s1-test-1 were disabled") end - test "disable all idle agents", %{page: page, org: org} do + browser_test "disable all idle agents", %{page: page, org: org} do create_agent_type(org.id, "s1-test-1") simulate_booting_an_agent(org.id, "s1-test-1", "s1-vagrant-23o8127381") @@ -158,14 +156,13 @@ defmodule Front.Browser.SelfHostedAgentsTest do |> click(Query.text("s1-test-1")) |> click(Query.link("Disable all…")) - assert_text(page, "Disable agents for s1-test-1") - assert_text(page, "Proceed carefully, this cannot be undone!") + Browser.assert_stable_text(page, "Disable agents for s1-test-1") + Browser.assert_stable_text(page, "Proceed carefully, this cannot be undone!") page |> click(Query.radio_button("Disable all idle agents")) |> click(Query.button("Disable agents")) - - assert_text(page, "All idle agents for s1-test-1 were disabled") + |> Browser.assert_flash_notice("All idle agents for s1-test-1 were disabled") end defp click_add_agent_type(page) do @@ -173,16 +170,10 @@ defmodule Front.Browser.SelfHostedAgentsTest do end defp click_register_agent_type(page) do - script = "document.querySelector('#register-self-hosted-agent').scrollIntoView()" - - page |> execute_script(script) page |> click(Query.button("Looks good. Register")) end defp click_disconnect_link(page) do - script = "document.querySelector('.disable-self-hosted-agent').scrollIntoView()" - - page |> execute_script(script) page |> click(Query.link("Disconnect")) end diff --git a/front/test/browser/workflow_editor/after_pipeline_test.exs b/front/test/browser/workflow_editor/after_pipeline_test.exs index 8c3ccc293..d30c498f7 100644 --- a/front/test/browser/workflow_editor/after_pipeline_test.exs +++ b/front/test/browser/workflow_editor/after_pipeline_test.exs @@ -16,21 +16,20 @@ defmodule Front.Browser.WorkflowEditor.AfterPipelineTest do {:ok, %{page: page}} end - test "when configure is clicked the after pipeline config panel is shown", %{page: page} do - page |> take_screenshot() - page |> click(Query.css("[data-action=configureAfterPipeline]")) + browser_test "when configure is clicked the after pipeline config panel is shown", %{page: page} do + page |> click(Query.data("action", "configureAfterPipeline")) assert_text(page, "Job #1") end describe "jobs" do setup %{page: page} do - page |> click(Query.css("[data-action=configureAfterPipeline]")) + page |> click(Query.data("action", "configureAfterPipeline")) {:ok, %{page: page}} end - test "setting up a simple job", %{page: page} do + browser_test "setting up a simple job", %{page: page} do after_pipeline = after_pipeline_yaml(page) job = after_pipeline |> get_in(["task", "jobs", Access.at(0)]) @@ -38,7 +37,7 @@ defmodule Front.Browser.WorkflowEditor.AfterPipelineTest do assert job["name"] == "Job #1" end - test "setting up job parallelism", %{page: page} do + browser_test "setting up job parallelism", %{page: page} do page |> Editor.expand_config("Configure parallelism or a job matrix") |> select_parallelism_type("Multiple instances") @@ -57,7 +56,7 @@ defmodule Front.Browser.WorkflowEditor.AfterPipelineTest do assert job["parallelism"] == 8 end - test "setting up job matrix", %{page: page} do + browser_test "setting up job matrix", %{page: page} do page = page |> Editor.expand_config("Configure parallelism or a job matrix") diff --git a/front/test/browser/workflow_editor/blocks_test.exs b/front/test/browser/workflow_editor/blocks_test.exs index dd300d18c..ce5a8395f 100644 --- a/front/test/browser/workflow_editor/blocks_test.exs +++ b/front/test/browser/workflow_editor/blocks_test.exs @@ -18,18 +18,18 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do {:ok, %{page: page}} end - test "users can add new blocks", %{page: page} do + browser_test "users can add new blocks", %{page: page} do block_count = page |> all(Query.css("#workflow-editor-diagram [data-type=block]")) |> length page - |> click(Query.css("[data-action=addBlock]")) + |> click(Query.data("action", "addBlock")) |> assert_text("Block ##{block_count + 1}") end - test "adding a secret to block", %{page: page} do + browser_test "adding a secret to block", %{page: page} do secret = Support.Stubs.Secret.last() secret_name = secret.api_model.metadata.name @@ -49,7 +49,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert secret["name"] == secret_name end - test "editing prologue commands", %{page: page} do + browser_test "editing prologue commands", %{page: page} do text = " \necho C\n " page = @@ -71,7 +71,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert commands == ["echo C"] end - test "editing epilogue always commands", %{page: page} do + browser_test "editing epilogue always commands", %{page: page} do always_text = "echo always" page = @@ -92,7 +92,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert always == ["echo always"] end - test "editing epilogue on-fail commands", %{page: page} do + browser_test "editing epilogue on-fail commands", %{page: page} do on_fail_text = " \necho fail\n " page = @@ -113,7 +113,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert on_fail == ["echo fail"] end - test "editing epilogue on-pass commands", %{page: page} do + browser_test "editing epilogue on-pass commands", %{page: page} do on_pass_text = "echo pass1\n \necho pass2" page = @@ -140,7 +140,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do {:ok, %{page: page}} end - test "setting up job parallelism", %{page: page} do + browser_test "setting up job parallelism", %{page: page} do page |> Editor.expand_config("Configure parallelism or a job matrix") |> select_parallelism_type("Multiple instances") @@ -159,7 +159,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert job["parallelism"] == 8 end - test "setting up job matrix", %{page: page} do + browser_test "setting up job matrix", %{page: page} do page = page |> Editor.expand_config("Configure parallelism or a job matrix") @@ -222,7 +222,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do {:ok, %{page: page}} end - test "enabling global override", %{page: page} do + browser_test "enabling global override", %{page: page} do # enable page = page |> click(Query.checkbox("Override global agent definition")) @@ -236,7 +236,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert get_in(yaml, ["task", "agent"]) == nil end - test "configuring Linux VM agent", %{page: page} do + browser_test "configuring Linux VM agent", %{page: page} do # enable page = page |> click(Query.checkbox("Override global agent definition")) page = page |> Editor.change_agent_env_type_for_block("Linux Based Virtual Machine") @@ -254,7 +254,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert get_in(yaml, ["task", "agent", "machine", "type"]) == "e1-standard-4" end - test "configuring Mac VM agent", %{page: page} do + browser_test "configuring Mac VM agent", %{page: page} do # enable page = page |> click(Query.checkbox("Override global agent definition")) page = page |> Editor.change_agent_env_type_for_block("Mac Based Virtual Machine") @@ -264,7 +264,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert get_in(yaml, ["task", "agent", "machine", "type"]) == "a1-standard-4" end - test "configuring Docker based VM agent", %{page: page} do + browser_test "configuring Docker based VM agent", %{page: page} do # enable page = page |> click(Query.checkbox("Override global agent definition")) @@ -318,7 +318,9 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do ] end - test "self-hosted environment is not available if no agent types are created", %{page: page} do + browser_test "self-hosted environment is not available if no agent types are created", %{ + page: page + } do page |> click(Query.checkbox("Override global agent definition")) |> Editor.in_config("Agent", fn cfg -> @@ -341,7 +343,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do {:ok, %{page: page}} end - test "setting up a skip condition", %{page: page} do + browser_test "setting up a skip condition", %{page: page} do page = page |> change_skip_condition_type("Skip this block when conditions are met") @@ -352,7 +354,7 @@ defmodule Front.Browser.WorkflowEditor.BlocksTest do assert page |> Editor.first_block_yaml() |> get_in(["skip", "when"]) == "branch = 'dev'" end - test "setting up a run condition", %{page: page} do + browser_test "setting up a run condition", %{page: page} do page = page |> change_skip_condition_type("Run this block when conditions are met") diff --git a/front/test/browser/workflow_editor/code_editor_test.exs b/front/test/browser/workflow_editor/code_editor_test.exs index 9661b4499..86591f0ca 100644 --- a/front/test/browser/workflow_editor/code_editor_test.exs +++ b/front/test/browser/workflow_editor/code_editor_test.exs @@ -33,7 +33,7 @@ defmodule Front.Browser.WorkflowEditor.CodeEditorTest do {:ok, %{page: page}} end - test "YAML validation errors in code editor", %{page: page} do + browser_test "YAML validation errors in code editor", %{page: page} do page |> Editor.change_code_in_editor("semaphore.yml", @broken_yaml) |> assert_has(css(".CodeMirror-lint-marker-error")) @@ -41,7 +41,7 @@ defmodule Front.Browser.WorkflowEditor.CodeEditorTest do |> refute_has(css(".CodeMirror-lint-marker-error")) end - test "YAML validation errors on diagram", %{page: page} do + browser_test "YAML validation errors on diagram", %{page: page} do error_message = "bad indentation of a mapping entry" error_title = "Invalid YAML syntax in .semaphore/semaphore.yml" diff --git a/front/test/browser/workflow_editor/commit_dialog_test.exs b/front/test/browser/workflow_editor/commit_dialog_test.exs index ef016f27c..02e814289 100644 --- a/front/test/browser/workflow_editor/commit_dialog_test.exs +++ b/front/test/browser/workflow_editor/commit_dialog_test.exs @@ -16,7 +16,7 @@ defmodule Front.Browser.WorkflowEditor.CommitDialogTest do {:ok, %{page: page}} end - test "dismiss and exit editor goes back to workflow page", %{page: page} do + browser_test "dismiss and exit editor goes back to workflow page", %{page: page} do page = page |> Browser.disable_onbeforeunload_dialog() @@ -28,7 +28,7 @@ defmodule Front.Browser.WorkflowEditor.CommitDialogTest do end describe "filling in the branch name and commit message and clicking submit" do - test "when the action succeds => it redirects to workflow", %{page: page} do + browser_test "when the action succeds => it redirects to workflow", %{page: page} do user = Support.Stubs.User.create_default() org = Support.Stubs.Organization.create_default() Support.Stubs.Feature.enable_feature(org.id, :permission_patrol) diff --git a/front/test/browser/workflow_editor/pipeline_test.exs b/front/test/browser/workflow_editor/pipeline_test.exs index c4df26c3a..67fb3cd7d 100644 --- a/front/test/browser/workflow_editor/pipeline_test.exs +++ b/front/test/browser/workflow_editor/pipeline_test.exs @@ -25,7 +25,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do {:ok, %{page: page}} end - test "configuring Linux VM agent", %{page: page} do + browser_test "configuring Linux VM agent", %{page: page} do page = page |> Editor.change_agent_env_type_for_pipeline("Linux Based Virtual Machine") page = @@ -37,7 +37,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(yaml, ["agent", "machine", "type"]) == "e1-standard-4" end - test "configuring Mac VM agent", %{page: page} do + browser_test "configuring Mac VM agent", %{page: page} do page = page |> Editor.change_agent_env_type_for_pipeline("Mac Based Virtual Machine") yaml = Editor.get_first_pipeline(page) @@ -45,7 +45,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(yaml, ["agent", "machine", "type"]) == "a1-standard-4" end - test "configuring Docker based VM agent", %{page: page} do + browser_test "configuring Docker based VM agent", %{page: page} do # first, make sure we are not in docker page = page |> Editor.change_agent_env_type_for_pipeline("Linux Based Virtual Machine") @@ -80,7 +80,9 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do ] end - test "self-hosted environment is not available if no agent types are created", %{page: page} do + browser_test "self-hosted environment is not available if no agent types are created", %{ + page: page + } do page |> find(Query.select("Environment Type"), fn select -> select |> refute_has(Query.option("Self-Hosted Machine")) @@ -95,7 +97,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do {:ok, %{page: page}} end - test "disable fail-fast", %{page: page} do + browser_test "disable fail-fast", %{page: page} do # setting to non-disabled page = page |> change_fail_fast_type("Stop all remaining jobs") @@ -108,14 +110,14 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(yaml, ["fail_fast"]) == nil end - test "setting strategy to stop all remaining jobs", %{page: page} do + browser_test "setting strategy to stop all remaining jobs", %{page: page} do page = page |> change_fail_fast_type("Stop all remaining jobs") yaml = Editor.get_first_pipeline(page) assert get_in(yaml, ["fail_fast"]) == %{"stop" => %{"when" => "true"}} end - test "setting strategy to cancel all pending jobs", %{page: page} do + browser_test "setting strategy to cancel all pending jobs", %{page: page} do page = page |> change_fail_fast_type("Cancel all pending jobs, wait for started ones to finish") @@ -123,7 +125,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(yaml, ["fail_fast"]) == %{"cancel" => %{"when" => "true"}} end - test "setting strategy to stop on non-master", %{page: page} do + browser_test "setting strategy to stop on non-master", %{page: page} do page = page |> change_fail_fast_type( @@ -134,7 +136,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(yaml, ["fail_fast"]) == %{"stop" => %{"when" => "branch != 'master'"}} end - test "setting strategy to a custom one", %{page: page} do + browser_test "setting strategy to a custom one", %{page: page} do page = page |> change_fail_fast_type("Run a custom fail-fast strategy") page = @@ -168,7 +170,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do @strategy_master "On the master branch cancel only queued pipelines, on others cancel both running and queued" @strategy_custom "Run a custom auto-cancel strategy" - test "disable auto-cancel", %{page: page} do + browser_test "disable auto-cancel", %{page: page} do # setting to non-disabled page = page |> change_auto_cancel_type(@strategy_cancel_all) @@ -183,21 +185,21 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(yaml, ["auto_cancel"]) == nil end - test "setting strategy to cancel all", %{page: page} do + browser_test "setting strategy to cancel all", %{page: page} do page = page |> change_auto_cancel_type(@strategy_cancel_all) yaml = Editor.get_first_pipeline(page) assert get_in(yaml, ["auto_cancel"]) == %{"running" => %{"when" => "true"}} end - test "setting strategy to cancel all queued pipelines", %{page: page} do + browser_test "setting strategy to cancel all queued pipelines", %{page: page} do page = page |> change_auto_cancel_type(@strategy_queued) yaml = Editor.get_first_pipeline(page) assert get_in(yaml, ["auto_cancel"]) == %{"queued" => %{"when" => "true"}} end - test "setting strategy to stop on non-master", %{page: page} do + browser_test "setting strategy to stop on non-master", %{page: page} do page = page |> change_auto_cancel_type(@strategy_master) yaml = Editor.get_first_pipeline(page) @@ -208,7 +210,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do } end - test "setting strategy to a custom one", %{page: page} do + browser_test "setting strategy to a custom one", %{page: page} do page = page |> change_auto_cancel_type(@strategy_custom) running_query = Query.text_field("Cancel both running and queued pipelines when:") @@ -239,7 +241,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do {:ok, %{page: page}} end - test "editing prologue commands", %{page: page} do + browser_test "editing prologue commands", %{page: page} do page = page |> Editor.select_first_pipeline() @@ -256,7 +258,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(yaml, ["global_job_config", "prologue", "commands"]) == ["echo hello"] end - test "editing epilogue always", %{page: page} do + browser_test "editing epilogue always", %{page: page} do page = page |> Editor.select_first_pipeline() @@ -273,7 +275,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(epilogue, ["always", "commands"]) == ["echo always"] end - test "editing epilogue on fail", %{page: page} do + browser_test "editing epilogue on fail", %{page: page} do page = page |> Editor.select_first_pipeline() @@ -290,7 +292,7 @@ defmodule Front.Browser.WorkflowEditor.PipelineTest do assert get_in(epilogue, ["on_fail", "commands"]) == ["echo fail"] end - test "editing epilogue on pass", %{page: page} do + browser_test "editing epilogue on pass", %{page: page} do page = page |> Editor.select_first_pipeline() diff --git a/front/test/browser/workflow_editor/promotion_parameters_test.exs b/front/test/browser/workflow_editor/promotion_parameters_test.exs index fc3362fda..bd0e4ac10 100644 --- a/front/test/browser/workflow_editor/promotion_parameters_test.exs +++ b/front/test/browser/workflow_editor/promotion_parameters_test.exs @@ -4,11 +4,11 @@ defmodule Front.Browser.WorkflowEditor.PromotionParametersTest do alias Support.Browser.WorkflowEditor, as: Editor @add_env_var_buttom Query.css("a", text: "+ Add Environment Variable") - @input_name Query.css("[data-action=changePromotionParameterEnvName]") - @input_description Query.css("[data-action=changePromotionParameterEnvDescription]") - @input_default Query.css("[data-action=changePromotionParameterEnvDefault]") - @input_options Query.css("[data-action=changePromotionParameterEnvOptions]") - @input_required Query.css("[data-action=changePromotionParameterEnvRequired]") + @input_name Query.data("action", "changePromotionParameterEnvName") + @input_description Query.data("action", "changePromotionParameterEnvDescription") + @input_default Query.data("action", "changePromotionParameterEnvDefault") + @input_options Query.data("action", "changePromotionParameterEnvOptions") + @input_required Query.data("action", "changePromotionParameterEnvRequired") setup %{session: session} do Editor.init() @@ -18,12 +18,12 @@ defmodule Front.Browser.WorkflowEditor.PromotionParametersTest do workflow = Editor.get_workflow() page = Editor.open(session, workflow.id) - page = page |> click(Query.css("[data-action=addPromotion]")) + page = page |> click(Query.data("action", "addPromotion")) {:ok, %{page: page}} end - test "adding a required promotion parameter", %{page: page} do + browser_test "adding a required promotion parameter", %{page: page} do page |> click(@add_env_var_buttom) |> Editor.fill(@input_name, "SERVER") @@ -45,7 +45,7 @@ defmodule Front.Browser.WorkflowEditor.PromotionParametersTest do assert param["required"] == true end - test "adding an optional promotion parameter", %{page: page} do + browser_test "adding an optional promotion parameter", %{page: page} do page |> click(@add_env_var_buttom) |> Editor.fill(@input_name, "SERVER") diff --git a/front/test/browser/workflow_editor/self_hosted_agents_test.exs b/front/test/browser/workflow_editor/self_hosted_agents_test.exs index 75266acbd..9b89aeaf2 100644 --- a/front/test/browser/workflow_editor/self_hosted_agents_test.exs +++ b/front/test/browser/workflow_editor/self_hosted_agents_test.exs @@ -31,7 +31,7 @@ defmodule Front.Browser.WorkflowEditor.SelfHostedAgentsTest do {:ok, %{page: page}} end - test "configure self-hosted machine", %{page: page} do + browser_test "configure self-hosted machine", %{page: page} do # enable page = page |> click(Query.checkbox("Override global agent definition")) page = page |> Editor.change_agent_env_type_for_block("Self-Hosted Machine") @@ -52,7 +52,7 @@ defmodule Front.Browser.WorkflowEditor.SelfHostedAgentsTest do {:ok, %{page: page}} end - test "configure self-hosted machine", %{page: page} do + browser_test "configure self-hosted machine", %{page: page} do page = page |> Editor.change_agent_env_type_for_pipeline("Self-Hosted Machine") page = diff --git a/front/test/browser/workflow_page/errors_test.exs b/front/test/browser/workflow_page/errors_test.exs index b8fc7cf77..1c39bc4c6 100644 --- a/front/test/browser/workflow_page/errors_test.exs +++ b/front/test/browser/workflow_page/errors_test.exs @@ -14,7 +14,7 @@ defmodule Front.Browser.WorkflowPage.ErrorTest do {:ok, context} end - test "generic structured error", context do + browser_test "generic structured error", context do err = """ { "message": "Initialization step failed, see logs for more details.", @@ -29,13 +29,12 @@ defmodule Front.Browser.WorkflowPage.ErrorTest do Support.Stubs.Pipeline.set_error(context.pipeline.id, err) page = open(context) - take_screenshot(page) assert has_text?(page, "We couldn't run your pipeline") assert has_text?(page, "Initialization failed. See logs for more details.") end - test "when language error", context do + browser_test "when language error", context do err = """ { "location":{ @@ -50,14 +49,13 @@ defmodule Front.Browser.WorkflowPage.ErrorTest do Support.Stubs.Pipeline.set_error(context.pipeline.id, err) page = open(context) - take_screenshot(page) assert has_text?(page, "We couldn't run your pipeline") assert has_text?(page, "Invalid when expression detected") assert has_text?(page, "Invalid expression on the left of") end - test "missing branch in change_in expression", context do + browser_test "missing branch in change_in expression", context do err = """ { "type": "ErrorChangeInMissingBranch", @@ -72,7 +70,6 @@ defmodule Front.Browser.WorkflowPage.ErrorTest do Support.Stubs.Pipeline.set_error(context.pipeline.id, err) page = open(context) - take_screenshot(page) assert has_text?(page, "We couldn't run your pipeline") assert has_text?(page, "Unknown branch referenced") @@ -85,7 +82,7 @@ defmodule Front.Browser.WorkflowPage.ErrorTest do assert has_text?(page, msg) end - test "pipeline YAML has tabs", context do + browser_test "pipeline YAML has tabs", context do err = """ Error: {{:throw, {:yamerl_exception, [{:yamerl_parsing_error, :error, 'Block mapping value not allowed here', 12, 9, @@ -96,13 +93,12 @@ defmodule Front.Browser.WorkflowPage.ErrorTest do Support.Stubs.Pipeline.set_error(context.pipeline.id, err) page = open(context) - take_screenshot(page) assert has_text?(page, "We couldn't run your pipeline") assert has_text?(page, "Unprocessable YAML file.") end - test "unknown error", context do + browser_test "unknown error", context do err = """ Error: {{:throw, {:, [{:, :error, 'Block mapping value not allowed here', 12, 9,}}}} @@ -111,7 +107,6 @@ defmodule Front.Browser.WorkflowPage.ErrorTest do Support.Stubs.Pipeline.set_error(context.pipeline.id, err) page = open(context) - take_screenshot(page) assert has_text?(page, "We couldn't run your pipeline") assert has_text?(page, "Error") diff --git a/front/test/browser/workflow_page/favicon_test.exs b/front/test/browser/workflow_page/favicon_test.exs index 8ad3bace9..51e895feb 100644 --- a/front/test/browser/workflow_page/favicon_test.exs +++ b/front/test/browser/workflow_page/favicon_test.exs @@ -16,7 +16,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do {:ok, context} end - test "when pipeline is running favicon is in running state", params do + browser_test "when pipeline is running favicon is in running state", params do Support.Stubs.Pipeline.change_state(params.pipeline.id, :running) page = open(params) @@ -26,7 +26,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do assert Page.current_favicon(page) == "/images/favicon-running.svg" end - test "when pipeline is running favicon is in passed state", params do + browser_test "when pipeline is running favicon is in passed state", params do Support.Stubs.Pipeline.change_state(params.pipeline.id, :passed) page = open(params) @@ -36,7 +36,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do assert Page.current_favicon(page) == "/images/favicon-passed.svg" end - test "when pipeline is running favicon is in failed state", params do + browser_test "when pipeline is running favicon is in failed state", params do Support.Stubs.Pipeline.change_state(params.pipeline.id, :failed) page = open(params) @@ -46,7 +46,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do assert Page.current_favicon(page) == "/images/favicon-failed.svg" end - test "when pipeline is running favicon is in stopping state", params do + browser_test "when pipeline is running favicon is in stopping state", params do Support.Stubs.Pipeline.change_state(params.pipeline.id, :stopping) page = open(params) @@ -56,7 +56,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do assert Page.current_favicon(page) == "/images/favicon-stopped.svg" end - test "when pipeline is running favicon is in stopped state", params do + browser_test "when pipeline is running favicon is in stopped state", params do Support.Stubs.Pipeline.change_state(params.pipeline.id, :stopped) page = open(params) @@ -66,7 +66,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do assert Page.current_favicon(page) == "/images/favicon-stopped.svg" end - test "when pipeline is running favicon is in pending state", params do + browser_test "when pipeline is running favicon is in pending state", params do Support.Stubs.Pipeline.change_state(params.pipeline.id, :pending) page = open(params) @@ -76,7 +76,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do assert Page.current_favicon(page) == "/images/favicon-queued.svg" end - test "when pipeline is running favicon is in canceled state", params do + browser_test "when pipeline is running favicon is in canceled state", params do Support.Stubs.Pipeline.change_state(params.pipeline.id, :canceled) page = open(params) @@ -86,7 +86,7 @@ defmodule Front.Browser.WorkflowPage.FaviconTest do assert Page.current_favicon(page) == "/images/favicon-not-completed.svg" end - test "pipeline state change", params do + browser_test "pipeline state change", params do page = open(params) Process.sleep(@pipeline_status_response_limit) diff --git a/front/test/browser/workflow_page/initialization_test.exs b/front/test/browser/workflow_page/initialization_test.exs index 0f75058d8..9be1ac50f 100644 --- a/front/test/browser/workflow_page/initialization_test.exs +++ b/front/test/browser/workflow_page/initialization_test.exs @@ -13,14 +13,15 @@ defmodule Front.Browser.WorkflowPage.InitializationTest do {:ok, context} end - test "no compilation step => display nothing", context do + browser_test "no compilation step => display nothing", context do page = open(context) refute has_text?(page, "Initializing") refute has_text?(page, "Initialization") end - test "compile exists, not yet started => display the message with 00:00 timer", context do + browser_test "compile exists, not yet started => display the message with 00:00 timer", + context do Support.Stubs.Pipeline.add_compile_task(context.pipeline.id) Cacheman.clear(:front) @@ -42,7 +43,7 @@ defmodule Front.Browser.WorkflowPage.InitializationTest do |> assert_has(Query.text("Cloning your reposi")) end - test "compile step exists and finished", context do + browser_test "compile step exists and finished", context do task = Support.Stubs.Pipeline.add_compile_task(context.pipeline.id) Support.Stubs.Task.change_state(task, :finished) Support.Stubs.Pipeline.change_state(context.pipeline.id, :running) @@ -60,7 +61,8 @@ defmodule Front.Browser.WorkflowPage.InitializationTest do |> refute_has(Query.text("Cloning your reposi")) end - test "transitioning from initializing -> running expands the promotions as well", context do + browser_test "transitioning from initializing -> running expands the promotions as well", + context do task = Support.Stubs.Pipeline.add_compile_task(context.pipeline.id) page = open(context) diff --git a/front/test/browser/workflow_page/promotions_test.exs b/front/test/browser/workflow_page/promotions_test.exs index c90630b23..17d7bc67f 100644 --- a/front/test/browser/workflow_page/promotions_test.exs +++ b/front/test/browser/workflow_page/promotions_test.exs @@ -11,7 +11,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do {:ok, context} end - test "when target has parameters form is prefilled and displayed", ctx do + browser_test "when target has parameters form is prefilled and displayed", ctx do page = open(ctx) assert_text(page, "Production") @@ -22,13 +22,11 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert has_text?(page, "Where to deploy?") assert has_text?(page, "STRATEGY") - assert has_value?(page, Query.option("fast (default)"), "fast") - assert has_value?(page, Query.option("slow"), "slow") + assert has_text?(page, Query.data("value", "fast"), "fast (default)") assert has_text?(page, "Which deployment strategy should be used?") end - @tag :skip - test "promoting target with empty required parameter throws error", ctx do + browser_test "promoting target with empty required parameter throws error", ctx do page = open(ctx) assert_text(page, "QA") @@ -42,7 +40,8 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.css(".form-control-error")) end - test "when target has blocking deployment target and deployment targets are disabled", ctx do + browser_test "when target has blocking deployment target and deployment targets are disabled", + ctx do configure_dt_promotion(ctx, "Production", %{ allowed: false, reason: :BANNED_SUBJECT, @@ -57,7 +56,8 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do refute_has(page, Query.text("You cannot deploy")) end - test "when target has allowing deployment target and deployment targets are disabled", ctx do + browser_test "when target has allowing deployment target and deployment targets are disabled", + ctx do configure_dt_promotion(ctx, "Production", %{ allowed: true, reason: :NO_REASON, @@ -72,7 +72,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do refute_has(page, Query.text("You cannot deploy")) end - test "when target with no parameters is promoted, show yes/cancel options", ctx do + browser_test "when target with no parameters is promoted, show yes/cancel options", ctx do page = open(ctx) assert_text(page, "Staging") @@ -82,7 +82,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert has_text?(page, "Nevermind") end - test "promotion targets with single quotes render and open correctly", ctx do + browser_test "promotion targets with single quotes render and open correctly", ctx do quoted_name = "Publish 'my-package' to Production" Support.Stubs.Switch.add_target(ctx.switch, name: quoted_name) @@ -99,7 +99,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.text("Promote to #{quoted_name}?")) end - test "promotion targets with double quotes render and open correctly", ctx do + browser_test "promotion targets with double quotes render and open correctly", ctx do quoted_name = ~s(Deploy "production" build) Support.Stubs.Switch.add_target(ctx.switch, name: quoted_name) @@ -112,7 +112,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.css("[promote-confirmation][data-promotion-target='#{quoted_name}']")) end - test "promotion targets with backslashes render and open correctly", ctx do + browser_test "promotion targets with backslashes render and open correctly", ctx do name_with_backslash = "Deploy\\Staging\\App" Support.Stubs.Switch.add_target(ctx.switch, name: name_with_backslash) @@ -123,7 +123,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.text("Promote to #{name_with_backslash}?")) end - test "promotion targets with brackets and special characters work correctly", ctx do + browser_test "promotion targets with brackets and special characters work correctly", ctx do special_name = "Deploy[test]:value.config" Support.Stubs.Switch.add_target(ctx.switch, name: special_name) @@ -134,7 +134,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.text("Promote to #{special_name}?")) end - test "promotion targets with emoji render and open correctly", ctx do + browser_test "promotion targets with emoji render and open correctly", ctx do emoji_name = "Deploy 🚀 to Production" Support.Stubs.Switch.add_target(ctx.switch, name: emoji_name) @@ -145,7 +145,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.text("Promote to #{emoji_name}?")) end - test "promotion targets with accented characters render and open correctly", ctx do + browser_test "promotion targets with accented characters render and open correctly", ctx do accented_name = "Déploiement Français" Support.Stubs.Switch.add_target(ctx.switch, name: accented_name) @@ -156,7 +156,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.text("Promote to #{accented_name}?")) end - test "promotion targets with CJK characters render and open correctly", ctx do + browser_test "promotion targets with CJK characters render and open correctly", ctx do cjk_name = "部署到生产环境" Support.Stubs.Switch.add_target(ctx.switch, name: cjk_name) @@ -167,7 +167,8 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.text("Promote to #{cjk_name}?")) end - test "promotion targets with mixed special characters and unicode work correctly", ctx do + browser_test "promotion targets with mixed special characters and unicode work correctly", + ctx do mixed_name = "Deploy 'app' 🎉 to Production" Support.Stubs.Switch.add_target(ctx.switch, name: mixed_name) @@ -178,7 +179,8 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.text("Promote to #{mixed_name}?")) end - test "promotion targets with complex bracket and quote combinations work correctly", ctx do + browser_test "promotion targets with complex bracket and quote combinations work correctly", + ctx do complex_name = "test[data] 'value' config" Support.Stubs.Switch.add_target(ctx.switch, name: complex_name) @@ -195,7 +197,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do on_exit(fn -> Support.Stubs.Feature.disable_feature(ctx.org.id, :deployment_targets) end) end - test "when target has deployment target that blocks promotion", ctx do + browser_test "when target has deployment target that blocks promotion", ctx do configure_dt_promotion(ctx, "Production", %{ allowed: false, reason: :BANNED_SUBJECT, @@ -212,7 +214,7 @@ defmodule Front.Browser.WorkflowPage.PromotionsTest do assert_has(page, Query.link("ProductionDT")) end - test "when target has deployment target that allows promotion", ctx do + browser_test "when target has deployment target that allows promotion", ctx do configure_dt_promotion(ctx, "Production", %{ allowed: true, reason: :NO_REASON, diff --git a/front/test/browser/workflow_page_test.exs b/front/test/browser/workflow_page_test.exs index 59b2312a7..81fa321d1 100644 --- a/front/test/browser/workflow_page_test.exs +++ b/front/test/browser/workflow_page_test.exs @@ -17,7 +17,7 @@ defmodule Front.Browser.WorkflowPage do end describe "header" do - test "the users can see information about the commit", params do + browser_test "the users can see information about the commit", params do page = open(params) assert_text(page, params.hook.api_model.commit_message) @@ -26,7 +26,7 @@ defmodule Front.Browser.WorkflowPage do end describe "diagram" do - test "the users can see the pipeline", params do + browser_test "the users can see the pipeline", params do page = open(params) assert_text(page, "Build & Test") @@ -35,14 +35,14 @@ defmodule Front.Browser.WorkflowPage do assert_text(page, "Block 3") end - test "the users can see promotions", params do + browser_test "the users can see promotions", params do page = open(params) assert_text(page, "Production") assert_text(page, "Staging") end - test "promotions with unicode characters (emoji) are displayed correctly", params do + browser_test "promotions with unicode characters (emoji) are displayed correctly", params do switch = params.switch Support.Stubs.Switch.add_target(switch, name: "Deploy 🚀 Production") @@ -51,7 +51,7 @@ defmodule Front.Browser.WorkflowPage do assert_text(page, "Deploy 🚀 Production") end - test "promotions with accented characters are displayed correctly", params do + browser_test "promotions with accented characters are displayed correctly", params do switch = params.switch Support.Stubs.Switch.add_target(switch, name: "Déploiement Français") @@ -60,7 +60,7 @@ defmodule Front.Browser.WorkflowPage do assert_text(page, "Déploiement Français") end - test "promotions with CJK characters are displayed correctly", params do + browser_test "promotions with CJK characters are displayed correctly", params do switch = params.switch Support.Stubs.Switch.add_target(switch, name: "部署到生产环境") @@ -69,7 +69,7 @@ defmodule Front.Browser.WorkflowPage do assert_text(page, "部署到生产环境") end - test "promotions with single quotes are displayed and clickable", params do + browser_test "promotions with single quotes are displayed and clickable", params do switch = params.switch Support.Stubs.Switch.add_target(switch, name: "Publish 'my-package' to Production") @@ -79,7 +79,7 @@ defmodule Front.Browser.WorkflowPage do assert find(page, Query.button("Publish 'my-package' to Production")) end - test "promotions with mixed unicode and special characters work correctly", params do + browser_test "promotions with mixed unicode and special characters work correctly", params do switch = params.switch Support.Stubs.Switch.add_target(switch, name: "Deploy 'app' 🎉 to Staging") @@ -89,7 +89,7 @@ defmodule Front.Browser.WorkflowPage do assert find(page, Query.button("Deploy 'app' 🎉 to Staging")) end - test "If project is public, show blocks, but promotions should be disabled", params do + browser_test "If project is public, show blocks, but promotions should be disabled", params do Support.Stubs.PermissionPatrol.remove_all_permissions() with_mocks([ @@ -110,11 +110,11 @@ defmodule Front.Browser.WorkflowPage do end describe "editing a workflow" do - test "edit button is visible when user has write github access", params do + browser_test "edit button is visible when user has write github access", params do open(params) |> assert_has(@edit_link) end - test "click on 'edit' opens the Visual Builder", params do + browser_test "click on 'edit' opens the Visual Builder", params do open(params) |> click(@edit_link) |> assert_text("Visual Builder") end end @@ -126,17 +126,15 @@ defmodule Front.Browser.WorkflowPage do {:ok, params} end - test "when the waiting is > 20 secs => display link to Activity Monitor", params do + browser_test "when the waiting is > 20 secs => display link to Activity Monitor", params do Support.Stubs.Time.travel_back(:timer.minutes(15), fn -> params.blocks |> Enum.each(fn block -> Support.Stubs.Task.create(block) end) end) - params.session |> take_screenshot() - open(params) |> assert_has(@waiting_for_quota_bagde) end - test "when the waiting is < 20 secs => don't display Activity link", params do + browser_test "when the waiting is < 20 secs => don't display Activity link", params do open(params) |> refute_has(@waiting_for_quota_bagde) end end diff --git a/front/test/support/browser.ex b/front/test/support/browser.ex index c456a402b..eb39014b6 100644 --- a/front/test/support/browser.ex +++ b/front/test/support/browser.ex @@ -1,5 +1,11 @@ defmodule Support.Browser do use Wallaby.DSL + require Wallaby.Browser + + alias Wallaby.{Browser, Query, StaleReferenceError} + + @stale_retry_attempts 5 + @stale_retry_delay 100 def fetch_js_value(session, script) do session @@ -37,7 +43,71 @@ defmodule Support.Browser do session |> execute_script("window.onbeforeunload = null;") end - def scroll_into_view(session, css_selector) do - session |> execute_script("document.querySelector('#{css_selector}').scrollIntoView()") + @doc """ + Like `assert_has/2`, but retries automatically if the DOM was replaced. + """ + def assert_stable(session, query) do + retry_on_stale(fn -> Browser.assert_has(session, query) end) + session + end + + @doc """ + Like `assert_text/2`, but retries automatically if the DOM was replaced. + """ + def assert_stable_text(session, text) do + retry_on_stale(fn -> Browser.assert_text(session, text) end) + session + end + + @doc """ + Waits for the global flash banner rendered in `_action_notification.html.eex`. + """ + def assert_flash_notice(session, text) do + assert_stable(session, Query.css("#changes-notification p", text: text)) + end + + def retry_on_stale(fun, attempts \\ @stale_retry_attempts) + def retry_on_stale(fun, 0), do: fun.() + + def retry_on_stale(fun, attempts) do + fun.() + rescue + _ in StaleReferenceError -> + Process.sleep(@stale_retry_delay) + retry_on_stale(fun, attempts - 1) + end +end + +defmodule Support.Browser.Assertions do + require Wallaby.Browser + + defmacro assert_text(session, text) do + quote do + Support.Browser.retry_on_stale(fn -> + Wallaby.Browser.assert_text(unquote(session), unquote(text)) + end) + + unquote(session) + end + end + + defmacro assert_has(session, query) do + quote do + Support.Browser.retry_on_stale(fn -> + Wallaby.Browser.assert_has(unquote(session), unquote(query)) + end) + + unquote(session) + end + end + + defmacro refute_has(session, query) do + quote do + Support.Browser.retry_on_stale(fn -> + Wallaby.Browser.refute_has(unquote(session), unquote(query)) + end) + + unquote(session) + end end end diff --git a/front/test/support/browser/workflow_editor.ex b/front/test/support/browser/workflow_editor.ex index fa8e12666..024408fb9 100644 --- a/front/test/support/browser/workflow_editor.ex +++ b/front/test/support/browser/workflow_editor.ex @@ -125,18 +125,6 @@ defmodule Support.Browser.WorkflowEditor do query = Query.css("#workflow-editor-config-panel details summary", text: title) click(session, query) - - scroll_into_view = - [ - "let query = '#workflow-editor-config-panel details summary'", - "let els = document.querySelectorAll(query)", - "let el = Array.from(els).find((el) => el.textContent === '#{title}')", - "el.scrollIntoView(true)", - "return true" - ] - |> Enum.join(";") - - session |> execute_script(scroll_into_view) end def fill(session, query, value) do diff --git a/front/test/support/wallaby_conn_case.ex b/front/test/support/wallaby_conn_case.ex index 88753ef6e..fa4629131 100644 --- a/front/test/support/wallaby_conn_case.ex +++ b/front/test/support/wallaby_conn_case.ex @@ -6,6 +6,10 @@ defmodule FrontWeb.WallabyCase do import Plug.Conn import Phoenix.ConnTest use Wallaby.DSL + require Wallaby.Browser + import Wallaby.Browser, except: [assert_text: 2, assert_has: 2, refute_has: 2] + import Support.Browser.Assertions + import FrontWeb.WallabyCase, only: [browser_test: 2, browser_test: 3] @moduletag :browser @@ -16,6 +20,29 @@ defmodule FrontWeb.WallabyCase do end end + defmacro browser_test(message, context \\ quote(do: _), contents) do + context = Macro.escape(context) + contents = Macro.escape(contents, unquote: true) + + quote bind_quoted: [context: context, contents: contents, message: message] do + name = ExUnit.Case.register_test(__MODULE__, __ENV__.file, __ENV__.line, :test, message, []) + + def unquote(name)(unquote(context)) do + unquote(contents) + rescue + exception -> + if Wallaby.screenshot_on_failure?() do + Wallaby.Feature.Utils.take_screenshots_for_sessions( + self(), + to_string(unquote(message)) + ) + end + + reraise(exception, __STACKTRACE__) + end + end + end + setup _tags do Cachex.clear(:front_cache) Cachex.clear(:auth_cache) @@ -25,7 +52,11 @@ defmodule FrontWeb.WallabyCase do Application.put_env(:wallaby, :js_errors, true) - {:ok, session} = Wallaby.start_session(window_size: [width: 1280, height: 720]) + {:ok, session} = Wallaby.start_session() + + on_exit(fn -> + Wallaby.end_session(session) + end) {:ok, conn: Phoenix.ConnTest.build_conn(), session: session} end diff --git a/front/test/test_helper.exs b/front/test/test_helper.exs index c663ac7db..4ab70d827 100644 --- a/front/test/test_helper.exs +++ b/front/test/test_helper.exs @@ -13,11 +13,35 @@ Application.put_env(:wallaby, :base_url, FrontWeb.Endpoint.url()) {:ok, file} = File.open("browser_logs.log", [:write]) Application.put_env(:wallaby, :js_logger, file) +Application.put_env( + :wallaby, + :chromedriver, + Application.get_env(:wallaby, :chromedriver, []) + |> Keyword.merge( + headless: false, + capabilities: + Wallaby.Chrome.default_capabilities() + |> put_in([:chromeOptions, :args], [ + "--headless=new", + "--no-sandbox", + "--disable-dev-shm-usage", + "--disable-gpu", + "--disable-background-networking", + "--disable-renderer-backgrounding", + "--disable-software-rasterizer", + "--remote-debugging-port=0", + "window-size=1920,1600", + "--user-agent=Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36" + ]) + ) +) + Support.Stubs.init() Mox.defmock(ServiceAccountMock, for: Front.ServiceAccount.Behaviour) ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter]) + ExUnit.start(trace: false, capture_log: true) Faker.start()