Skip to content

Commit 1518931

Browse files
committed
chore: set up authenticated tests and refactor template loading
fix issue with month badge in light theme
1 parent d9a2f57 commit 1518931

42 files changed

Lines changed: 440 additions & 169 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
# Frontend configuration for during development
22
# Backend host, usually /api if hosted locally and used via proxy
3-
# If omitted the app will be available in demo mode only
3+
# If omitted and OCULAR_HYBRID_MODE is not set to true, authentication will be required to use the app
44
OCULAR_GENESIS_HOST=/api
55

6+
# If set to true it will be possible to use the app without authentication
7+
# If left empty authentication will be required
8+
OCULAR_HYBRID_MODE=
9+
610
# Optional, pre-filled login credentials for local testing
711
OCULAR_TEST_USERNAME=admin
812
OCULAR_TEST_PASSWORD=hgEiPCZP

.env.genesis

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
GENESIS_PORT=8080
44
GENESIS_BASE_URL=/
55
GENESIS_DB_PATH=.data
6-
GENESIS_CREATE_USERS=admin!:hgEiPCZP,test:EczUR8dn
7-
GENESIS_AUTHORIZED_URIS=localhost:3000
6+
GENESIS_CREATE_USERS=admin!:hgEiPCZP
87
GENESIS_JWT_SECRET=84d62c48dd30ca7caf6561252c5bd919}
98
GENESIS_JWT_TOKEN_EXPIRATION=120000
109
GENESIS_USERNAME_PATTERN=^[\w]{0,32}$
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: 'Setup Repository'
2+
description: 'Set up the repository with pnpm and Node.js'
3+
inputs:
4+
pnpm-version:
5+
description: 'Version of pnpm to use'
6+
default: 10.27.0
7+
node-version:
8+
description: 'Version of Node.js to use'
9+
default: 24.12.0
10+
runs:
11+
using: 'composite'
12+
steps:
13+
- name: Setup pnpm
14+
uses: pnpm/action-setup@v3
15+
with:
16+
version: ${{ inputs.pnpm-version }}
17+
18+
- name: Set up Node.js
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: ${{ inputs.node-version }}
22+
cache: 'pnpm'
23+
24+
- name: Install dependencies
25+
shell: bash
26+
run: pnpm install --frozen-lockfile
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: 'Wait for Healthcheck'
2+
description: 'Wait for a service to be healthy by checking its healthcheck endpoint'
3+
inputs:
4+
host:
5+
description: 'The host of the backend'
6+
required: true
7+
endpoint:
8+
description: 'The healthcheck endpoint'
9+
required: true
10+
default: 'health'
11+
expected_code:
12+
description: 'The expected HTTP status code'
13+
default: '200'
14+
timeout:
15+
description: 'The timeout in seconds'
16+
default: '30'
17+
runs:
18+
using: 'composite'
19+
steps:
20+
- name: Wait for service to be healthy
21+
shell: bash
22+
run: |
23+
counter=0
24+
while [ "$(curl -s -o /dev/null -w '%{http_code}' http://${{ inputs.host }}/${{ inputs.endpoint }})" -ne ${{ inputs.expected_code }} ]; do
25+
counter=$((counter+1))
26+
if [ $counter -ge ${{ inputs.timeout }} ]; then
27+
echo "Service failed to start within ${{ inputs.timeout }} seconds."
28+
exit 1
29+
fi
30+
echo "Waiting for service to start..."
31+
sleep 1
32+
done
33+
echo "Service is healthy"

.github/workflows/main.yml

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,18 @@ permissions:
1414
env:
1515
IMAGE_REGISTRY: ghcr.io
1616
IMAGE_NAME: ${{ github.repository }}
17-
PNPM_VERSION: 10.27.0
18-
NODE_VERSION: 24.12.0
1917
HUSKY: 0
2018

