mirror of
https://github.com/documenso/documenso.git
synced 2025-11-23 05:01:54 +10:00
fix: add public profiles tests
This commit is contained in:
@ -18,8 +18,8 @@ tsRestHonoApp
|
||||
.get('/openapi.json', (c) => c.json(OpenAPIV1))
|
||||
.get('/me', async (c) => testCredentialsHandler(c.req.raw));
|
||||
|
||||
// Zapier. Todo: Check methods. Are these get/post/update requests?
|
||||
// Todo: Is there really no validations?
|
||||
// Zapier. Todo: (RR7) Check methods. Are these get/post/update requests?
|
||||
// Todo: (RR7) Is there really no validations?
|
||||
tsRestHonoApp
|
||||
.all('/zapier/list-documents', async (c) => listDocumentsHandler(c.req.raw))
|
||||
.all('/zapier/subscribe', async (c) => subscribeHandler(c.req.raw))
|
||||
|
||||
@ -52,7 +52,7 @@ export const authenticatedMiddleware = <
|
||||
}
|
||||
|
||||
const metadata: ApiRequestMetadata = {
|
||||
requestMetadata: extractRequestMetadata(request), // Todo: Test
|
||||
requestMetadata: extractRequestMetadata(request), // Todo: (RR7) Test
|
||||
source: 'apiV1',
|
||||
auth: 'api',
|
||||
auditUser: {
|
||||
|
||||
144
packages/app-tests/e2e/public-profiles/public-profiles.spec.ts
Normal file
144
packages/app-tests/e2e/public-profiles/public-profiles.spec.ts
Normal file
@ -0,0 +1,144 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
import { seedTeam } from '@documenso/prisma/seed/teams';
|
||||
import { seedDirectTemplate } from '@documenso/prisma/seed/templates';
|
||||
import { seedUser } from '@documenso/prisma/seed/users';
|
||||
|
||||
import { apiSignin } from '../fixtures/authentication';
|
||||
|
||||
test.describe.configure({ mode: 'parallel' });
|
||||
|
||||
test('[PUBLIC_PROFILE]: create profile', async ({ page }) => {
|
||||
const user = await seedUser();
|
||||
|
||||
// Create direct template.
|
||||
const directTemplate = await seedDirectTemplate({
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: '/settings/public-profile',
|
||||
});
|
||||
|
||||
const publicProfileUrl = Date.now().toString();
|
||||
const publicProfileBio = `public-profile-bio`;
|
||||
|
||||
await page.getByRole('textbox', { name: 'Public profile URL' }).click();
|
||||
await page.getByRole('textbox', { name: 'Public profile URL' }).fill(publicProfileUrl);
|
||||
|
||||
await page.getByRole('textbox', { name: 'Bio' }).click();
|
||||
await page.getByRole('textbox', { name: 'Bio' }).fill(publicProfileBio);
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).click();
|
||||
|
||||
await expect(page.getByRole('status').first()).toContainText(
|
||||
'Your public profile has been updated.',
|
||||
);
|
||||
|
||||
// Link direct template to public profile.
|
||||
await page.getByRole('button', { name: 'Link template' }).click();
|
||||
await page.getByRole('cell', { name: directTemplate.title }).click();
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
|
||||
await page.getByRole('textbox', { name: 'Title *' }).fill('public-direct-template-title');
|
||||
await page
|
||||
.getByRole('textbox', { name: 'Description *' })
|
||||
.fill('public-direct-template-description');
|
||||
await page.getByRole('button', { name: 'Update' }).click();
|
||||
|
||||
// Check that public profile is disabled.
|
||||
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/p/${publicProfileUrl}`);
|
||||
await expect(page.locator('body')).toContainText('404 Profile not found');
|
||||
|
||||
// Go back to public profile page.
|
||||
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/settings/public-profile`);
|
||||
await page.getByRole('switch').click();
|
||||
|
||||
// Assert values.
|
||||
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/p/${publicProfileUrl}`);
|
||||
await expect(page.getByRole('main')).toContainText(publicProfileBio);
|
||||
await expect(page.locator('body')).toContainText('public-direct-template-title');
|
||||
await expect(page.locator('body')).toContainText('public-direct-template-description');
|
||||
|
||||
await page.getByRole('link', { name: 'Sign' }).click();
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
await page.getByRole('button', { name: 'Complete' }).click();
|
||||
await page.getByRole('button', { name: 'Sign' }).click();
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Document Signed' })).toBeVisible();
|
||||
await expect(page.getByRole('heading')).toContainText('Document Signed');
|
||||
});
|
||||
|
||||
test('[PUBLIC_PROFILE]: create team profile', async ({ page }) => {
|
||||
const team = await seedTeam({
|
||||
createTeamMembers: 1,
|
||||
});
|
||||
|
||||
const user = team.owner;
|
||||
|
||||
// Create direct template.
|
||||
const directTemplate = await seedDirectTemplate({
|
||||
userId: user.id,
|
||||
teamId: team.id,
|
||||
});
|
||||
|
||||
// Create non team template to make sure you can only see the team one.
|
||||
// Will be indirectly asserted because test should fail when 2 elements appear.
|
||||
await seedDirectTemplate({
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
await apiSignin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: `/t/${team.url}/settings/public-profile`,
|
||||
});
|
||||
|
||||
const publicProfileUrl = team.url;
|
||||
const publicProfileBio = `public-profile-bio`;
|
||||
|
||||
await page.getByRole('textbox', { name: 'Bio' }).click();
|
||||
await page.getByRole('textbox', { name: 'Bio' }).fill(publicProfileBio);
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).click();
|
||||
|
||||
await expect(page.getByRole('status').first()).toContainText(
|
||||
'Your public profile has been updated.',
|
||||
);
|
||||
|
||||
// Link direct template to public profile.
|
||||
await page.getByRole('button', { name: 'Link template' }).click();
|
||||
await page.getByRole('cell', { name: directTemplate.title }).click();
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
|
||||
await page.getByRole('textbox', { name: 'Title *' }).fill('public-direct-template-title');
|
||||
await page
|
||||
.getByRole('textbox', { name: 'Description *' })
|
||||
.fill('public-direct-template-description');
|
||||
await page.getByRole('button', { name: 'Update' }).click();
|
||||
|
||||
// Check that public profile is disabled.
|
||||
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/p/${publicProfileUrl}`);
|
||||
await expect(page.locator('body')).toContainText('404 Profile not found');
|
||||
|
||||
// Go back to public profile page.
|
||||
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${team.url}/settings/public-profile`);
|
||||
await page.getByRole('switch').click();
|
||||
|
||||
// Assert values.
|
||||
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/p/${publicProfileUrl}`);
|
||||
await expect(page.getByRole('main')).toContainText(publicProfileBio);
|
||||
await expect(page.locator('body')).toContainText('public-direct-template-title');
|
||||
await expect(page.locator('body')).toContainText('public-direct-template-description');
|
||||
|
||||
await page.getByRole('link', { name: 'Sign' }).click();
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
await page.getByRole('button', { name: 'Complete' }).click();
|
||||
await page.getByRole('button', { name: 'Sign' }).click();
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Document Signed' })).toBeVisible();
|
||||
await expect(page.getByRole('heading')).toContainText('Document Signed');
|
||||
});
|
||||
@ -30,10 +30,10 @@ const getAuthSecret = () => {
|
||||
export const sessionCookieOptions = {
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite: useSecureCookies ? 'none' : 'lax', // Todo: This feels wrong?
|
||||
sameSite: useSecureCookies ? 'none' : 'lax', // Todo: (RR7) This feels wrong?
|
||||
secure: useSecureCookies,
|
||||
domain: getCookieDomain(),
|
||||
// Todo: Max age for specific auth cookies.
|
||||
// Todo: (RR7) Max age for specific auth cookies.
|
||||
} as const;
|
||||
|
||||
export const extractSessionCookieFromHeaders = (headers: Headers): string | null => {
|
||||
|
||||
@ -38,7 +38,7 @@ export const getOptionalSession = async (
|
||||
};
|
||||
|
||||
/**
|
||||
* Todo: Rethink, this is pretty sketchy.
|
||||
* Todo: (RR7) Rethink, this is pretty sketchy.
|
||||
*/
|
||||
const mapRequestToContextForCookie = (c: Context | Request) => {
|
||||
if (c instanceof Request) {
|
||||
|
||||
@ -144,7 +144,7 @@ export const handleOAuthCallbackUrl = async (options: HandleOAuthCallbackUrlOpti
|
||||
},
|
||||
data: {
|
||||
emailVerified: new Date(),
|
||||
password: null, // Todo: Check this
|
||||
password: null, // Todo: (RR7) Check this
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -182,7 +182,7 @@ export const handleOAuthCallbackUrl = async (options: HandleOAuthCallbackUrlOpti
|
||||
});
|
||||
|
||||
await onCreateUserHook(createdUser).catch((err) => {
|
||||
// Todo: Add logging.
|
||||
// Todo: (RR7) Add logging.
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
|
||||
const csrfCookieToken = await getCsrfCookie(c);
|
||||
|
||||
// Todo: Add logging here.
|
||||
// Todo: (RR7) Add logging here.
|
||||
if (csrfToken !== csrfCookieToken || !csrfCookieToken) {
|
||||
throw new AppError(AuthenticationErrorCode.InvalidRequest, {
|
||||
message: 'Invalid CSRF token',
|
||||
|
||||
@ -51,7 +51,7 @@ export const stripeWebhookHandler = async (req: Request) => {
|
||||
);
|
||||
}
|
||||
|
||||
// Todo: I'm not sure about this.
|
||||
// Todo: (RR7) I'm not sure about this.
|
||||
const clonedReq = req.clone();
|
||||
const rawBody = await clonedReq.arrayBuffer();
|
||||
const body = Buffer.from(rawBody);
|
||||
|
||||
@ -40,7 +40,7 @@ export const useSession = () => {
|
||||
|
||||
return {
|
||||
...context.sessionData,
|
||||
refresh: context.refresh,
|
||||
refreshSession: context.refresh,
|
||||
};
|
||||
};
|
||||
|
||||
@ -68,7 +68,7 @@ export const SessionProvider = ({ children, initialSession }: SessionProviderPro
|
||||
}
|
||||
|
||||
const teams = await trpc.team.getTeams.query().catch(() => {
|
||||
// Todo: Log
|
||||
// Todo: (RR7) Log
|
||||
return [];
|
||||
});
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ export class InngestJobProvider extends BaseJobProvider {
|
||||
// };
|
||||
// }
|
||||
|
||||
// Todo: Do we need to handle the above?
|
||||
// Todo: (RR7) Do we need to handle the above?
|
||||
public getApiHandler() {
|
||||
return async (context: HonoContext) => {
|
||||
const handler = createHonoPagesRoute({
|
||||
|
||||
@ -52,18 +52,18 @@ export const createUser = async ({ name, email, password, signature, url }: Crea
|
||||
data: {
|
||||
name,
|
||||
email: email.toLowerCase(),
|
||||
password: hashedPassword, // Todo: Drop password.
|
||||
password: hashedPassword, // Todo: (RR7) Drop password.
|
||||
signature,
|
||||
url,
|
||||
},
|
||||
});
|
||||
|
||||
// Todo: Migrate to use this after RR7.
|
||||
// Todo: (RR7) Migrate to use this after RR7.
|
||||
// await tx.account.create({
|
||||
// data: {
|
||||
// userId: user.id,
|
||||
// type: 'emailPassword', // Todo
|
||||
// provider: 'DOCUMENSO', // Todo: Enums
|
||||
// type: 'emailPassword', // Todo: (RR7)
|
||||
// provider: 'DOCUMENSO', // Todo: (RR7) Enums
|
||||
// providerAccountId: user.id.toString(),
|
||||
// password: hashedPassword,
|
||||
// },
|
||||
@ -73,7 +73,7 @@ export const createUser = async ({ name, email, password, signature, url }: Crea
|
||||
});
|
||||
|
||||
await onCreateUserHook(user).catch((err) => {
|
||||
// Todo: Add logging.
|
||||
// Todo: (RR7) Add logging.
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ datasource db {
|
||||
directUrl = env("NEXT_PRIVATE_DIRECT_DATABASE_URL")
|
||||
}
|
||||
|
||||
// Todo: Remove after RR7 migration.
|
||||
// Todo: (RR7) Remove after RR7 migration.
|
||||
enum IdentityProvider {
|
||||
DOCUMENSO
|
||||
GOOGLE
|
||||
@ -41,14 +41,14 @@ model User {
|
||||
customerId String? @unique
|
||||
email String @unique
|
||||
emailVerified DateTime?
|
||||
password String? // Todo: Remove after RR7 migration.
|
||||
password String? // Todo: (RR7) Remove after RR7 migration.
|
||||
source String?
|
||||
signature String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
lastSignedIn DateTime @default(now())
|
||||
roles Role[] @default([USER])
|
||||
identityProvider IdentityProvider @default(DOCUMENSO) // Todo: Remove after RR7 migration.
|
||||
identityProvider IdentityProvider @default(DOCUMENSO) // Todo: (RR7) Remove after RR7 migration.
|
||||
avatarImageId String?
|
||||
disabled Boolean @default(false)
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Todo: Not sure if this actually makes it client-only.
|
||||
// Todo: (RR7) Not sure if this actually makes it client-only.
|
||||
import { Suspense, lazy } from 'react';
|
||||
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
Reference in New Issue
Block a user