make view activity works!

This commit is contained in:
2026-06-20 17:14:51 +10:00
parent 09ab959b08
commit 91b16aba53
8 changed files with 350 additions and 18 deletions
+90 -4
View File
@@ -74,6 +74,49 @@ class FakeD1Database {
click_count: row.click_count,
};
}
findPrivateActiveById(ownerUserId: string, id: string): Omit<LinkRow, 'scope' | 'status' | 'owner_user_id'> | null {
const row = this.links.find((candidate) => {
return (
candidate.scope === 'private' &&
candidate.status === 'active' &&
candidate.owner_user_id === ownerUserId &&
candidate.id === id
);
});
if (!row) {
return null;
}
return {
id: row.id,
alias: row.alias,
link_type: row.link_type,
target_url: row.target_url,
content_markdown: row.content_markdown,
click_count: row.click_count,
};
}
findPublicActiveById(id: string): Omit<LinkRow, 'scope' | 'status'> | null {
const row = this.links.find((candidate) => {
return candidate.scope === 'public' && candidate.status === 'active' && candidate.id === id;
});
if (!row) {
return null;
}
return {
id: row.id,
alias: row.alias,
link_type: row.link_type,
target_url: row.target_url,
content_markdown: row.content_markdown,
click_count: row.click_count,
};
}
}
class FakeD1PreparedStatement {
@@ -111,12 +154,25 @@ class FakeD1PreparedStatement {
if (this.sql.includes("scope='private'")) {
expect(this.sql).toContain("status='active'");
expect(this.sql).toContain('owner_user_id=?');
expect(this.sql).toContain('alias=?');
expect(this.sql).toContain('LIMIT 1');
const ownerUserId = String(this.params[0]);
const alias = String(this.params[1]);
return this.db.findPrivateActive(ownerUserId, alias) as T;
if (this.sql.includes('alias=?')) {
const ownerUserId = String(this.params[0]);
const alias = String(this.params[1]);
return this.db.findPrivateActive(ownerUserId, alias) as T;
}
expect(this.sql).toContain('id=?');
const id = String(this.params[0]);
const ownerUserId = String(this.params[1]);
return this.db.findPrivateActiveById(ownerUserId, id) as T;
}
if (this.sql.includes("scope='public'")) {
expect(this.sql).toContain("status='active'");
expect(this.sql).toContain('id=?');
const id = String(this.params[0]);
return this.db.findPublicActiveById(id) as T;
}
return null;
@@ -284,6 +340,36 @@ describe('my.heygo.cc private shortlinks', () => {
expect(db.runCalls[1].params).toEqual(['link_a']);
});
it('resolves /links/:id/go for the authenticated owner from the app host', async () => {
const cookie = await sessionCookie('token-a');
const session = await userSession('token-a', 'userA');
const { response, ctx, db } = await fetchWorker('https://heygo.cc/links/link_a/go', {
cookie,
sessions: [session],
links: [
{
id: 'link_a',
alias: 'foo',
scope: 'private',
status: 'active',
link_type: 'redirect',
target_url: 'https://example.com/foo-a',
content_markdown: null,
click_count: 0,
owner_user_id: 'userA',
},
],
});
expect(response.status).toBe(302);
expect(response.headers.get('location')).toBe('https://example.com/foo-a');
expectPrivateNoStoreHeaders(response);
expect(ctx.promises).toHaveLength(1);
await Promise.all(ctx.promises);
expect(db.runCalls[0].params).toEqual(['link_a']);
expect(db.runCalls[1].params).toEqual(['link_a']);
});
it('isolates private aliases per user (user B resolves own link, not user A)', async () => {
const cookieA = await sessionCookie('token-a');
const cookieB = await sessionCookie('token-b');
+50 -4
View File
@@ -50,6 +50,25 @@ class FakeD1Database {
click_count: row.click_count,
};
}
findPublicActiveById(id: string): Omit<LinkRow, 'scope' | 'status'> | null {
const row = this.rows.find((candidate) => {
return candidate.id === id && candidate.scope === 'public' && candidate.status === 'active';
});
if (!row) {
return null;
}
return {
id: row.id,
alias: row.alias,
link_type: row.link_type,
target_url: row.target_url,
content_markdown: row.content_markdown,
click_count: row.click_count,
};
}
}
class FakeD1PreparedStatement {
@@ -66,10 +85,13 @@ class FakeD1PreparedStatement {
async first<T>(): Promise<T | null> {
expect(this.sql).toContain("scope='public'");
expect(this.sql).toContain("status='active'");
expect(this.sql).toContain('alias=?');
const alias = String(this.params[0]);
return this.db.findPublicActive(alias) as T | null;
if (this.sql.includes('alias=?')) {
const alias = String(this.params[0]);
return this.db.findPublicActive(alias) as T | null;
}
expect(this.sql).toContain('id=?');
const id = String(this.params[0]);
return this.db.findPublicActiveById(id) as T | null;
}
async run(): Promise<D1Result> {
@@ -164,6 +186,30 @@ describe('public heygo.cc shortlink redirects', () => {
expect(html).toContain('&lt;script&gt;');
});
it('resolves /links/:id/go for a public link and records analytics', async () => {
const { response, ctx, db } = await fetchWorker('https://heygo.cc/links/link_2/go', [
{
id: 'link_2',
alias: 'about',
scope: 'public',
status: 'active',
link_type: 'custom',
target_url: null,
content_markdown: '# About Heygo',
click_count: 5,
},
]);
expect(response.status).toBe(200);
expect(response.headers.get('content-type')).toContain('text/html');
expect(ctx.promises).toHaveLength(1);
await Promise.all(ctx.promises);
expect(db.runCalls).toHaveLength(2);
expect(db.runCalls[0].params).toEqual(['link_2']);
expect(db.runCalls[1].params).toEqual(['link_2']);
});
it('returns a public 404 HTML response for an unknown alias on heygo.cc', async () => {
const { response } = await fetchWorker('https://heygo.cc/missing');