Files
memind/mindspace-rybbit.test.mjs

105 lines
3.4 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('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');
});