From 9d78419100d581020b7bb8ff76e1e5a90462e5a1 Mon Sep 17 00:00:00 2001 From: Cesare Naldi Date: Thu, 15 Feb 2024 21:25:41 +0100 Subject: [PATCH] Removes Lensfrens, fixes tests, fix v1 handle redirect --- e2e/fixtures/profiles.ts | 17 ++-- e2e/profiles.spec.ts | 166 ++++++++-------------------------- e2e/publications.spec.ts | 20 +++- manifests/lensfrens.json | 16 ---- manifests/orna.json | 2 +- next.config.js | 2 +- src/data/AppManifestSchema.ts | 2 +- src/data/findProfileApps.ts | 1 - src/data/storage.ts | 1 + 9 files changed, 66 insertions(+), 161 deletions(-) delete mode 100644 manifests/lensfrens.json diff --git a/e2e/fixtures/profiles.ts b/e2e/fixtures/profiles.ts index e916ba9..82bd907 100644 --- a/e2e/fixtures/profiles.ts +++ b/e2e/fixtures/profiles.ts @@ -3,20 +3,15 @@ import { test as base, expect } from "@playwright/test"; import { ProfilePage } from "./ProfilePage"; export const test = base.extend<{ - v1Profile: ProfilePage; - v1ProfileWithSuffix: ProfilePage; - v2Profile: ProfilePage; + lensProfile: ProfilePage; + anyProfile: ProfilePage; }>({ - v1Profile: async ({ page }, use) => { - const profile = new ProfilePage(page, "lensprotocol"); + lensProfile: async ({ page }, use) => { + const profile = new ProfilePage(page, "lens/lens"); await use(profile); }, - v1ProfileWithSuffix: async ({ page }, use) => { - const profile = new ProfilePage(page, "lensprotocol.lens"); - await use(profile); - }, - v2Profile: async ({ page }, use) => { - const profile = new ProfilePage(page, "lens/lensprotocol"); + anyProfile: async ({ page }, use) => { + const profile = new ProfilePage(page, "lens/stani"); await use(profile); }, }); diff --git a/e2e/profiles.spec.ts b/e2e/profiles.spec.ts index 57dada3..ee50071 100644 --- a/e2e/profiles.spec.ts +++ b/e2e/profiles.spec.ts @@ -6,13 +6,13 @@ test.use(devices["Desktop Chrome"]); test.describe("Given a Profile link", async () => { test.describe("When opening it", async () => { - test("Then it should show relevant app options", async ({ v1Profile }) => { - await v1Profile.open(); + test("Then it should show relevant app options", async ({ anyProfile }) => { + await anyProfile.open(); - await expect(v1Profile.options).toHaveText([ + await expect(anyProfile.options).toHaveText([ "Buttrfly", "Hey", - "LensFrens", + "orb", "Orna", "Riff", "Soclly", @@ -22,90 +22,28 @@ test.describe("Given a Profile link", async () => { }); }); -test.describe("Given a v1 Profile link posted on a social media website/app", async () => { - test.describe("When checking Open Graph meta tags", async () => { - test("Then it should render the expected base-line meta tags", async ({ v1Profile }) => { - await v1Profile.open(); - - expect(await v1Profile.extractOpenGraphProperties()).toMatchObject({ - "og:title": `lens/${v1Profile.handle} profile`, - "og:description": "The Social Layer for Web3 🌿", - "og:url": expect.stringContaining(`/u/lens/${v1Profile.handle}`), - "og:site_name": "Lens Share", - "og:type": "profile", - }); - }); - - test("Then it should include the expected Twitter Card meta tags", async ({ v1Profile }) => { - await v1Profile.open(); - - expect(await v1Profile.extractTwitterMetaTags()).toEqual({ - "twitter:card": "summary_large_image", - "twitter:site": "LensProtocol", - "twitter:title": `lens/${v1Profile.handle} profile`, - "twitter:description": "The Social Layer for Web3 🌿", - "twitter:image": expect.any(String), - "twitter:image:type": "image/png", - }); - }); - }); -}); - -test.describe("Given a v1 Profile link with suffix posted on a social media website/app", async () => { - test.describe("When checking Open Graph meta tags", async () => { - test("Then it should render the expected base-line meta tags", async ({ - v1ProfileWithSuffix, - }) => { - await v1ProfileWithSuffix.open(); - - expect(await v1ProfileWithSuffix.extractOpenGraphProperties()).toMatchObject({ - "og:title": `lens/lensprotocol profile`, - "og:description": "The Social Layer for Web3 🌿", - "og:url": expect.stringContaining(`/u/lens/lensprotocol`), - "og:site_name": "Lens Share", - "og:type": "profile", - }); - }); - - test("Then it should include the expected Twitter Card meta tags", async ({ - v1ProfileWithSuffix, - }) => { - await v1ProfileWithSuffix.open(); - - expect(await v1ProfileWithSuffix.extractTwitterMetaTags()).toEqual({ - "twitter:card": "summary_large_image", - "twitter:site": "LensProtocol", - "twitter:title": `lens/lensprotocol profile`, - "twitter:description": "The Social Layer for Web3 🌿", - "twitter:image": expect.any(String), - "twitter:image:type": "image/png", - }); - }); - }); -}); - -test.describe("Given a v2 Profile link posted on a social media website/app", async () => { +test.describe("Given a Profile link posted on a social media website/app", async () => { test.describe("When checking Open Graph meta tags", async () => { - test("Then it should render the expected base-line meta tags", async ({ v2Profile }) => { - await v2Profile.open(); + test("Then it should render the expected base-line meta tags", async ({ lensProfile }) => { + await lensProfile.open(); - expect(await v2Profile.extractOpenGraphProperties()).toMatchObject({ - "og:title": `${v2Profile.handle} profile`, - "og:description": "The Social Layer for Web3 🌿", - "og:url": expect.stringContaining(`/u/${v2Profile.handle}`), + expect(await lensProfile.extractOpenGraphProperties()).toMatchObject({ + "og:title": `${lensProfile.handle} profile`, + "og:description": "onchain social", + "og:url": expect.stringContaining(`/u/${lensProfile.handle}`), "og:site_name": "Lens Share", "og:type": "profile", }); }); - test("Then it should include the expected Twitter Card meta tags", async ({ v2Profile }) => { - await v2Profile.open(); + test("Then it should include the expected Twitter Card meta tags", async ({ lensProfile }) => { + await lensProfile.open(); - expect(await v2Profile.extractTwitterMetaTags()).toEqual({ + expect(await lensProfile.extractTwitterMetaTags()).toEqual({ "twitter:card": "summary_large_image", "twitter:site": "LensProtocol", - "twitter:title": `${v2Profile.handle} profile`, - "twitter:description": "The Social Layer for Web3 🌿", + "twitter:title": `${lensProfile.handle} profile`, + "twitter:description": "onchain social", "twitter:image": expect.any(String), "twitter:image:type": "image/png", }); @@ -116,26 +54,22 @@ test.describe("Given a v2 Profile link posted on a social media website/app", as test.describe("Given a Profile link posted on a social media website/app", async () => { test.describe("When the link includes the `by` attribution param", async () => { test("Then it should mention the originating app in page `title` and Open Graph `site_name` tag", async ({ - v1Profile, + anyProfile, }) => { - await v1Profile.openAsSharedBy("Hey"); + await anyProfile.openAsSharedBy("Hey"); - expect(await v1Profile.getTitle()).toContain("Hey"); - expect(await v1Profile.extractOpenGraphProperties()).toMatchObject({ + expect(await anyProfile.getTitle()).toContain("Hey"); + expect(await anyProfile.extractOpenGraphProperties()).toMatchObject({ "og:site_name": "Hey", }); }); test("Then it should mention the originating app in Twitter Card `site` if a Twitter handle is provided in the app manifest", async ({ - v1Profile, + anyProfile, }) => { - await v1Profile.openAsSharedBy("Hey"); + await anyProfile.openAsSharedBy("Hey"); - expect(await v1Profile.getTitle()).toContain("Hey"); - expect(await v1Profile.extractOpenGraphProperties()).toMatchObject({ - "og:site_name": "Hey", - }); - expect(await v1Profile.extractTwitterMetaTags()).toMatchObject({ + expect(await anyProfile.extractTwitterMetaTags()).toMatchObject({ "twitter:site": "heydotxyz", }); }); @@ -144,13 +78,13 @@ test.describe("Given a Profile link posted on a social media website/app", async test.describe("Given a Profile link with `by` attribution param", async () => { test.describe("When opening it", async () => { - test("Then it should show the specified app first", async ({ v1Profile }) => { - await v1Profile.openAsSharedBy("Hey"); + test("Then it should show the specified app first", async ({ anyProfile }) => { + await anyProfile.openAsSharedBy("Hey"); - await expect(v1Profile.options).toHaveText([ + await expect(anyProfile.options).toHaveText([ "Hey", "Buttrfly", - "LensFrens", + "orb", "Orna", "Riff", "Soclly", @@ -161,55 +95,33 @@ test.describe("Given a Profile link with `by` attribution param", async () => { test.describe("When opening it on a platform not supported by the specified app", async () => { test("Then it should show a message an attribution message before offering other options", async ({ - v1Profile, + anyProfile, }) => { - await v1Profile.openAsSharedBy("phaver"); - - await expect(v1Profile.context).toHaveText("Shared via Phaver."); - }); - }); -}); - -test.describe("Given an opened v1 Profile link", async () => { - test.describe("When submitting an app choice", async () => { - test("Then it should open the publication with the selected app", async ({ v1Profile }) => { - await v1Profile.open(); - const url = await v1Profile.justOnce("Hey"); - - expect(url).toMatch(`https://hey.xyz/u/lens/${v1Profile.handle}`); - }); - }); - - test.describe("When submitting an app choice with 'Remember' checkbox selected", async () => { - test("Then it should use the same app for all future publications", async ({ v1Profile }) => { - await v1Profile.open(); - await v1Profile.remember("Hey"); - - const response = await v1Profile.open(); + await anyProfile.openAsSharedBy("phaver"); - expect(response?.url()).toMatch(`https://hey.xyz/u/lens/${v1Profile.handle}`); + await expect(anyProfile.context).toHaveText("Shared via Phaver."); }); }); }); test.describe("Given an opened v2 Profile link", async () => { test.describe("When submitting an app choice", async () => { - test("Then it should open the publication with the selected app", async ({ v2Profile }) => { - await v2Profile.open(); - const url = await v2Profile.justOnce("Hey"); + test("Then it should open the publication with the selected app", async ({ anyProfile }) => { + await anyProfile.open(); + const url = await anyProfile.justOnce("Hey"); - expect(url).toMatch(`https://hey.xyz/u/${v2Profile.handle}`); + expect(url).toMatch(`https://hey.xyz/u/${anyProfile.handle}`); }); }); test.describe("When submitting an app choice with 'Remember' checkbox selected", async () => { - test("Then it should use the same app for all future publications", async ({ v2Profile }) => { - await v2Profile.open(); - await v2Profile.remember("Hey"); + test("Then it should use the same app for all future publications", async ({ anyProfile }) => { + await anyProfile.open(); + await anyProfile.remember("Hey"); - const response = await v2Profile.open(); + const response = await anyProfile.open(); - expect(response?.url()).toMatch(`https://hey.xyz/u/${v2Profile.handle}`); + expect(response?.url()).toMatch(`https://hey.xyz/u/${anyProfile.handle}`); }); }); }); diff --git a/e2e/publications.spec.ts b/e2e/publications.spec.ts index de2f50d..4611c30 100644 --- a/e2e/publications.spec.ts +++ b/e2e/publications.spec.ts @@ -9,7 +9,7 @@ test.describe("Given a Publication link", async () => { test("Then it should show relevant app options", async ({ imagePost }) => { await imagePost.open(); - await expect(imagePost.options).toHaveText(["Buttrfly", "Hey", "Orna", "Soclly"]); + await expect(imagePost.options).toHaveText(["Buttrfly", "Hey", "orb", "Orna", "Soclly"]); }); }); }); @@ -111,7 +111,14 @@ test.describe("Given a Video Publication link", async () => { }) => { await videoPost.open(); - await expect(videoPost.options).toHaveText(["Buttrfly", "Collectz", "Hey", "Soclly", "Tape"]); + await expect(videoPost.options).toHaveText([ + "Buttrfly", + "Hey", + "orb", + "Orna", + "Soclly", + "Tape", + ]); }); }); }); @@ -121,7 +128,14 @@ test.describe("Given a Publication link with `by` attribution param", async () = test("Then it should show the specified app first", async ({ videoPost }) => { await videoPost.openAsSharedBy("tape"); - await expect(videoPost.options).toHaveText(["Tape", "Buttrfly", "Collectz", "Hey", "Soclly"]); + await expect(videoPost.options).toHaveText([ + "Tape", + "Buttrfly", + "Hey", + "orb", + "Orna", + "Soclly", + ]); }); }); diff --git a/manifests/lensfrens.json b/manifests/lensfrens.json deleted file mode 100644 index 06c17e7..0000000 --- a/manifests/lensfrens.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "appId": "lensfrens", - "name": "LensFrens", - "description": "Simple curated page for your lens profiles.", - "platform": "web", - "icon": { - "url": "/icons/lensfrens.svg", - "background": "#272E29" - }, - "routes": { - "home": "https://www.lensfrens.xyz/", - "profile": { - "url": "https://www.lensfrens.xyz/:handle" - } - } -} diff --git a/manifests/orna.json b/manifests/orna.json index 44f79b1..1216b6b 100644 --- a/manifests/orna.json +++ b/manifests/orna.json @@ -14,7 +14,7 @@ }, "publication": { "url": "https://orna.art/c/:id", - "supports": ["IMAGE", "AUDIO", "VIDEO", "THREED"] + "supports": ["IMAGE", "AUDIO", "VIDEO", "THREE_D"] } }, "twitter": "nftz_me" diff --git a/next.config.js b/next.config.js index 0f58081..75c909b 100644 --- a/next.config.js +++ b/next.config.js @@ -79,7 +79,7 @@ const nextConfig = { }, // v1 to v2 handle redirect { - source: "/u/:handle", + source: "/u/:handle.lens", destination: "/u/lens/:handle", permanent: false, }, diff --git a/src/data/AppManifestSchema.ts b/src/data/AppManifestSchema.ts index c2e63ab..154b5f4 100644 --- a/src/data/AppManifestSchema.ts +++ b/src/data/AppManifestSchema.ts @@ -13,7 +13,7 @@ const AppIdSchema: z.Schema = z }) .min(3) .max(16) - .regex(/^[a-z0-9]+$/i) + .regex(/^[a-z0-9.]+$/i) .transform((value) => value as AppId); const ProfileUrlSchema = z.object( diff --git a/src/data/findProfileApps.ts b/src/data/findProfileApps.ts index 71d4742..c4b9772 100644 --- a/src/data/findProfileApps.ts +++ b/src/data/findProfileApps.ts @@ -24,7 +24,6 @@ export async function findProfileApps( .filter((app) => webOnly(app) && supportsProfileRoute(app)) .sort(withPriorityTo(request.priorityTo)); } - return apps .filter(supportsProfileRoute) .sort(byMobilePlatformFirst) diff --git a/src/data/storage.ts b/src/data/storage.ts index 0f00505..82abf48 100644 --- a/src/data/storage.ts +++ b/src/data/storage.ts @@ -34,6 +34,7 @@ async function readAllManifestFiles(): Promise[]> { return success(manifest); } catch (e) { + console.log(e); assertError(e); return failure(e); }