2119
jobs:
2220
test:
23-
name: Build apps and run tests
21+
name: Run unit, lint and e2e tests
2422
runs-on: ubuntu-latest
2523
steps:
2624
- name: Checkout repository
2725
uses: actions/checkout@v4
2826

29-
- name: Setup pnpm
30-
uses: pnpm/action-setup@v3
31-
with:
32-
version: ${{ env.PNPM_VERSION }}
33-
34-
- name: Set up Node.js
35-
uses: actions/setup-node@v4
36-
with:
37-
node-version: ${{ env.NODE_VERSION }}
38-
cache: 'pnpm'
39-
40-
- name: Install dependencies
41-
run: pnpm install --frozen-lockfile
27+
- name: Setup repository
28+
uses: ./.github/workflows/actions/setup-repository
4229

4330
- name: Setup ESLint cache
4431
uses: actions/cache@v4
@@ -52,18 +39,53 @@ jobs:
5239
- name: Run unit tests
5340
run: pnpm test
5441

55-
- name: Build app
42+
- name: Build testing app
5643
run: pnpm build
44+
env:
45+
OCULAR_GENESIS_HOST: /api
46+
OCULAR_HYBRID_MODE: true
5747

58-
- name: Build docs
59-
run: pnpm docs:build
48+
- name: Start genesis and ocular
49+
run: |
50+
docker pull ghcr.io/simonwep/genesis:latest
51+
docker run -p 8080:8080 -v "./.data:/app/.data" --env-file .env.genesis ghcr.io/simonwep/genesis:latest start &
52+
pnpm vite preview &
53+
54+
- name: Wait for genesis to be healthy
55+
uses: ./.github/workflows/actions/wait-for-health-check
56+
with:
57+
host: localhost:8080
58+
59+
- name: Wait for ocular to be healthy
60+
uses: ./.github/workflows/actions/wait-for-health-check
61+
with:
62+
host: localhost:3000
63+
endpoint: /dashboard
6064

6165
- name: Install playwright browsers
6266
run: pnpm exec playwright install --with-deps firefox
6367

6468
- name: Run e2e tests
6569
run: pnpm test:e2e
6670

71+
- name: Upload test results
72+
uses: actions/upload-artifact@v4
73+
if: ${{ failure() }}
74+
with:
75+
name: test-results
76+
path: test-results/
77+
retention-days: 7
78+
79+
build:
80+
name: Run demo and docs build
81+
runs-on: ubuntu-latest
82+
steps:
83+
- name: Checkout repository
84+
uses: actions/checkout@v4
85+
86+
- name: Setup repository
87+
uses: ./.github/workflows/actions/setup-repository
88+
6789
- name: Set outputs
6890
id: vars
6991
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
@@ -75,6 +97,9 @@ jobs:
7597
OCULAR_BUILD_SHA: ${{ steps.vars.outputs.sha_short }}
7698
OCULAR_BASE_URL: /ocular/demo/
7799

100+
- name: Build docs
101+
run: pnpm docs:build
102+
78103
- name: Upload app build
79104
uses: actions/upload-artifact@v4
80105
if: github.ref == 'refs/heads/main'
@@ -91,18 +116,10 @@ jobs:
91116
path: docs/.vitepress/dist
92117
retention-days: 1
93118

94-
- name: Upload test results
95-
uses: actions/upload-artifact@v4
96-
if: ${{ failure() }}
97-
with:
98-
name: test-results
99-
path: test-results/
100-
retention-days: 7
101-
102119
publish_docs:
103120
if: github.ref == 'refs/heads/main'
104121
name: Publish docs
105-
needs: test
122+
needs: [build, test]
106123
runs-on: ubuntu-latest
107124
permissions:
108125
pages: write
@@ -142,7 +159,7 @@ jobs:
142159
publish_docker:
143160
if: startsWith(github.event.ref, 'refs/tags/v')
144161
name: Build and publish docker image
145-
needs: test
162+
needs: [build, test]
146163
runs-on: ubuntu-latest
147164
permissions:
148165
contents: read

