c7718c683b
Memind CI / Test, build, and release guards (push) Successful in 1m36s
Publication routes and share shells were missing the Rybbit tracker, and bootstrap now reuses the stored MindSpace analytics secret when Rybbit env secret is absent. Co-authored-by: Cursor <cursoragent@cursor.com>
116 lines
3.7 KiB
JavaScript
116 lines
3.7 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import vm from 'node:vm';
|
|
|
|
import {
|
|
injectMindSpaceRybbit,
|
|
resolveMindSpaceRybbitConfig,
|
|
} from './mindspace-rybbit.mjs';
|
|
|
|
test('rybbit config is disabled unless explicitly enabled and configured', () => {
|
|
assert.equal(resolveMindSpaceRybbitConfig({ MEMIND_RYBBIT_ENABLED: 'true' }).enabled, false);
|
|
assert.equal(resolveMindSpaceRybbitConfig({
|
|
MEMIND_RYBBIT_ENABLED: 'true',
|
|
MEMIND_RYBBIT_SITE_ID: '2',
|
|
}).enabled, false);
|
|
const config = resolveMindSpaceRybbitConfig({
|
|
MEMIND_RYBBIT_ENABLED: 'true',
|
|
MEMIND_RYBBIT_SITE_ID: '2',
|
|
MEMIND_RYBBIT_ID_SECRET: 'local-secret',
|
|
MEMIND_RYBBIT_URL: 'https://rybbit.tkmind.cn',
|
|
});
|
|
assert.equal(config.enabled, true);
|
|
assert.equal(config.siteId, '2');
|
|
assert.equal(config.rybbitUrl, 'https://rybbit.tkmind.cn');
|
|
assert.equal(config.hostPath, '/rybbit');
|
|
assert.equal(config.scriptPath, '/rybbit/script.js');
|
|
});
|
|
|
|
test('rybbit config can reuse stored analytics secret', () => {
|
|
const config = resolveMindSpaceRybbitConfig({
|
|
MEMIND_RYBBIT_ENABLED: 'true',
|
|
MEMIND_RYBBIT_SITE_ID: '2',
|
|
}, {
|
|
idSecret: 'stored-secret',
|
|
});
|
|
assert.equal(config.enabled, true);
|
|
assert.equal(config.idSecret, 'stored-secret');
|
|
});
|
|
|
|
test('injects one local same-origin rybbit tracker with page dimensions', () => {
|
|
const html = '<!doctype html><html><head><title>Demo</title></head><body><h1>Demo</h1></body></html>';
|
|
const out = injectMindSpaceRybbit(html, {
|
|
ownerId: 'user-123',
|
|
ownerLabel: '张三',
|
|
pageId: 'page-1',
|
|
publicationId: 'pub-1',
|
|
config: {
|
|
enabled: true,
|
|
siteId: '2',
|
|
idSecret: 'secret',
|
|
scriptPath: '/rybbit/script.js',
|
|
hostPath: '/rybbit',
|
|
},
|
|
});
|
|
assert.match(out, /src="\/rybbit\/script\.js"/);
|
|
assert.match(out, /data-site-id="2"/);
|
|
assert.match(out, /data-memind-rybbit="1"/);
|
|
assert.match(out, /r\.identify\(d\.owner_id,/);
|
|
assert.match(out, /r\.event\(n,p\)/);
|
|
assert.match(out, /page_click/);
|
|
assert.match(out, /page_form_submit/);
|
|
assert.match(out, /page_scroll_/);
|
|
assert.match(out, /page_engaged_10s/);
|
|
assert.match(out, /"username":"张三"/);
|
|
assert.doesNotMatch(out, /user-123/);
|
|
assert.equal(injectMindSpaceRybbit(out, {
|
|
ownerId: 'user-123',
|
|
config: { enabled: true, siteId: '2', idSecret: 'secret' },
|
|
}), out);
|
|
});
|
|
|
|
test('identifies the pseudonymous owner once rybbit is ready', () => {
|
|
const out = injectMindSpaceRybbit('<!doctype html><html><head></head><body></body></html>', {
|
|
ownerId: 'user-123',
|
|
ownerSegment: 'plan:pro',
|
|
ownerLabel: '张三',
|
|
channel: 'h5',
|
|
config: {
|
|
enabled: true,
|
|
siteId: '2',
|
|
idSecret: 'secret',
|
|
scriptPath: '/rybbit/script.js',
|
|
hostPath: '/rybbit',
|
|
},
|
|
});
|
|
const inlineScript = out.match(/<script data-memind-rybbit="1">([\s\S]*?)<\/script>/)?.[1];
|
|
assert.ok(inlineScript);
|
|
|
|
const calls = [];
|
|
const timers = [];
|
|
vm.runInNewContext(inlineScript, {
|
|
window: {
|
|
rybbit: {
|
|
identify: (...args) => calls.push(['identify', ...args]),
|
|
event: (...args) => calls.push(['event', ...args]),
|
|
},
|
|
innerHeight: 800,
|
|
scrollY: 0,
|
|
addEventListener: () => {},
|
|
},
|
|
document: {
|
|
readyState: 'complete',
|
|
title: 'Demo',
|
|
documentElement: { scrollHeight: 1600 },
|
|
addEventListener: () => {},
|
|
},
|
|
location: { href: 'http://127.0.0.1:8081/MindSpace/demo/public/page.html' },
|
|
setTimeout: (fn) => { timers.push(fn); },
|
|
});
|
|
|
|
assert.equal(calls[0]?.[0], 'identify');
|
|
assert.match(String(calls[0]?.[1] ?? ''), /^[a-f0-9]{32}$/);
|
|
assert.equal(calls[0]?.[2]?.username, '张三');
|
|
assert.equal(calls[0]?.[2]?.owner_segment, 'plan:pro');
|
|
});
|