Skip to content
Merged
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
48 changes: 37 additions & 11 deletions .github/workflows/run-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,51 @@ jobs:
rm -rf emulator-data
cp -r e2e/e2e-emulator-data emulator-data

# 3) Run App + E2E Test #
- name: Run all Devbox services
run: devbox services up -b

- name: Install Playwright dependencies
run: npm ci
working-directory: e2e

- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('e2e/package-lock.json') }}

- name: Install Playwright Browsers
run: npx playwright install --with-deps
timeout-minutes: 20
working-directory: e2e
run: DEBUG=pw:install npx --no-install playwright install --with-deps chromium

# 3) Run App + E2E Test #
- name: Run all Devbox services
run: devbox services up -b

- name: Show service logs
if: always()
run: |
sleep 5
ls -la logs || true
tail -n 80 logs/firebase-emulators.log || true
tail -n 80 logs/library-api.log || true
tail -n 80 logs/sync-library-metadata.log || true
tail -n 80 logs/builder-api.log || true
tail -n 80 logs/builder-frontend.log || true

- name: Wait for App to be available
uses: nev7n/wait_for_response@v1
with:
url: "http://localhost:5173/"
responseCode: 200
timeout: 90000
interval: 1000
run: |
timeout 90 bash -c '
until curl --fail --silent --show-error http://127.0.0.1:5173/ > /dev/null; do
echo "Waiting for frontend..."
sleep 1
done
'
# - name: Wait for App to be available
# uses: nev7n/wait_for_response@v1
# with:
# url: "http://127.0.0.1:5173/"
# responseCode: 200
# timeout: 90000
# interval: 1000

- name: Run Playwright tests
run: npx playwright test
Expand Down
100 changes: 100 additions & 0 deletions bin/run-e2e-tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env bash

# Run the Playwright e2e suite against the local dev stack.
#
# This script temporarily replaces root emulator-data with the e2e fixture data
# and restores the previous emulator-data directory before exiting.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
BACKUP_DIR=""
SERVICES_STARTED=0

cd "$PROJECT_ROOT"

