Skip to content
Open
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
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ PUBLIC_API_URL=http://localhost:8080


USERSPACE_USER_DEFAULT_ADMIN_EMAIL=admin@wippy.local
USERSPACE_USER_DEFAULT_ADMIN_PASSWORD=admin123
USERSPACE_USER_DEFAULT_ADMIN_PASSWORD=admin123

# OpenAI-compatible provider (supports OpenRouter, Ollama, vLLM, etc.)
OPENAI_COMPAT_API_KEY=your-api-key-here
OPENAI_COMPAT_BASE_URL=https://openrouter.ai/api/v1
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ wippy.exe
CLAUDE.md
.idea
.claude

.playwright-mcp/

.local/

.playwright-mcp/
test-results/

.local/
17 changes: 9 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ lint:
cd frontend/web-components/counter-persist && npm run lint

clean-build:
cd frontend/applications/main && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/app/main --emptyOutDir
cd frontend/web-components/reaction-bar && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/wc/reaction-bar --emptyOutDir
cd frontend/web-components/websocket-log && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/wc/websocket-log --emptyOutDir
cd frontend/web-components/chart-circle && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/wc/chart-circle --emptyOutDir
cd frontend/web-components/mermaid && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/wc/mermaid --emptyOutDir
cd frontend/web-components/markdown && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/wc/markdown --emptyOutDir
cd frontend/web-components/model-gallery && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/wc/model-gallery --emptyOutDir
cd frontend/web-components/counter-persist && rm -rf node_modules && npm install && npm run build -- --outDir ../../../static/wc/counter-persist --emptyOutDir
cd frontend/applications/main && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/app/main --emptyOutDir
cd frontend/applications/iframe-demo && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/app/iframe-demo --emptyOutDir
cd frontend/web-components/reaction-bar && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/wc/reaction-bar --emptyOutDir
cd frontend/web-components/websocket-log && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/wc/websocket-log --emptyOutDir
cd frontend/web-components/chart-circle && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/wc/chart-circle --emptyOutDir
cd frontend/web-components/mermaid && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/wc/mermaid --emptyOutDir
cd frontend/web-components/markdown && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/wc/markdown --emptyOutDir
cd frontend/web-components/model-gallery && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/wc/model-gallery --emptyOutDir
cd frontend/web-components/counter-persist && rm -rf node_modules package-lock.json && npm install && npm run build -- --outDir ../../../static/wc/counter-persist --emptyOutDir

dev:
cd frontend/applications/main && npm run dev
Expand Down
90 changes: 90 additions & 0 deletions e2e/theming.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* End-to-end tests for the facade theming endpoints:
* GET /api/public/facade/variables.css — CSS variables as a stylesheet
* GET /api/public/facade/config — full config with resolved theming
*
* Tests verify that `fs://` references in the css_variables and custom_css
* requirements are resolved to actual file content at request time, using the
* `content_fs` filesystem entry.
*
* Config is declarative in src/app/deps/_index.yaml (the `facade` dependency):
* - name: content_fs value: app:app_fs
* - name: custom_css value: "fs://custom-css.facade.css"
* - name: css_variables value: "fs://css-variables.facade.json"
* The fixture files live in ./static alongside login.html (served at /app), so
* content_fs (app:app_fs → ./static) resolves them — and the same files could
* also be <link>ed by a static page (login.html doesn't today, but can).
*
* `fs://`, not `file://`: the wippy loader interpolates `file://` at LOAD time
* (reads it relative to the _index.yaml dir), so a `file://` written in a YAML
* requirement param never reaches the facade. Just start wippy normally:
* ./wippy.exe run -c -o app:gateway:addr=:8086 \
* -o wippy.facade:fe_facade_url:default=http://localhost:5173
*/
import { expect, test } from '@playwright/test'
import { loginAsAdmin } from './helpers/login'

const CSS_VARS_PATH = '/api/public/facade/variables.css'
const CONFIG_PATH = '/api/public/facade/config'

test.describe('facade theming: fs:// resolution', () => {
test.beforeEach(async ({ page }) => {
await loginAsAdmin(page)
})

test('GET /facade/variables.css generates CSS from file-backed css-variables.facade.json', async ({ page }) => {
const res = await page.request.get(CSS_VARS_PATH)
expect(res.status()).toBe(200)
expect(res.headers()['content-type']).toContain('text/css')

const css = await res.text()

// Root block generated from flat string keys
expect(css).toContain(':root')
expect(css).toContain('--e2e-primary: #e2e001;')
expect(css).toContain('--e2e-secondary: #e2e002;')

// @media dark block from nested @dark object
expect(css).toContain('prefers-color-scheme: dark')
expect(css).toContain('--e2e-primary: #e2e003;')
})

test('GET /facade/variables.css carries Cache-Control header', async ({ page }) => {
const res = await page.request.get(CSS_VARS_PATH)
expect(res.status()).toBe(200)
expect(res.headers()['cache-control']).toContain('public')
expect(res.headers()['cache-control']).toContain('max-age=3600')
})

test('GET /facade/config resolves fs:// custom_css to file content', async ({ page }) => {
const res = await page.request.get(CONFIG_PATH)
expect(res.status()).toBe(200)

const config = await res.json()
const customCSS: string | undefined = config?.theming?.global?.customCSS

// Must be file content, not the raw "fs://custom-css.facade.css" string
expect(customCSS).toBeTruthy()
expect(customCSS).not.toContain('fs://')
// Must contain marker text from custom-css.facade.css
expect(customCSS).toContain('E2E Test Font')
})

test('GET /facade/config resolves fs:// css_variables to parsed JSON object', async ({ page }) => {
const res = await page.request.get(CONFIG_PATH)
expect(res.status()).toBe(200)

const config = await res.json()
const cssVars = config?.theming?.global?.cssVariables

// Must be the decoded JSON object, not a raw string
expect(cssVars).toBeTruthy()
expect(typeof cssVars).toBe('object')
expect(cssVars['--e2e-primary']).toBe('#e2e001')
expect(cssVars['--e2e-secondary']).toBe('#e2e002')

// @dark nested object must be preserved through JSON decode
expect(cssVars['@dark']).toBeTruthy()
expect(cssVars['@dark']['--e2e-primary']).toBe('#e2e003')
})
})
198 changes: 0 additions & 198 deletions e2e/warn-suppressor.spec.ts

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/applications/iframe-demo/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}
</script>
<script
src="https://web-host.wippy.ai/webcomponents-1.0.32/dev-proxy.js"
src="https://web-host.wippy.ai/webcomponents-1.0.36/dev-proxy.js"
data-role="@wippy/scripts"
></script>
</head>
Expand Down
Loading