diff --git a/apps/readest-app/src/__tests__/components/BookDetailView.test.tsx b/apps/readest-app/src/__tests__/components/BookDetailView.test.tsx index da19e583..cedce91e 100644 --- a/apps/readest-app/src/__tests__/components/BookDetailView.test.tsx +++ b/apps/readest-app/src/__tests__/components/BookDetailView.test.tsx @@ -13,7 +13,9 @@ vi.mock('@/store/settingsStore', () => ({ useSettingsStore: () => ({ settings: { metadataSeriesCollapsed: true, - metadataOthersCollapsed: true, + // The "File Path" entry lives under the Metadata section; tests below + // depend on it being expanded by default so the row is in the DOM. + metadataOthersCollapsed: false, metadataDescriptionCollapsed: true, }, }), @@ -100,3 +102,24 @@ describe('BookDetailView delete dropdown layout', () => { expect(menu!.className).toContain('!relative'); }); }); + +describe('BookDetailView file path row', () => { + // book.filePath is only set for in-place imports (and OS-handed paths like + // Android "Open with Readest"). Hash-copy imports leave it undefined, so + // surfacing it lets users tell the two storage modes apart at a glance. + it('shows the actual file path when book.filePath is set', () => { + const filePath = '/Users/me/Library/Books/sample.epub'; + const { getByText } = renderView({ book: makeBook({ filePath }) }); + + expect(getByText('File Path')).toBeTruthy(); + const value = getByText(filePath); + expect(value).toBeTruthy(); + // Long paths must remain hoverable for the full string. + expect(value.getAttribute('title')).toBe(filePath); + }); + + it('omits the file path row for hash-copy books (no filePath)', () => { + const { queryByText } = renderView({ book: makeBook() }); + expect(queryByText('File Path')).toBeNull(); + }); +}); diff --git a/apps/readest-app/src/components/metadata/BookDetailView.tsx b/apps/readest-app/src/components/metadata/BookDetailView.tsx index e26c9cab..87062dae 100644 --- a/apps/readest-app/src/components/metadata/BookDetailView.tsx +++ b/apps/readest-app/src/components/metadata/BookDetailView.tsx @@ -222,6 +222,21 @@ const BookDetailView: React.FC = ({ {metadata?.identifier || _('Unknown')}

+ {/* + Only books imported in-place (or files opened directly via the + OS, e.g. Android "Open with Readest") keep a `filePath`; books + copied into Books// have it left undefined. Surfacing the + path lets the user verify which on-disk file the entry points at + and tell apart in-place vs hash-copy imports at a glance. + */} + {book.filePath && ( +
+ {_('File Path')} +

+ {book.filePath} +

+
+ )} )}