cleanup() {
local exit_code=$?

if [ "$SERVICES_STARTED" -eq 1 ]; then
devbox services stop || true
fi

rm -rf emulator-data
if [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR/emulator-data" ]; then
mv "$BACKUP_DIR/emulator-data" emulator-data
rmdir "$BACKUP_DIR" 2>/dev/null || true
fi

exit "$exit_code"
}

trap cleanup EXIT

ensure_env_file() {
local target="$1"
local example="$2"

if [ ! -f "$target" ]; then
cp "$example" "$target"
fi
}

wait_for_url() {
local name="$1"
local url="$2"
local max_attempts="${3:-90}"
local attempt=1

echo "Waiting for $name at $url"
while [ "$attempt" -le "$max_attempts" ]; do
if curl --silent --show-error --output /dev/null --max-time 2 "$url"; then
echo "$name is ready"
return 0
fi

sleep 1
attempt=$((attempt + 1))
done

echo "Timed out waiting for $name at $url" >&2
return 1
}

if ! command -v devbox >/dev/null 2>&1; then
echo "devbox is required. Install it with bin/install-devbox first." >&2
exit 1
fi

ensure_env_file ".env" ".env.example"
ensure_env_file "builder-frontend/.env" "builder-frontend/.env.example"
ensure_env_file "builder-api/.env" "builder-api/.env.example"
ensure_env_file "library-api/.env" "library-api/.env.example"

devbox run install-builder-frontend-ci

devbox services stop || true

if [ -d emulator-data ]; then
BACKUP_DIR="$(mktemp -d)"
mv emulator-data "$BACKUP_DIR/emulator-data"
fi

cp -R e2e/e2e-emulator-data emulator-data

devbox services up -b
SERVICES_STARTED=1

wait_for_url "Firestore emulator" "http://localhost:8080/"
wait_for_url "Storage emulator" "http://localhost:9199/"
wait_for_url "Auth emulator" "http://localhost:9099/"
wait_for_url "Library API" "http://localhost:8083/"
wait_for_url "builder frontend" "http://localhost:5173/"

(
cd e2e
npm ci
npx playwright install
npx playwright test "$@"
)
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default function NewScreenerForm({}) {
type="submit"
variant="secondary"
id="new-screener-submit"
data-testid="submit-new-screener-button"
disabled={isLoading()}
>
Create
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export default function ProjectsList() {
build custom checks that meet your specific needs.
</div>
<button
data-testid="create-new-screener-button"
onClick={() => setIsNewScreenerModalVisible(true)}
class="
mt-2 px-4 py-2 w-fit cursor-pointer bg-blue-500
Expand Down
3 changes: 3 additions & 0 deletions builder-frontend/src/components/project/FormEditorView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ function FormEditorView({ formSchema, setFormSchema }) {
<Switch>
<Match when={isUnsaved()}>
<button
data-testid="form-editor-save-button"
onClick={handleSave}
class="btn-default btn-yellow shadow-[0_0_10px_rgba(0,0,0,0.4)]"
>
Expand All @@ -204,6 +205,7 @@ function FormEditorView({ formSchema, setFormSchema }) {
</Match>
<Match when={isSaving()}>
<button
data-testid="form-editor-save-button"
onClick={handleSave}
class="btn-default btn-gray cursor-not-allowed shadow-[0_0_10px_rgba(0,0,0,0.4)]"
>
Expand All @@ -212,6 +214,7 @@ function FormEditorView({ formSchema, setFormSchema }) {
</Match>
<Match when={!isUnsaved() && !isSaving()}>
<button
data-testid="form-editor-save-button"
onClick={handleSave}
class="btn-default btn-blue shadow-[0_0_10px_rgba(0,0,0,0.4)]"
>
Expand Down
1 change: 1 addition & 0 deletions builder-frontend/src/components/project/Publish.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export default function Publish({ project, refetchProject }) {
<Button
variant="secondary"
id="publish-screener-button"
data-testid="publish-screener-button"
onClick={handlePublish}
disabled={isLoading()}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const BenefitList = ({
benefit can have associated eligibility checks.
</div>
<div
data-testid="create-new-benefit-button"
class="btn-default btn-blue mb-3 mr-1"
onClick={() => {
setAddingNewBenefit(true);
Expand Down Expand Up @@ -154,6 +155,7 @@ const BenefitCard = ({
class="p-4 flex justify-end space-x-2"
>
<div
data-testid={`edit-benefit-${benefit.id}`}
class="btn-default btn-gray"
onClick={() => {
setBenefitIdToConfigure(benefit.id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const AddNewBenefitModal = (
<div
class={"btn-default bg-sky-600 text-white " + addButtonClasses()}
id="new-benefit-submit"
data-testid="submit-new-benefit-button"
onClick={async () => {
if (isAddDisabled()) {
console.log("Please fill in all fields.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@ const EligibilityCheckRow = ({
return (
<tr id={"check-row_" + check.name}>
<td class="eligibility-check-table-cell border-top">
<div class="btn-default btn-blue" onClick={() => onAdd(check)}>
<div
data-testid={`add-check-${check.name}`}
class="btn-default btn-blue"
onClick={() => onAdd(check)}
>
Add
</div>
</td>
Expand Down
1 change: 1 addition & 0 deletions builder-frontend/src/components/shared/BdtNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const BdtNavbar = ({ navProps }: { navProps: Accessor<NavbarProps> }) => {
</Show>
{navProps().tabDefs.map((tab) => (
<button
data-testid={`project-tab-${tab.key}`}
class={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${
navProps().activeTabKey() === tab.key
? "border-b border-gray-700 text-gray-700 hover:bg-gray-200"
Expand Down
Loading
Loading