test: build HMAC tenant fixtures from domain, drop product URLs

HMAC identity tests should not hardcode gholak/montzar hosts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-09 22:12:21 +03:30
co-authored by Cursor
parent 82e74f86f0
commit 38337c62d7
2 changed files with 54 additions and 54 deletions
+50 -49
View File
@@ -1,65 +1,66 @@
import { findTenantForHost, scoreTenantHost } from './tenant-host.util';
import {
findTenantForHost,
scoreTenantHost,
type TenantHostFields,
} from './tenant-host.util';
const gholak = {
domain: 'app.gholaktala.ir',
function fromDomain(
domain: string,
extra: Partial<TenantHostFields> = {},
): TenantHostFields {
return {
domain,
domains: [],
appUrl: 'https://app.gholaktala.ir',
adminUrl: 'https://k.montzar.ir/admin',
nodeServer: 'https://new.gholaktala.ir/server',
};
const montzar = {
domain: 'k.montzar.ir',
domains: ['montzar.ir'],
appUrl: 'https://k.montzar.ir',
adminUrl: 'https://k.montzar.ir',
nodeServer: 'https://new.gholaktala.ir/server',
};
const otherOnSameBox = {
domain: 'examplegold.ir',
domains: [],
appUrl: 'https://examplegold.ir',
appUrl: `https://${domain}`,
adminUrl: null,
nodeServer: 'https://new.gholaktala.ir/server',
nodeServer: null,
...extra,
};
}
describe('findTenantForHost', () => {
const tenants = [gholak, otherOnSameBox, montzar];
it('hmac does not treat shared adminUrl as gholaktala', () => {
expect(scoreTenantHost(gholak, 'k.montzar.ir', 'hmac')).toBe(0);
expect(findTenantForHost(tenants, 'k.montzar.ir', 'hmac')?.domain).toBe(
'k.montzar.ir',
);
it('hmac matches the tenant whose domain is the host', () => {
const host = 'shop.example.ir';
const mine = fromDomain(host);
const other = fromDomain('other.example.ir', {
adminUrl: `https://${host}/admin`,
});
it('hmac without montzar tenant does not fall back to gholak adminUrl', () => {
expect(
findTenantForHost([gholak, otherOnSameBox], 'k.montzar.ir', 'hmac'),
).toBeUndefined();
expect(scoreTenantHost(other, host, 'hmac')).toBe(0);
expect(findTenantForHost([other, mine], host, 'hmac')?.domain).toBe(host);
});
it('full get_user still maps k.montzar.ir to montzar by primary domain', () => {
expect(findTenantForHost(tenants, 'k.montzar.ir')?.domain).toBe(
'k.montzar.ir',
);
it('hmac does not use another tenant adminUrl as identity', () => {
const host = 'panel.example.ir';
const other = fromDomain('app.other.ir', {
adminUrl: `https://${host}/admin`,
});
it('maps new.gholaktala.ir to gholaktala via subdomain, not nodeServer', () => {
const gholakBare = { ...gholak, domain: 'gholaktala.ir' };
expect(
findTenantForHost([montzar, otherOnSameBox, gholakBare], 'new.gholaktala.ir')
?.domain,
).toBe('gholaktala.ir');
expect(scoreTenantHost(gholakBare, 'new.gholaktala.ir')).toBe(75);
expect(findTenantForHost([other], host, 'hmac')).toBeUndefined();
});
it('does not pick a random tenant when only nodeServer matches several rows', () => {
const sharedOnly = [
{ ...montzar, domain: 'a.ir', domains: [] },
{ ...gholak, domain: 'b.ir', domains: [] },
];
expect(findTenantForHost(sharedOnly, 'new.gholaktala.ir')).toBeUndefined();
it('full match uses primary domain when present', () => {
const host = 'shop.example.ir';
expect(findTenantForHost([fromDomain(host)], host)?.domain).toBe(host);
});
it('subdomain of the tenant domain beats a shared nodeServer', () => {
const root = 'shop.example.ir';
const api = `new.${root}`;
const mine = fromDomain(root, { nodeServer: `https://${api}/server` });
const roommate = fromDomain('roommate.ir', {
nodeServer: `https://${api}/server`,
});
expect(findTenantForHost([roommate, mine], api)?.domain).toBe(root);
expect(scoreTenantHost(mine, api)).toBe(75);
});
it('does not pick a tenant when only a shared nodeServer matches', () => {
const api = 'box.example.ir';
const left = fromDomain('a.ir', { nodeServer: `https://${api}/server` });
const right = fromDomain('b.ir', { nodeServer: `https://${api}/server` });
expect(findTenantForHost([left, right], api)).toBeUndefined();
});
});
+2 -3
View File
@@ -54,7 +54,7 @@ function hostsEqual(left: string, right: string): boolean {
return left.replace(/^www\./, '') === right.replace(/^www\./, '');
}
/** new.gholaktala.ir belongs to tenant domain gholaktala.ir — not via shared nodeServer. */
/** new.shop.ir belongs to tenant domain shop.ir — not via shared nodeServer. */
function isSubdomainOf(host: string, parent: string): boolean {
const child = normalizeTenantHost(host);
const root = normalizeTenantHost(parent).replace(/^www\./, '');
@@ -66,8 +66,7 @@ export type TenantHostMatchMode = 'full' | 'hmac';
/**
* full: get_user — دامنه، alias، app/admin/node.
* hmac: فقط دامنهٔ اصلی نسخه (و ساب‌دامنهٔ همان). adminUrl مشترک
* (k.montzar.ir روی نسخهٔ app.gholaktala.ir) هویت نیست.
* hmac: فقط دامنهٔ اصلی نسخه (و ساب‌دامنهٔ همان). adminUrl هویت نیست.
*/
export function scoreTenantHost(
tenant: TenantHostFields,