fix: refactor OG link builder (#17897)
* fix: manually encode special characters * fix test * fix * fix
This commit is contained in:
@@ -55,10 +55,10 @@ test("check SSR and OG - User Event Type", async ({ page, users }) => {
|
||||
expect(canonicalLink).toEqual(`${WEBAPP_URL}/${user.username}/30-min`);
|
||||
// Verify that there is correct URL that would generate the awesome OG image
|
||||
expect(ogImage).toContain(
|
||||
"/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage?type=meeting&title=30%20min"
|
||||
"/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage%3Ftype%3Dmeeting%26title%3D30%2Bmin"
|
||||
);
|
||||
// Verify Organizer Name in the URL
|
||||
expect(ogImage).toContain("meetingProfileName=Test%20User");
|
||||
expect(ogImage).toContain("meetingProfileName%3DTest%2BUser");
|
||||
});
|
||||
|
||||
todo("check SSR and OG - Team Event Type");
|
||||
|
||||
@@ -428,10 +428,10 @@ test.describe("Bookings", () => {
|
||||
expect(canonicalLink).toEqual(`${orgOrigin}${calLink}`);
|
||||
// Verify that there is correct URL that would generate the awesome OG image
|
||||
expect(ogImage).toContain(
|
||||
"/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage?type=meeting&title="
|
||||
"/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage%3Ftype%3Dmeeting%26title%3D"
|
||||
);
|
||||
// Verify Organizer Name in the URL
|
||||
expect(ogImage).toContain("meetingProfileName=Test%20User");
|
||||
expect(ogImage).toContain("meetingProfileName%3DTest%2BUser");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -64,9 +64,10 @@ test.describe("User Avatar", async () => {
|
||||
);
|
||||
// verify objectKey is passed to the OG image
|
||||
// yes, OG image URI encodes at multiple places.. don't want to mess with that.
|
||||
const searchParam = `meetingImage=${encodeURIComponent(`${CAL_URL}/api/avatar/${objectKey}.png`)}`;
|
||||
await expect(page.locator('meta[property="og:image"]')).toHaveAttribute(
|
||||
"content",
|
||||
new RegExp(`meetingImage=${encodeURIComponent(`${CAL_URL}/api/avatar/${objectKey}.png`)}`)
|
||||
new RegExp(encodeURIComponent(searchParam))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+28
-27
@@ -57,17 +57,22 @@ const makeAbsoluteUrl = (url: string) => (/^https?:\/\//.test(url) ? url : `${CA
|
||||
* 5. Dynamic collective (2 persons) http://localhost:3000/api/social/og/image?type=meeting&title=15min&meetingProfileName=Team%20Pro%20Example,%20Pro%20Example&names=Team%20Pro%20Example&names=Pro%20Example&usernames=teampro&usernames=pro
|
||||
*/
|
||||
export const constructMeetingImage = ({ title, users = [], profile }: MeetingImageProps): string => {
|
||||
const url = [
|
||||
`?type=meeting`,
|
||||
`&title=${encodeURIComponent(title)}`,
|
||||
`&meetingProfileName=${encodeURIComponent(profile.name)}`,
|
||||
profile.image && `&meetingImage=${encodeURIComponent(makeAbsoluteUrl(profile.image))}`,
|
||||
`${users.map((user) => `&names=${encodeURIComponent(user.name)}`).join("")}`,
|
||||
`${users.map((user) => `&usernames=${encodeURIComponent(user.username)}`).join("")}`,
|
||||
// Joining a multiline string for readability.
|
||||
].join("");
|
||||
const params = new URLSearchParams({
|
||||
type: "meeting",
|
||||
title,
|
||||
meetingProfileName: profile.name,
|
||||
});
|
||||
|
||||
return url;
|
||||
if (profile.image) {
|
||||
params.set("meetingImage", makeAbsoluteUrl(profile.image));
|
||||
}
|
||||
|
||||
users.forEach((user) => {
|
||||
params.append("names", user.name);
|
||||
params.append("usernames", user.username);
|
||||
});
|
||||
|
||||
return encodeURIComponent(`/api/social/og/image?${params.toString()}`);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -75,26 +80,22 @@ export const constructMeetingImage = ({ title, users = [], profile }: MeetingIma
|
||||
* http://localhost:3000/api/social/og/image?type=app&name=Huddle01&slug=/api/app-store/huddle01video/icon.svg&description=Huddle01%20is%20a%20new%20video%20conferencing%20software%20native%20to%20Web3%20and%20is%20comparable%20to%20a%20decentralized%20version%20of%20Zoom.%20It%20supports%20conversations%20for...
|
||||
*/
|
||||
export const constructAppImage = ({ name, slug, description }: AppImageProps): string => {
|
||||
const url = [
|
||||
`?type=app`,
|
||||
`&name=${encodeURIComponent(name)}`,
|
||||
`&slug=${encodeURIComponent(slug)}`,
|
||||
`&description=${encodeURIComponent(description)}`,
|
||||
// Joining a multiline string for readability.
|
||||
].join("");
|
||||
|
||||
return url;
|
||||
const params = new URLSearchParams({
|
||||
type: "app",
|
||||
name,
|
||||
slug,
|
||||
description,
|
||||
});
|
||||
return encodeURIComponent(`/api/social/og/image?${params.toString()}`);
|
||||
};
|
||||
|
||||
export const constructGenericImage = ({ title, description }: GenericImageProps) => {
|
||||
const url = [
|
||||
`?type=generic`,
|
||||
`&title=${encodeURIComponent(title)}`,
|
||||
`&description=${encodeURIComponent(description)}`,
|
||||
// Joining a multiline string for readability.
|
||||
].join("");
|
||||
|
||||
return url;
|
||||
const params = new URLSearchParams({
|
||||
type: "generic",
|
||||
title,
|
||||
description,
|
||||
});
|
||||
return encodeURIComponent(`/api/social/og/image?${params.toString()}`);
|
||||
};
|
||||
|
||||
const Wrapper = ({ children, variant = "light", rotateBackground }: WrapperProps) => (
|
||||
|
||||
@@ -87,9 +87,7 @@ export const SEO_IMG_DEFAULT = `${CAL_URL}/og-image.png`;
|
||||
// This results in a 80% smaller image 🤯. It is however important that for the query
|
||||
// parameters you pass to the /api/social/og/image endpoint, you wrap them in encodeURIComponent
|
||||
// as well, otherwise the URL won't be valid.
|
||||
export const SEO_IMG_OGIMG = `${CAL_URL}/_next/image?w=1200&q=100&url=${encodeURIComponent(
|
||||
`/api/social/og/image`
|
||||
)}`;
|
||||
export const SEO_IMG_OGIMG = `${CAL_URL}/_next/image?w=1200&q=100&url=`;
|
||||
export const SEO_IMG_OGIMG_VIDEO = `${CAL_URL}/video-og-image.png`;
|
||||
export const IS_STRIPE_ENABLED = !!(
|
||||
process.env.STRIPE_CLIENT_ID &&
|
||||
|
||||
Reference in New Issue
Block a user