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
Binary file modified img/screenshots/admin-catalog-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/screenshots/admin-catalog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/screenshots/personal-settings-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/screenshots/personal-settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/screenshots/user-management-dialog-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/screenshots/user-management-dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/screenshots/workflow-notify-admins-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/screenshots/workflow-notify-admins.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
106 changes: 24 additions & 82 deletions playwright/generate-screenshots.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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))
Expand Down Expand Up @@ -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 })
Expand All @@ -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')
Expand Down Expand Up @@ -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' })

Expand Down
38 changes: 38 additions & 0 deletions src/tests/utils/pedroPotiPersona.spec.ts
Original file line number Diff line number Diff line change
@@ -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')
})
})
93 changes: 93 additions & 0 deletions src/utils/pedroPotiPersona.js
Original file line number Diff line number Diff line change
@@ -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' },
},
],
}
Loading