Skip to content

Has/e2e/UI user management #267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion e2e/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ e2e-*.tar

# Temporary files, for example, from tests.
/tmp/
/out/
/out/
.envrc
54 changes: 54 additions & 0 deletions e2e/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
ARG ELIXIR_VERSION=1.14.3
ARG OTP_VERSION=25.2.3
ARG ALPINE_VERSION=3.18.0
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-alpine-${ALPINE_VERSION}"

# Base stage with common dependencies
FROM ${BUILDER_IMAGE} AS base

# Set Wallaby env var
ENV START_WALLABY=true

# Install system dependencies including ChromeDriver
RUN apk update && \
apk add --no-cache \
build-base \
git \
python3 \
curl \
openssh \
chromium \
chromium-chromedriver \
xvfb \
bash \
# Add additional dependencies that may be required
ttf-freefont \
fontconfig \
dbus \
&& apk add --no-cache --upgrade busybox busybox-binsh ssl_client

# Set up Chrome for headless operation
ENV CHROME_BIN=/usr/bin/chromium-browser
ENV CHROME_PATH=/usr/lib/chromium/
ENV CHROME_DRIVER_PATH=/usr/bin/chromedriver

# Set up Elixir environment
WORKDIR /app

# Install hex and rebar
RUN mix local.hex --force && \
mix local.rebar --force

# Copy and compile dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get && mix deps.compile

# Copy application code
COPY . .

# Set Wallaby to use Chrome in headless mode
ENV WALLABY_DRIVER=chrome
ENV WALLABY_CHROME_HEADLESS=true

# Create directory for screenshots
RUN mkdir -p /app/out/screenshots
44 changes: 43 additions & 1 deletion e2e/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: format test test.ui
.PHONY: format test test.ui console.bash test.ui.docker

SHELL := /bin/bash
export MIX_ENV ?= test
Expand All @@ -17,12 +17,54 @@ ifeq (test.ui,$(MAKECMDGOALS))
export START_WALLABY=true
endif

ifeq (test.ui.docker,$(MAKECMDGOALS))
export START_WALLABY=true
endif

ifeq (console.bash,$(MAKECMDGOALS))
export START_WALLABY=true
endif

gcloud.auth:
gcloud config set project $(GOOGLE_PROJECT_NAME) --quiet && gcloud auth login --cred-file=$(GOOGLE_APPLICATION_CREDENTIALS)

console.ex: env.assert mix.prepare
iex -S mix

# Start a bash shell in the Docker container
console.bash: env.assert
docker compose run --rm \
-e START_WALLABY=true \
-e MIX_ENV=$(MIX_ENV) \
-e BASE_DOMAIN=$(BASE_DOMAIN) \
-e CLOUD_TEST_ENV_PREFIX=$(CLOUD_TEST_ENV_PREFIX) \
-e GITHUB_ORGANIZATION=$(GITHUB_ORGANIZATION) \
-e GITHUB_REPOSITORY=$(GITHUB_REPOSITORY) \
-e GITHUB_BRANCH=$(GITHUB_BRANCH) \
-e SEMAPHORE_ORGANIZATION=$(SEMAPHORE_ORGANIZATION) \
-e SEMAPHORE_BASE_DOMAIN=$(SEMAPHORE_BASE_DOMAIN) \
-e SEMAPHORE_USER_EMAIL=$(SEMAPHORE_USER_EMAIL) \
-e SEMAPHORE_API_TOKEN=$(SEMAPHORE_API_TOKEN) \
-e SEMAPHORE_USER_PASSWORD=$(SEMAPHORE_USER_PASSWORD) \
e2e-tests sh

# Run UI tests in Docker
test.ui.docker: env.assert
docker compose run --rm \
-e START_WALLABY=true \
-e MIX_ENV=$(MIX_ENV) \
-e BASE_DOMAIN=$(BASE_DOMAIN) \
-e CLOUD_TEST_ENV_PREFIX=$(CLOUD_TEST_ENV_PREFIX) \
-e GITHUB_ORGANIZATION=$(GITHUB_ORGANIZATION) \
-e GITHUB_REPOSITORY=$(GITHUB_REPOSITORY) \
-e GITHUB_BRANCH=$(GITHUB_BRANCH) \
-e SEMAPHORE_ORGANIZATION=$(SEMAPHORE_ORGANIZATION) \
-e SEMAPHORE_BASE_DOMAIN=$(SEMAPHORE_BASE_DOMAIN) \
-e SEMAPHORE_USER_EMAIL=$(SEMAPHORE_USER_EMAIL) \
-e SEMAPHORE_API_TOKEN=$(SEMAPHORE_API_TOKEN) \
-e SEMAPHORE_USER_PASSWORD=$(SEMAPHORE_USER_PASSWORD) \
e2e-tests sh -c "chromedriver --port=9515 --whitelisted-ips='' --url-base=/wd/hub & mix test $(if $(TEST_FILE),$(TEST_FILE),test/e2e/ui)"

format:
SEMAPHORE_API_TOKEN="" \
SEMAPHORE_USER_PASSWORD="" \
Expand Down
37 changes: 37 additions & 0 deletions e2e/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: "3"

