Browse Source

fix logic for share link

Yuki Takei 1 month ago
parent
commit
3379c3ea58

+ 75 - 0
apps/app/src/states/page/use-fetch-current-page.spec.tsx

@@ -26,6 +26,7 @@ import {
   pageLoadingAtom,
   pageNotFoundAtom,
   remoteRevisionBodyAtom,
+  shareLinkIdAtom,
 } from '~/states/page/internal-atoms';
 import { useSWRxPageInfo } from '~/stores/page';
 
@@ -1045,4 +1046,78 @@ describe('useFetchCurrentPage - Integration Test', () => {
       expect(store.get(currentPageEntityIdAtom)).toBe('pageId123');
     });
   });
+
+  it('should use currentPageId when shareLinkId is present instead of path from router', async () => {
+    // Arrange: Simulate share link page where SSR is skipped and CSR fetch is triggered
+    // shareLinkIdAtom is hydrated from SSR props, currentPageEntityIdAtom is also hydrated
+    const shareLinkId = '65d4e0a0f7b7b2e5a8652e86';
+    const pageId = '58a4569921a8424d00a1aa0e';
+    store.set(shareLinkIdAtom, shareLinkId);
+    store.set(currentPageEntityIdAtom, pageId);
+
+    const pageData = createPageDataMock(
+      pageId,
+      '/actual/wiki/path',
+      'share link page content that is very long',
+    );
+    mockedApiv3Get.mockResolvedValue(mockApiResponse(pageData));
+
+    // Act: fetchCurrentPage is called with router.asPath = /share/<shareLinkId>
+    // This simulates what useInitialCsrFetch does when SSR is skipped
+    const { result } = renderHookWithProvider();
+    await act(async () => {
+      await result.current.fetchCurrentPage({
+        path: `/share/${shareLinkId}`,
+        force: true,
+      });
+    });
+
+    // Assert: API should be called with pageId (not path=/share/...) and shareLinkId
+    await waitFor(() => {
+      expect(mockedApiv3Get).toHaveBeenCalledWith(
+        '/page',
+        expect.objectContaining({
+          pageId,
+          shareLinkId,
+        }),
+      );
+      // path should NOT be sent
+      expect(mockedApiv3Get).toHaveBeenCalledWith(
+        '/page',
+        expect.not.objectContaining({ path: expect.anything() }),
+      );
+      expect(store.get(currentPageEntityIdAtom)).toBe(pageId);
+    });
+  });
+
+  it('should fall through to existing logic when shareLinkId is present but currentPageId is null', async () => {
+    // Arrange: shareLinkId is set but currentPageEntityIdAtom is not
+    const shareLinkId = '65d4e0a0f7b7b2e5a8652e86';
+    store.set(shareLinkIdAtom, shareLinkId);
+    // currentPageEntityIdAtom is NOT set (undefined)
+
+    const pageData = createPageDataMock(
+      'somePageId',
+      '/share/some-path',
+      'content',
+    );
+    mockedApiv3Get.mockResolvedValue(mockApiResponse(pageData));
+
+    // Act: fetchCurrentPage called with a path
+    const { result } = renderHookWithProvider();
+    await act(async () => {
+      await result.current.fetchCurrentPage({ path: '/some/path' });
+    });
+
+    // Assert: Falls through to path-based logic since currentPageId is null
+    await waitFor(() => {
+      expect(mockedApiv3Get).toHaveBeenCalledWith(
+        '/page',
+        expect.objectContaining({
+          path: '/some/path',
+          shareLinkId,
+        }),
+      );
+    });
+  });
 });

+ 8 - 3
apps/app/src/states/page/use-fetch-current-page.ts

@@ -136,23 +136,28 @@ const buildApiParams = ({
     shareLinkId?: string;
   } = {};
 
-  if (shareLinkId != null) {
+  if (shareLinkId != null && shareLinkId.length > 0) {
     params.shareLinkId = shareLinkId;
   }
   if (revisionId != null) {
     params.revisionId = revisionId;
   }
 
-  // priority A: pageId > permalink > path
+  // priority A: fetchPageArgs.pageId
   if (fetchPageArgs?.pageId != null) {
     params.pageId = fetchPageArgs.pageId;
+  }
+  // priority B: currentPageId for share link (required by certifySharedPage middleware)
+  else if (shareLinkId != null && currentPageId != null) {
+    params.pageId = currentPageId;
   } else if (decodedPathname != null) {
+    // priority C: permalink > path
     if (isPermalink(decodedPathname)) {
       params.pageId = removeHeadingSlash(decodedPathname);
     } else {
       params.path = decodedPathname;
     }
-    // priority B: currentPageId > permalink(by location) > path(by location)
+    // priority D: currentPageId > permalink(by location) > path(by location)
   } else if (currentPageId != null) {
     params.pageId = currentPageId;
   } else if (isClient()) {