diff --git a/@fiction/admin/test/emailVerify.uiux.test.ts b/@fiction/admin/test/emailVerify.uiux.test.ts index 101980051..1ecaba1f5 100644 --- a/@fiction/admin/test/emailVerify.uiux.test.ts +++ b/@fiction/admin/test/emailVerify.uiux.test.ts @@ -35,21 +35,21 @@ describe('email actions', async () => { { "actionId": "verifyEmail", "appName": "Test Fiction App", - "callbackUrl": "http://localhost:15963/__transaction/verify-email?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic3Vic2NyaWJlciIsInVzZXJJZCI6InVzcjY2ZjIyZmQ3ZjhhMzk1MGNhODUwNzc4NyIsImVtYWlsIjoiYXJwb3dlcnMrNTc4OTU5Mzk4NEBnbWFpbC5jb20iLCJ2ZXJpZnlFbWFpbCI6dHJ1ZSwiaWF0IjoxNzI3MTQ3OTkxLCJleHAiOjE3MjczMjA3OTF9.LZ3tYBz1rOFjhlMfccuEUreL1qFhnJb7u4uxZlwIVEI&code=795601&email=arpowers%2B5789593984%40gmail.com&userId=usr66f22fd7f8a3950ca8507787", - "code": "795601", - "email": "arpowers+5789593984@gmail.com", - "fullName": "Marcos Gleichner III", - "originUrl": "http://localhost:15963", + "callbackUrl": "http://localhost:24773/__transaction/verify-email?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic3Vic2NyaWJlciIsInVzZXJJZCI6InVzcjY2ZjI0OGU0Zjg5MDEzMGQ5ZjA5M2Y4ZSIsImVtYWlsIjoiYXJwb3dlcnMrMzE4OTkxNDQ4MUBnbWFpbC5jb20iLCJ2ZXJpZnlFbWFpbCI6dHJ1ZSwiaWF0IjoxNzI3MTU0NDA0LCJleHAiOjE3MjczMjcyMDR9.Mq6RT1YRdtdDwbwPCfSR_TtPBaPCMaObbkS-i3sCHm4&code=536619&email=arpowers%2B3189914481%40gmail.com&userId=usr66f248e4f890130d9f093f8e", + "code": "536619", + "email": "arpowers+3189914481@gmail.com", + "fullName": "Traci Torphy", + "originUrl": "http://localhost:24773", "queryVars": { - "code": "795601", - "email": "arpowers+5789593984@gmail.com", - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic3Vic2NyaWJlciIsInVzZXJJZCI6InVzcjY2ZjIyZmQ3ZjhhMzk1MGNhODUwNzc4NyIsImVtYWlsIjoiYXJwb3dlcnMrNTc4OTU5Mzk4NEBnbWFpbC5jb20iLCJ2ZXJpZnlFbWFpbCI6dHJ1ZSwiaWF0IjoxNzI3MTQ3OTkxLCJleHAiOjE3MjczMjA3OTF9.LZ3tYBz1rOFjhlMfccuEUreL1qFhnJb7u4uxZlwIVEI", - "userId": "usr66f22fd7f8a3950ca8507787", + "code": "536619", + "email": "arpowers+3189914481@gmail.com", + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic3Vic2NyaWJlciIsInVzZXJJZCI6InVzcjY2ZjI0OGU0Zjg5MDEzMGQ5ZjA5M2Y4ZSIsImVtYWlsIjoiYXJwb3dlcnMrMzE4OTkxNDQ4MUBnbWFpbC5jb20iLCJ2ZXJpZnlFbWFpbCI6dHJ1ZSwiaWF0IjoxNzI3MTU0NDA0LCJleHAiOjE3MjczMjcyMDR9.Mq6RT1YRdtdDwbwPCfSR_TtPBaPCMaObbkS-i3sCHm4", + "userId": "usr66f248e4f890130d9f093f8e", }, "redirect": "", - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic3Vic2NyaWJlciIsInVzZXJJZCI6InVzcjY2ZjIyZmQ3ZjhhMzk1MGNhODUwNzc4NyIsImVtYWlsIjoiYXJwb3dlcnMrNTc4OTU5Mzk4NEBnbWFpbC5jb20iLCJ2ZXJpZnlFbWFpbCI6dHJ1ZSwiaWF0IjoxNzI3MTQ3OTkxLCJleHAiOjE3MjczMjA3OTF9.LZ3tYBz1rOFjhlMfccuEUreL1qFhnJb7u4uxZlwIVEI", - "unsubscribeUrl": "http://localhost:15963/__transaction/unsubscribe", - "userId": "usr66f22fd7f8a3950ca8507787", + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic3Vic2NyaWJlciIsInVzZXJJZCI6InVzcjY2ZjI0OGU0Zjg5MDEzMGQ5ZjA5M2Y4ZSIsImVtYWlsIjoiYXJwb3dlcnMrMzE4OTkxNDQ4MUBnbWFpbC5jb20iLCJ2ZXJpZnlFbWFpbCI6dHJ1ZSwiaWF0IjoxNzI3MTU0NDA0LCJleHAiOjE3MjczMjcyMDR9.Mq6RT1YRdtdDwbwPCfSR_TtPBaPCMaObbkS-i3sCHm4", + "unsubscribeUrl": "http://localhost:24773/__transaction/unsubscribe", + "userId": "usr66f248e4f890130d9f093f8e", "username": "", } `) diff --git a/@fiction/cards/cinema/index.ts b/@fiction/cards/cinema/index.ts index b6e464698..a2d7a1d20 100644 --- a/@fiction/cards/cinema/index.ts +++ b/@fiction/cards/cinema/index.ts @@ -97,13 +97,7 @@ const options: InputOption[] = [ new InputOption({ key: 'subHeader', label: 'Sub Header', input: 'InputText' }), new InputOption({ key: 'superHeader', label: 'Super Header', input: 'InputText' }), new InputOption({ key: 'media', label: 'Media', input: 'InputMedia', props: { formats: { url: true, image: true, video: true } } }), - new InputOption({ key: 'actions', label: 'Actions', input: 'InputList', options: [ - new InputOption({ key: 'name', label: 'Name', input: 'InputText' }), - new InputOption({ key: 'href', label: 'Href', input: 'InputText' }), - new InputOption({ key: 'btn', label: 'Button', input: 'InputSelect', props: { options: ['outline', 'minimal'] } }), - new InputOption({ key: 'icon', label: 'Icon (Left)', input: 'InputIcon', description: 'Use format i-tabler-[icon], check docs for info' }), - new InputOption({ key: 'iconAfter', label: 'Icon (Right)', input: 'InputIcon', description: 'Use format i-tabler-[icon], check docs for info' }), - ] }), + new InputOption({ key: 'actions', input: 'InputActions', label: 'Buttons' }), ], }), new InputOption({ key: 'autoSlide', label: 'Auto Change Slide (12 Seconds)', input: 'InputToggle' }), diff --git a/@fiction/core/plugin-app/plugin-render.ts b/@fiction/core/plugin-app/plugin-render.ts index 8d280e7dc..bc656a289 100644 --- a/@fiction/core/plugin-app/plugin-render.ts +++ b/@fiction/core/plugin-app/plugin-render.ts @@ -79,7 +79,7 @@ export class FictionRender extends FictionPlugin { { appType: 'custom', server: { middlewareMode: true }, - optimizeDeps: { holdUntilCrawlEnd: true }, + // optimizeDeps: { holdUntilCrawlEnd: true }, }, ]) diff --git a/@fiction/core/test-utils/buildTest.ts b/@fiction/core/test-utils/buildTest.ts index 2a023663a..7fd163bac 100644 --- a/@fiction/core/test-utils/buildTest.ts +++ b/@fiction/core/test-utils/buildTest.ts @@ -145,35 +145,38 @@ export async function createTestServer(params: { }, } } - -class PlaywrightLogger { +export class PlaywrightLogger { private logger = log.contextLogger('playwright') - errorLogs: string[] = [] + public errorLogs: string[] = [] private currentUrl: string = '' - caller: string - constructor(args: { caller: string }) { - this.caller = args.caller + private readonly caller: string + private page?: Page + + constructor(caller: string) { + this.caller = caller } async setupLogging(page: Page): Promise { + this.page = page page.on('console', this.handleConsoleMessage.bind(this)) page.on('pageerror', this.handlePageError.bind(this)) - page.on('load', () => { - this.currentUrl = page.url() - }) + page.on('load', () => { this.currentUrl = page.url() }) } - cleanup(): void { - + close(): void { + if (this.page) { + this.page.removeListener('console', this.handleConsoleMessage.bind(this)) + this.page.removeListener('pageerror', this.handlePageError.bind(this)) + this.page = undefined + } } private async handleConsoleMessage(message: playwrightTest.ConsoleMessage): Promise { const type = message.type() const text = this.cleanMessage(message.text()) - if (type === 'debug') { - return // Don't log debug messages - } + if (type === 'debug') + return const logData = { url: `${this.caller} -> ${this.currentUrl}`, @@ -205,7 +208,7 @@ class PlaywrightLogger { private handlePageError(error: Error): void { const logData = { url: `${this.caller} -> ${this.currentUrl}`, - stack: error.stack, + stack: this.parseStackTrace(error.stack || ''), } this.logger.error(error.message, { data: logData }) this.errorLogs.push(`[${this.currentUrl}] ${error.message}`) @@ -215,39 +218,29 @@ class PlaywrightLogger { const serialized = await Promise.all(args.map(async (arg) => { try { const value = await arg.jsonValue().catch(() => 'Unable to serialize') - return typeof value === 'object' && value !== null - ? JSON.parse(JSON.stringify(value, this.jsonReplacer)) - : value + return JSON.parse(JSON.stringify(value, this.jsonReplacer)) } catch { return 'Error serializing argument' } })) - return serialized.filter(arg => - typeof arg !== 'string' || !arg.match(/^(color|font-weight|background-color):/), - ).map(arg => typeof arg === 'string' ? this.cleanMessage(arg) : arg) + return serialized.filter(arg => !this.isStyleInfo(arg)) + .map(arg => typeof arg === 'string' ? this.cleanMessage(arg) : arg) } private extractStackTrace(args: any[]): string | null { const stackArg = args.find(arg => typeof arg === 'string' && arg.includes('at ')) - if (stackArg) { - return this.parseStackTrace(stackArg) - } - return null + return stackArg ? this.parseStackTrace(stackArg) : null } private parseStackTrace(stack: string): string { - if (!stack) - return '' - - const lines = stack.split('\n') - return lines + return stack.split('\n') .filter(line => line.includes('/fiction/') && !line.includes('node_modules')) .join('\n') } - private jsonReplacer(key: string, value: any): any { + private jsonReplacer(_key: string, value: any): any { if (value instanceof RegExp) return value.toString() if (typeof value === 'function') @@ -258,26 +251,20 @@ class PlaywrightLogger { } private cleanMessage(message: string): string { - // Remove color and styling information - message = message - .replace(/%c/g, '') - .replace(/(?:color|font-weight|background-color): [^;]+;?\s*/g, '') - .trim() + message = message.replace(/%c/g, '').replace(/(?:color|font-weight|background-color): [^;]+;?\s*/g, '').trim() - // Improve Vue warnings if (message.startsWith('[Vue warn]')) { - const lines = message.split('\n') - const warning = lines[0] - const componentInfo = lines.slice(1) - .filter(line => line.trim() !== '' && !line.includes('at <')) - .join(' ') - return `${warning} ${componentInfo}`.trim() + const [warning, ...componentInfo] = message.split('\n') + return `${warning} ${componentInfo.filter(line => line.trim() !== '' && !line.includes('at <')).join(' ')}`.trim() } - // For other multi-line messages, join them with a space return message.replace(/\n+/g, ' ') } + private isStyleInfo(arg: any): boolean { + return typeof arg === 'string' && /^(color|font-weight|background-color):/.test(arg) + } + getErrorLogs(): string[] { return this.errorLogs } @@ -306,7 +293,7 @@ export async function performActions(args: { const url = new URL(path || '/', `http://localhost:${port}`).toString() - const playwrightLogger = new PlaywrightLogger({ caller }) + const playwrightLogger = new PlaywrightLogger(caller) playwrightLogger.setupLogging(page) @@ -457,6 +444,8 @@ export async function performActions(args: { if (playwrightLogger.errorLogs.length > 0) playwrightLogger.errorLogs.forEach(e => console.error(e)) // expect(errorLogs).toStrictEqual([]) + + playwrightLogger.close() } function getModifiedCommands(commands: CliCommand[]) { diff --git a/@fiction/posts/test/postEditing.debug.test.ts b/@fiction/posts/test/postEditing.debug.test.ts index b4f16c834..a271a8b11 100644 --- a/@fiction/posts/test/postEditing.debug.test.ts +++ b/@fiction/posts/test/postEditing.debug.test.ts @@ -1,5 +1,5 @@ import { isCi } from '@fiction/core' -import { afterAll, describe, it } from 'vitest' +import { describe, it } from 'vitest' import { createPostsUiTestingKit } from './postTestUtils' describe('postEditing', async () => { diff --git a/@fiction/ui/inputs/index.ts b/@fiction/ui/inputs/index.ts index 85881758a..64c0a5d70 100644 --- a/@fiction/ui/inputs/index.ts +++ b/@fiction/ui/inputs/index.ts @@ -9,7 +9,7 @@ type InputEntry = { el: vue.Component, shape?: string[] } export const inputs = { InputProse: { el: def(async () => import('./InputProse.vue')) }, InputActionList: { el: def(async () => import('./InputActionList.vue')) }, - InputActions: { el: def(async () => import('./InputActions.vue')), shape: ['0.design', '0.href', '0.icon', '0.iconAfter', '0.name', '0.size', '0.target', '0.theme'] }, + InputActions: { el: def(async () => import('./InputActions.vue')), shape: ['0.design', '0.href', '0.icon', '0.iconAfter', '0.name', '0.size', '0.target', '0.theme', '0.rounding', '0.disabled', '0.format', '0.loading'] }, InputItems: { el: def(async () => import('./InputItems.vue')) }, InputUsername: { el: def(async () => import('./InputUsername.vue')) }, InputImage: { el: def(async () => import('./InputImage.vue')) },