test(share): cover alias controllers; address PR #214 review

Add the two blocking test-coverage specs requested in the PR #214 review and
clear the cheap non-blocking items.

Must-fix:
- share-alias-redirect.controller.spec.ts: routing/leak guard for the public
  GET /l/:alias resolver (modeled on share-seo.controller.routing.spec). Pins
  302-to-canonical on a hit; SPA index without a 302 for unknown/dangling/
  unreadable aliases and a null workspace (no name-existence leak); defensive
  percent-decoding treated as unknown; self-hosted findFirst vs subdomain
  findByHostname workspace resolution; 404 when no built client index exists.
- share-alias.controller.spec.ts: authz gates with mocked PageRepo/ShareService/
  ShareAliasService/PageAccessService. Covers cross-workspace/nonexistent page
  -> NotFoundException, validateCanEdit, resolveReadableSharePage null ->
  BadRequestException, isSharingAllowed false -> ForbiddenException, set happy
  path delegation, remove() of a dangling alias (pageId null) skipping
  validateCanEdit but still deleting, and for-page validateCanView.

Cheap review items:
- Remove dead Logger import/field from ShareAliasRedirectController.
- Remove dead PagePermissionRepo import/dependency from ShareAliasController.
- Register the new share-alias UI strings in en-US and ru-RU catalogs.
- Add an [Unreleased]/Added CHANGELOG entry for /l/:alias (#205).
- Drop the tautological boilerplate assertions from the migration spec
  (exports up/down; runtime checks of typed entity literals).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
claude code agent 227
2026-06-26 17:22:29 +03:00
parent fdeede003b
commit 1043fe3b51
8 changed files with 527 additions and 16 deletions

View File

@@ -13,11 +13,6 @@ import type {
* the generated entity types line up with the column set.
*/
describe('share-aliases migration', () => {
it('exports up and down functions', () => {
expect(typeof migration.up).toBe('function');
expect(typeof migration.down).toBe('function');
});
it('up creates the table, the unique index and the page_id index', async () => {
const calls: string[] = [];
@@ -76,7 +71,9 @@ describe('share-aliases migration', () => {
});
it('entity types expose the alias columns', () => {
// Compile-time + runtime sanity: a well-formed row/insert/update value.
// Compile-time only: these typed declarations fail `tsc` if the entity types
// drift (missing/renamed columns, wrong nullability). The runtime assertions
// would be tautological, so the value is purely in the type-check.
const row: ShareAlias = {
id: 'a-1',
workspaceId: 'ws-1',
@@ -92,8 +89,6 @@ describe('share-aliases migration', () => {
};
const update: UpdatableShareAlias = { pageId: null };
expect(row.alias).toBe('foo');
expect(insert.workspaceId).toBe('ws-1');
expect(update.pageId).toBeNull();
expect([row, insert, update]).toHaveLength(3);
});
});