diff --git a/img/screenshots/admin-catalog-thumb.png b/img/screenshots/admin-catalog-thumb.png index 33c8e9a..a35520e 100644 Binary files a/img/screenshots/admin-catalog-thumb.png and b/img/screenshots/admin-catalog-thumb.png differ diff --git a/img/screenshots/admin-catalog.png b/img/screenshots/admin-catalog.png index 04def4e..876fa29 100644 Binary files a/img/screenshots/admin-catalog.png and b/img/screenshots/admin-catalog.png differ diff --git a/img/screenshots/personal-settings-thumb.png b/img/screenshots/personal-settings-thumb.png index 6c4c04a..206458a 100644 Binary files a/img/screenshots/personal-settings-thumb.png and b/img/screenshots/personal-settings-thumb.png differ diff --git a/img/screenshots/personal-settings.png b/img/screenshots/personal-settings.png index 1434684..6b60440 100644 Binary files a/img/screenshots/personal-settings.png and b/img/screenshots/personal-settings.png differ diff --git a/img/screenshots/user-management-dialog-thumb.png b/img/screenshots/user-management-dialog-thumb.png index 67b2567..d67aed8 100644 Binary files a/img/screenshots/user-management-dialog-thumb.png and b/img/screenshots/user-management-dialog-thumb.png differ diff --git a/img/screenshots/user-management-dialog.png b/img/screenshots/user-management-dialog.png index 218be8c..b54eb4a 100644 Binary files a/img/screenshots/user-management-dialog.png and b/img/screenshots/user-management-dialog.png differ diff --git a/img/screenshots/workflow-notify-admins-thumb.png b/img/screenshots/workflow-notify-admins-thumb.png index e2640b0..2581075 100644 Binary files a/img/screenshots/workflow-notify-admins-thumb.png and b/img/screenshots/workflow-notify-admins-thumb.png differ diff --git a/img/screenshots/workflow-notify-admins.png b/img/screenshots/workflow-notify-admins.png index 53d1e05..d25a57e 100644 Binary files a/img/screenshots/workflow-notify-admins.png and b/img/screenshots/workflow-notify-admins.png differ diff --git a/playwright/generate-screenshots.mjs b/playwright/generate-screenshots.mjs index e77be3c..ff84a38 100644 --- a/playwright/generate-screenshots.mjs +++ b/playwright/generate-screenshots.mjs @@ -6,6 +6,7 @@ import { mkdir, readFile, rm } from 'node:fs/promises' import { join } from 'node:path' import { spawnSync } from 'node:child_process' import { chromium, request } from '@playwright/test' +import { pedroPotiPersona } from '../src/utils/pedroPotiPersona.js' const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? 'https://localhost' const adminUser = process.env.NEXTCLOUD_ADMIN_USER ?? 'admin' @@ -17,87 +18,8 @@ const demoAvatarPath = 'playwright/fixtures/pedro-poti-avatar.png' const legacyDemoUserIds = ['amina_okafor_demo', 'araci_potira_demo'] -const demoUser = { - id: 'pedro_poti_demo', - password: 'PedroDemoPass123!', - displayName: 'Pedro Poti', - email: 'pedro.poti@example.net', -} - -const showcaseFields = [ - { - fieldKey: 'showcase_support_region', - label: 'Support region', - type: 'text', - adminOnly: false, - userEditable: true, - userVisible: true, - initialVisibility: 'users', - sortOrder: 10, - adminValue: { value: 'Northern Europe', currentVisibility: 'users' }, - demoValue: { value: 'East Africa', currentVisibility: 'users' }, - }, - { - fieldKey: 'showcase_product_specialty', - label: 'Product specialty', - type: 'text', - adminOnly: false, - userEditable: true, - userVisible: true, - initialVisibility: 'public', - sortOrder: 20, - adminValue: { value: 'Contract automation', currentVisibility: 'public' }, - demoValue: { value: 'Identity operations', currentVisibility: 'public' }, - }, - { - fieldKey: 'showcase_customer_segment', - label: 'Customer segment', - type: 'text', - adminOnly: false, - userEditable: true, - userVisible: true, - initialVisibility: 'users', - sortOrder: 30, - adminValue: { value: 'Public sector', currentVisibility: 'users' }, - demoValue: { value: 'Financial services', currentVisibility: 'users' }, - }, - { - fieldKey: 'showcase_escalation_alias', - label: 'Escalation alias', - type: 'text', - adminOnly: false, - userEditable: true, - userVisible: true, - initialVisibility: 'private', - sortOrder: 40, - adminValue: { value: 'north-eu-escalations', currentVisibility: 'private' }, - demoValue: { value: 'east-africa-escalations', currentVisibility: 'private' }, - }, - { - fieldKey: 'showcase_incident_role', - label: 'Incident response role', - type: 'text', - adminOnly: false, - userEditable: true, - userVisible: true, - initialVisibility: 'users', - sortOrder: 50, - adminValue: { value: 'Communications lead', currentVisibility: 'users' }, - demoValue: { value: 'Regional coordinator', currentVisibility: 'users' }, - }, - { - fieldKey: 'showcase_on_call_tier', - label: 'On-call tier', - type: 'number', - adminOnly: true, - userEditable: false, - userVisible: true, - initialVisibility: 'private', - sortOrder: 60, - adminValue: { value: 2, currentVisibility: 'private' }, - demoValue: { value: 1, currentVisibility: 'private' }, - }, -] +const demoUser = pedroPotiPersona.user +const showcaseFields = pedroPotiPersona.showcaseFields const showcaseKeys = new Set(showcaseFields.map((field) => field.fieldKey)) const showcaseLabels = new Set(showcaseFields.map((field) => field.label)) @@ -297,6 +219,25 @@ const hideNonShowcaseDialogFields = async(page) => { }, { labels: [...showcaseLabels], demoUserId: demoUser.id }) } +const fillAccountField = async(page, label, value) => { + const textboxes = page.getByRole('textbox', { name: label, exact: true }) + const input = await textboxes.count() > 0 + ? textboxes.first() + : page.locator(`input[aria-label="${label}"], textarea[aria-label="${label}"]`).first() + await input.waitFor({ state: 'visible', timeout: 60_000 }) + await input.fill(value) + await input.blur() + await page.waitForTimeout(250) +} + +const seedPedroPotiAccountProfile = async(page) => { + for (const field of pedroPotiPersona.accountFields) { + await fillAccountField(page, field.label, field.value) + } + + await page.waitForTimeout(800) +} + const prepareWorkflowScreenshot = async(page) => { await page.goto('./settings/admin/workflow') await page.getByRole('heading', { name: 'Available flows' }).waitFor({ state: 'visible', timeout: 60_000 }) @@ -305,7 +246,7 @@ const prepareWorkflowScreenshot = async(page) => { if (await showMoreButton.count() > 0) { await showMoreButton.click() } - await page.getByRole('heading', { name: 'Create Talk conversation', exact: true }).waitFor({ state: 'visible', timeout: 60_000 }) + await page.getByRole('heading', { name: 'Create Talk conversation', exact: true }).first().waitFor({ state: 'visible', timeout: 60_000 }) await page.evaluate(() => { document.querySelector('header')?.setAttribute('style', 'display:none') @@ -407,6 +348,7 @@ const run = async() => { const personalPage = await demoContext.newPage() await personalPage.goto('./settings/user/personal-info') await personalPage.getByTestId('profile-fields-personal-field-showcase_support_region').waitFor({ state: 'visible', timeout: 60_000 }) + await seedPedroPotiAccountProfile(personalPage) await hideNonShowcasePersonalFields(personalPage) await personalPage.locator('main').screenshot({ path: join(screenshotDir, 'personal-settings.png'), type: 'png' }) diff --git a/src/tests/utils/pedroPotiPersona.spec.ts b/src/tests/utils/pedroPotiPersona.spec.ts new file mode 100644 index 0000000..a5cf882 --- /dev/null +++ b/src/tests/utils/pedroPotiPersona.spec.ts @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2026 LibreCode coop and LibreCode contributors +// SPDX-License-Identifier: AGPL-3.0-or-later + +import { describe, expect, it } from 'vitest' + +import { pedroPotiPersona } from '../../utils/pedroPotiPersona.js' + +describe('pedroPotiPersona', () => { + it('keeps the demo identity and biography aligned with Pedro Poti in English', () => { + expect(pedroPotiPersona.user.displayName).toBe('Pedro Poti') + expect(pedroPotiPersona.user.email).toBe('pedro.poti@example.net') + + const accountFieldByLabel = new Map(pedroPotiPersona.accountFields.map((field) => [field.label, field.value])) + expect(accountFieldByLabel.get('Location')).toBe('Massurepe, Paraiba') + expect(accountFieldByLabel.get('Role')).toBe('Regedor of Paraiba') + expect(accountFieldByLabel.get('Headline')).toContain('Dutch Brazil') + expect(accountFieldByLabel.get('About')).toContain('five years in the Netherlands') + expect(accountFieldByLabel.get('About')).toContain('Reformed faith') + expect(accountFieldByLabel.get('About')).toContain('Paraiba chamber') + }) + + it('replaces generic showcase metadata with persona-specific profile fields', () => { + expect(pedroPotiPersona.showcaseFields.map((field) => field.label)).toEqual([ + 'Territory', + 'Core strength', + 'Community', + 'Letter alias', + 'Leadership role', + 'Council rank', + ]) + + const showcaseValueByKey = new Map(pedroPotiPersona.showcaseFields.map((field) => [field.fieldKey, field.demoValue.value])) + expect(showcaseValueByKey.get('showcase_support_region')).toBe('Captaincy of Paraiba') + expect(showcaseValueByKey.get('showcase_product_specialty')).toBe('Tupi correspondence') + expect(showcaseValueByKey.get('showcase_customer_segment')).toBe('Potiguara communities') + expect(showcaseValueByKey.get('showcase_incident_role')).toBe('Regedor of Paraiba') + }) +}) diff --git a/src/utils/pedroPotiPersona.js b/src/utils/pedroPotiPersona.js new file mode 100644 index 0000000..71b27aa --- /dev/null +++ b/src/utils/pedroPotiPersona.js @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2026 LibreCode coop and LibreCode contributors +// SPDX-License-Identifier: AGPL-3.0-or-later + +export const pedroPotiPersona = { + user: { + id: 'pedro_poti_demo', + password: 'PedroDemoPass123!', + displayName: 'Pedro Poti', + email: 'pedro.poti@example.net', + }, + accountFields: [ + { label: 'Pronouns', value: 'he/him' }, + { label: 'Location', value: 'Massurepe, Paraiba' }, + { label: 'Organisation', value: 'Potiguara people' }, + { label: 'Role', value: 'Regedor of Paraiba' }, + { label: 'Headline', value: 'Potiguara leader and Reformed ally in Dutch Brazil' }, + { label: 'About', value: 'Potiguara leader from Paraiba who spent five years in the Netherlands, learned to read and write, embraced the Reformed faith, and later served as regedor for the Paraiba chamber.' }, + ], + showcaseFields: [ + { + fieldKey: 'showcase_support_region', + label: 'Territory', + type: 'text', + adminOnly: false, + userEditable: true, + userVisible: true, + initialVisibility: 'users', + sortOrder: 10, + adminValue: { value: 'Recife administration', currentVisibility: 'users' }, + demoValue: { value: 'Captaincy of Paraiba', currentVisibility: 'users' }, + }, + { + fieldKey: 'showcase_product_specialty', + label: 'Core strength', + type: 'text', + adminOnly: false, + userEditable: true, + userVisible: true, + initialVisibility: 'public', + sortOrder: 20, + adminValue: { value: 'Field coordination', currentVisibility: 'public' }, + demoValue: { value: 'Tupi correspondence', currentVisibility: 'public' }, + }, + { + fieldKey: 'showcase_customer_segment', + label: 'Community', + type: 'text', + adminOnly: false, + userEditable: true, + userVisible: true, + initialVisibility: 'users', + sortOrder: 30, + adminValue: { value: 'Colonial administration', currentVisibility: 'users' }, + demoValue: { value: 'Potiguara communities', currentVisibility: 'users' }, + }, + { + fieldKey: 'showcase_escalation_alias', + label: 'Letter alias', + type: 'text', + adminOnly: false, + userEditable: true, + userVisible: true, + initialVisibility: 'private', + sortOrder: 40, + adminValue: { value: 'recife-council-ledger', currentVisibility: 'private' }, + demoValue: { value: 'pedro-poti-tupi-letters', currentVisibility: 'private' }, + }, + { + fieldKey: 'showcase_incident_role', + label: 'Leadership role', + type: 'text', + adminOnly: false, + userEditable: true, + userVisible: true, + initialVisibility: 'users', + sortOrder: 50, + adminValue: { value: 'Administrative overseer', currentVisibility: 'users' }, + demoValue: { value: 'Regedor of Paraiba', currentVisibility: 'users' }, + }, + { + fieldKey: 'showcase_on_call_tier', + label: 'Council rank', + type: 'number', + adminOnly: true, + userEditable: false, + userVisible: true, + initialVisibility: 'private', + sortOrder: 60, + adminValue: { value: 2, currentVisibility: 'private' }, + demoValue: { value: 1, currentVisibility: 'private' }, + }, + ], +}