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
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ jobs:
uses: ./.github/workflows/generate-sbom.yml
secrets: inherit

invoke-tests-web-console-e2e:
name: Web Console End-to-End Tests
needs: [check-prior-build, invoke-build-docker]
if: |
always() &&
(needs.invoke-build-docker.result == 'success' || needs.invoke-build-docker.result == 'skipped')
uses: ./.github/workflows/test-web-console-e2e.yml
secrets: inherit

invoke-tests-integration-platform:
name: Integration Tests
needs: [check-prior-build, invoke-build-docker]
Expand Down Expand Up @@ -298,6 +307,21 @@ jobs:
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel"

cancel-if-tests-web-console-integration-failed:
name: Cancel if Web Console Integration Tests Failed
needs: [invoke-tests-web-console-e2e]
if: failure()
runs-on: ubuntu-latest-amd64
permissions:
actions: write
steps:
- name: Cancel workflow
run: |
curl -fsSL -X POST \
-H "Authorization: Bearer ${{ github.token }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel"

cancel-if-tests-integration-platform-failed:
name: Cancel if Platform Integration Tests Failed
needs: [invoke-tests-integration-platform]
Expand Down Expand Up @@ -370,6 +394,7 @@ jobs:
- invoke-build-java
- invoke-build-docs
- invoke-tests-web-console-unit
- invoke-tests-web-console-e2e
- invoke-tests-unit
- invoke-tests-adapter
- invoke-build-docker
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/test-web-console-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Web Console Integration Tests

on:
workflow_call:
workflow_dispatch:

jobs:
web-console-integration-tests:
name: Web Console Integration Tests
runs-on: [k8s-runners-amd64]

container:
image: mcr.microsoft.com/playwright:v1.58.2-noble

services:
pipeline-manager:
image: ${{ vars.FELDERA_IMAGE_NAME }}:sha-${{ github.sha }}
env:
AUTH_PROVIDER: none
RUST_LOG: info
RUST_BACKTRACE: 1
options: >-
--health-cmd "curl --fail --silent --max-time 2 http://localhost:8080/healthz || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Bun
run: |
npm install -g --prefix /tmp/bun bun@1.3.10
echo "/tmp/bun/bin" >> $GITHUB_PATH

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Sync SvelteKit
run: bunx svelte-kit sync
working-directory: js-packages/web-console

- name: Verify pipeline-manager is reachable
run: curl -fsSL --retry 5 --retry-delay 2 --retry-connrefused http://localhost:8080/healthz

- name: Run Playwright e2e tests
if: ${{ vars.CI_DRY_RUN != 'true' }}
run: bun run test-e2e
working-directory: js-packages/web-console
env:
PLAYWRIGHT_API_ORIGIN: http://localhost:8080
PLAYWRIGHT_APP_ORIGIN: http://localhost:8080

- name: Show Kubernetes node
if: always()
run: |
echo "K8S node: ${K8S_NODE_NAME}"
72 changes: 71 additions & 1 deletion bun.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js-packages/web-console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@sveltejs/adapter-auto": "7.0.1",
"@sveltejs/adapter-static": "3.0.10",
"@sveltejs/kit": "2.52.2",
"@sveltejs/vite-plugin-svelte": "6.2.4",
"@sveltejs/vite-plugin-svelte": "7.0.0",
"@tailwindcss/forms": "0.5.11",
"@tailwindcss/typography": "0.5.19",
"@tailwindcss/vite": "4.2.0",
Expand Down Expand Up @@ -124,7 +124,7 @@
"generate-openapi": "openapi-ts && bun run format",
"build-openapi": "cd ../.. && cargo run -p pipeline-manager -- --dump-openapi",
"build-icons": "bun run scripts/build-webfont.ts -- -s src/assets/icons/feldera-material-icons -d src/assets/fonts/ -n feldera-material-icons -p fd --fix && bun run scripts/build-webfont.ts -- -s src/assets/icons/generic -d src/assets/fonts/ -n generic-icons -p gc && bun run format",
"test-e2e": "PLAYWRIGHT_API_ORIGIN=http://localhost:8080/ PLAYWRIGHT_APP_ORIGIN=http://localhost:8080/ DISPLAY= bun playwright test",
"test-e2e": "DISPLAY= bun playwright test",
"test-e2e-ui": "PLAYWRIGHT_API_ORIGIN=http://localhost:8080/ PLAYWRIGHT_APP_ORIGIN=http://localhost:8080/ DISPLAY= bun playwright test --ui-host=0.0.0.0",
"test-ct": "DISPLAY= bun playwright test -c playwright-ct.config.ts",
"test-ct-ui": "DISPLAY= bun playwright test -c playwright-ct.config.ts --ui-host=0.0.0.0",
Expand Down
18 changes: 13 additions & 5 deletions js-packages/web-console/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import type { PlaywrightTestConfig } from '@playwright/test'

const appOrigin = process.env.PLAYWRIGHT_APP_ORIGIN