playwright.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ export default defineConfig({
2222
webServer: {
2323
command: 'pnpm preview',
2424
url: 'http://localhost:3000',
25-
timeout: 120 * 1000,
26-
reuseExistingServer: !process.env.CI
25+
timeout: 30 * 1000,
26+
reuseExistingServer: true
2727
},
2828
use: {
2929
baseURL: 'http://localhost:3000',

src/app/App.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,19 @@ import LoadingScreen from '@components/misc/loading-screen/LoadingScreen.vue';
3131
import { useAppElement } from '@composables/app-element/useAppElement.ts';
3232
import { useAppSize } from '@composables/app-size/useAppSize.ts';
3333
import { useShowWinterFeatures } from '@composables/winter-features/useShowWinterFeatures.ts';
34-
import { useStorage } from '@storage/index';
3534
import { useSettingsStore } from '@store/settings';
36-
import { useTemplateData } from '@store/state/template/useTemplateData.ts';
35+
import { useDemoData } from '@store/state/template/useDemoData.ts';
36+
import { useStorage } from '@store/storage/useStorage.ts';
3737
import { useLocalStorage, usePreferredReducedMotion } from '@vueuse/core';
3838
import { nextTick, onMounted, watch } from 'vue';
3939
import { useI18n } from 'vue-i18n';
4040
import { useRouter } from 'vue-router';
4141
42+
const { OCULAR_GENESIS_HOST, OCULAR_HYBRID_MODE } = import.meta.env;
43+
4244
const { status } = useStorage();
4345
const { state: settings } = useSettingsStore();
44-
const { loadTemplateData } = useTemplateData();
46+
const { loadDemoData } = useDemoData();
4547
const { t } = useI18n();
4648
const showWinterFeatures = useShowWinterFeatures();
4749
const router = useRouter();
@@ -92,10 +94,8 @@ watch(router.currentRoute, (route) => {
9294
});
9395
9496
onMounted(() => {
95-
if (!import.meta.env.OCULAR_GENESIS_HOST && location.hash === '#demo') {
96-
loadTemplateData('demo');
97-
} else {
98-
loadTemplateData('template');
97+
if ((!OCULAR_GENESIS_HOST || OCULAR_HYBRID_MODE) && location.hash === '#demo') {
98+
loadDemoData();
9999
}
100100
});
101101
</script>

src/app/components/base/alert/Alert.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<p :class="[$style.alert, classes]">
2+
<p :data-testid="props.testId" :class="[$style.alert, classes]">
33
<component :is="mapping[type][1]" :class="$style.icon" />
44
<span>{{ text }}</span>
55
</p>
@@ -15,6 +15,7 @@ import type { Component } from 'vue';
1515
1616
const props = defineProps<{
1717
class?: ClassNames;
18+
testId?: string;
1819
text: string;
1920
type: AlertType;
2021
}>();

src/app/components/base/button/Button.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
:class="classes"
55
:data-testid="testId"
66
:disabled="disabled"
7+
v-bind="dataAttributes"
78
:type="type"
89
@click="emit('click', $event)"
910
>
@@ -38,6 +39,7 @@ const props = withDefaults(
3839
rounded?: boolean;
3940
disabled?: boolean;
4041
testId?: string;
42+
data?: Record<string, string>;
4143
}>(),
4244
{
4345
color: 'primary',
@@ -51,6 +53,11 @@ const props = withDefaults(
5153
5254
const styles = useCssModule();
5355
const theme = useThemeStyles(() => props.color);
56+
57+
const dataAttributes = computed(() =>
58+
props.data ? Object.fromEntries(Object.entries(props.data).map(([key, value]) => [`data-${key}`, value])) : {}
59+
);
60+
5461
const classes = computed(() => [
5562
styles.button,
5663
styles[props.size],
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export interface CellMenuAction {
2+
id?: string;
23
label: string;
34
handle: () => void | false; // Return false to prevent menu from closing
45
}

0 commit comments

Comments
 (0)