services:
e2e-tests:
build:
context: .
dockerfile: Dockerfile
platform: linux/arm64 # Use ARM64 platform for Apple Silicon Macs
shm_size: 2gb # Increase shared memory for Chrome
volumes:
- .:/app
- ./out/screenshots:/app/out/screenshots
environment:
- START_WALLABY
- WALLABY_DRIVER=chrome
- WALLABY_CHROME_HEADLESS=true
- MIX_ENV
# Chrome/Chromium configuration
- CHROME_BIN=/usr/bin/chromium-browser
- CHROME_PATH=/usr/lib/chromium/
# Pass Semaphore environment variables from the host
- SEMAPHORE_API_TOKEN
- SEMAPHORE_USER_PASSWORD
- SEMAPHORE_BASE_DOMAIN
- SEMAPHORE_USER_EMAIL
- SEMAPHORE_ORGANIZATION
- CLOUD_TEST_ENV_PREFIX
- BASE_DOMAIN
- GITHUB_ORGANIZATION
- GITHUB_REPOSITORY
- GITHUB_BRANCH
- GOOGLE_PROJECT_NAME
- GOOGLE_APPLICATION_CREDENTIALS
ports:
- "9515:9515" # ChromeDriver port
command: >
sh -c "chromedriver --port=9515 --verbose --whitelisted-ips='' --url-base=/wd/hub & mix test --include browser"
7 changes: 6 additions & 1 deletion e2e/lib/e2e/clients/common.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,18 @@ defmodule E2E.Clients.Common do
url = api_url(endpoint)
timeout = Application.get_env(:e2e, :http_timeout, 30_000)

case HTTPoison.get(url, headers, timeout: timeout, recv_timeout: timeout, follow_redirect: true) do
case HTTPoison.get(url, headers,
timeout: timeout,
recv_timeout: timeout,
follow_redirect: true
) do
{:ok, response} ->
{:ok, response}

{:error, %HTTPoison.Error{reason: :timeout}} ->
# Retry once on timeout
Process.sleep(1000)

HTTPoison.get(url, headers, timeout: timeout, recv_timeout: timeout, follow_redirect: true)

error ->
Expand Down
1 change: 0 additions & 1 deletion e2e/lib/e2e/clients/job.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ defmodule E2E.Clients.Job do
{:error, reason}
end
end

end
19 changes: 18 additions & 1 deletion e2e/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,24 @@ defmodule E2E.MixProject do
]
end

defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(:test) do
base = ["lib", "test/support"]
if System.get_env("START_WALLABY") do
base
else
# Exclude ui_test_case.ex if Wallaby is not available
["lib", "test/support"]
|> Enum.flat_map(fn path ->
if path == "test/support" do
Path.wildcard("test/support/*.ex")
|> Enum.reject(&(&1 =~ "ui_test_case.ex"))
else
[path]
end
end)
end
end

defp elixirc_paths(:dev), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]

Expand Down
2 changes: 1 addition & 1 deletion e2e/test/e2e/api/secrets_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ defmodule E2E.API.SecretsTest do
name = "test-project-#{:rand.uniform(1_000_000)}"
repository_url = "[email protected]:#{organization}/#{repository}.git"
{:ok, project} = Support.prepare_project(name, repository_url)

on_exit(fn ->
:ok = Project.delete(name)
end)
Expand Down
31 changes: 17 additions & 14 deletions e2e/test/e2e/api/task_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,32 @@ defmodule E2E.API.TaskTest do
name = "test-project-#{:rand.uniform(1_000_000)}"

# Create project with a task
task_definitions = [%{
"name" => "test-task",
"status" => "ACTIVE",
"description" => "Test periodic task",
"at" => "0 * * * *",
"pipeline_file" => ".semaphore/semaphore.yml",
"branch" => "main",
"parameters" => []
}]
task_definitions = [
%{
"name" => "test-task",
"status" => "ACTIVE",
"description" => "Test periodic task",
"at" => "0 * * * *",
"pipeline_file" => ".semaphore/semaphore.yml",
"branch" => "main",
"parameters" => []
}
]

{:ok, created_project} = Support.prepare_project(name, repository_url, task_definitions)

on_exit(fn ->
:ok = Project.delete(name)
end)

task = created_project["spec"]["tasks"] |> hd
{:ok,
project_id: created_project["metadata"]["id"],
task_id: task["id"]
}
{:ok, project_id: created_project["metadata"]["id"], task_id: task["id"]}
end

test "run task with run_now and wait for completion", %{project_id: project_id, task_id: task_id} do
test "run task with run_now and wait for completion", %{
project_id: project_id,
task_id: task_id
} do
# Trigger run_now
{:ok, response} = E2E.Clients.Task.run_now(task_id)

Expand Down
1 change: 1 addition & 0 deletions e2e/test/e2e/api/workflow_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ defmodule E2E.API.WorkflowTest do
Enum.each(pipelines, fn pipeline ->
if pipeline["result"] != "PASSED" do
{:ok, job_ids} = Pipeline.failed_jobs_id(pipeline["ppl_id"])

Enum.each(job_ids, fn job_id ->
{:ok, events} = Job.events(job_id)
Enum.each(events, fn event -> IO.puts(inspect(event)) end)
Expand Down
Loading