const config: PlaywrightTestConfig = {
webServer: {
command: 'npm run build && npm run preview',
port: 4173
},
// The globalSetup only runs when PLAYWRIGHT_APP_ORIGIN is set (i.e., dedicated Feldera instance), not during the local build+preview mode.
globalSetup: appOrigin ? './tests/global-setup.ts' : undefined,
...(appOrigin
? { use: { baseURL: appOrigin } }
: {
webServer: {
command: 'npm run build && npm run preview',
port: 4173
}
}),
testDir: 'tests',
testMatch: /(.+\.)?(test|spec)\.[jt]s/,
testMatch: /(.+\.)?e2e\.[jt]s/,
snapshotDir: 'playwright-snapshots/e2e',
expect: {
toHaveScreenshot: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
let lastGenerated = $state<{ name: string; key: string }[]>([])
</script>

<div class="flex flex-col gap-4 p-4">
<div class="flex flex-col gap-4">
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<form
class="flex flex-col gap-2"
Expand Down Expand Up @@ -82,40 +82,38 @@
</FieldErrors>
</Field>
</form>
<div>
{#if lastGenerated.length}
<div class="flex flex-col rounded bg-surface-50-950 p-4">
<div class="flex w-full flex-nowrap gap-2">
<div class="fd fd-circle-alert w-6 text-[20px]"></div>
<span>
{#if lastGenerated.length === 1}
This key will only be shown once and cannot be viewed again.<br />
<span class="font-semibold">Please ensure you store it securely.</span>
{:else}
These keys will only be shown once and cannot be viewed again.<br />
<span class="font-semibold">Please ensure you store them securely.</span>
{/if}
</span>
<button
class="fd fd-x ml-auto btn-icon text-[24px]"
onclick={() => {
lastGenerated = []
}}
aria-label="Hide new keys"
></button>
</div>
{#if lastGenerated.length}
<div class="scrollbar flex max-h-[30vh] flex-col overflow-y-auto rounded bg-surface-50-950 p-4">
<div class="flex w-full flex-nowrap gap-2">
<div class="fd fd-circle-alert w-6 text-[20px]"></div>
<span>
{#if lastGenerated.length === 1}
This key will only be shown once and cannot be viewed again.<br />
<span class="font-semibold">Please ensure you store it securely.</span>
{:else}
These keys will only be shown once and cannot be viewed again.<br />
<span class="font-semibold">Please ensure you store them securely.</span>
{/if}
</span>
<button
class="fd fd-x ml-auto btn-icon text-[24px]"
onclick={() => {
lastGenerated = []
}}
aria-label="Hide new keys"
></button>
</div>

<div class="pt-4 pl-8">
{#each lastGenerated as { name, key }}
<div class="flex w-full flex-nowrap items-center gap-2">
<span>{name}:</span>
<span class="w-full overflow-hidden overflow-ellipsis">{key}</span>
<ClipboardCopyButton value={key}></ClipboardCopyButton>
<Tooltip placement="top">Copy to clipboard</Tooltip>
</div>
{/each}
</div>
<div class="pt-4 pl-8">
{#each lastGenerated as { name, key }}
<div class="flex w-full flex-nowrap items-center gap-2">
<span class="text-nowrap">{name}:</span>
<span class="w-full overflow-hidden overflow-ellipsis">{key}</span>
<ClipboardCopyButton value={key}></ClipboardCopyButton>
<Tooltip placement="top">Copy to clipboard</Tooltip>
</div>
{/each}
</div>
{/if}
</div>
</div>
{/if}
</div>

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
actionName: string,
itemName: string | ((...args: Args) => string),
onAction: (...args: Args) => void | Promise<any>,
description = 'Are you sure? This action is irreversible.',
description?: string,
scrollableContent?: string
) {
return (...args: Args) => ({
Expand All @@ -18,36 +18,41 @@
</script>

<script lang="ts" generics="Args extends unknown[]">
import DangerDialog from './DangerDialog.svelte'
import { useGlobalDialog } from '$lib/compositions/layout/useGlobalDialog.svelte'

import GenericDialog from './GenericDialog.svelte'

let {
actionName,
itemName,
onAction,
description = 'Are you sure? This action is irreversible.',
scrollableContent,
args,
onClose
args
}: {
actionName: string
itemName: string | ((...args: Args) => string)
onAction: (...args: Args) => void | Promise<any>
description?: string
scrollableContent?: string
args: Args
onClose: () => void
} = $props()

let globalDialog = useGlobalDialog()

let content = $derived({
title: typeof itemName === 'string' ? itemName : itemName(...args),
description,
scrollableContent,
onSuccess: {
name: actionName,
callback: () => onAction(...args),
callback: async () => {
await onAction(...args)
globalDialog.dialog = null
},
'data-testid': 'button-confirm-delete'
}
})
</script>

<DangerDialog {content} {onClose}></DangerDialog>
<GenericDialog {content} danger></GenericDialog>
Loading
Loading