Files
zooqueenandzeekay 4712ee9d98 chore: complete posthog->insights rebrand (zero @posthog/* identity)
Decomplect the half-finished fork so the dependency graph has ONE source
with no posthog package identity, living under github.com/hanzoinsights.

LAYER 1 (package identity): rename straggler package.json names —
@posthog/next->@hanzo/insights-next (Next.js SDK; distinct from the existing
@hanzo/insights-nextjs config helper), @posthog/mcp->@hanzo/insights-mcp,
@posthog/plugin-utils->@hanzo/insights-plugin-utils,
@posthog/react-slim->@hanzo/react-slim, @posthog-tooling/release->
@hanzo/insights-tooling-release, and the @posthog/rrweb* family->@hanzo/rrweb*
(matching the already-published @hanzo/rrweb*@0.0.47 + minimumReleaseAgeExclude).
Repoint every repository.url/homepage/bugs to github.com/hanzoinsights/insights-js
and rebrand the PostHog author/description identity to Hanzo AI.

LAYER 2 (cross-package imports): rewrite every internal @posthog/* import to its
@hanzo/insights*|@hanzo/rrweb* equivalent and the bare module specifiers
posthog-js->@hanzo/insights, posthog-node->@hanzo/insights-node, mirrored in
package.json deps + the pnpm-lock importer keys. Result: 0 @posthog/* specifiers
in packages/tooling/examples/playground source.

LAYER 4 (wire protocol) PRESERVED: window.posthog global, ph_* keys,
$-prefixed event names, distinct_id, /decide, /e/, /flags, and the
__PosthogExtensions__ hook are left unchanged — the Insights server expects them.

Also repair pre-existing fork merge damage that blocked compilation (unrelated to
naming; identical to origin/main): restore the @hanzo/insights-core ./process
subpath (spawn-local/utils, re-matching the published artifact), the lost
constructor/var declarations in core + node clients, the mangled
external-scripts-loader, the missing TreeShakeable/isPlainError imports, the
DeviceId enum member, and stale ../posthog-core-stateless module paths. 26/34
turbo build tasks now pass; remaining failures (browser/react-native and their
dependents) are pre-existing fork damage, not rebrand-caused.
2026-07-16 09:09:17 -07:00

112 lines
4.8 KiB
TypeScript

/**
* @vitest-environment jsdom
*/
import { describe, it, beforeEach, expect } from 'vitest';
import { mediaSelectorPlugin, pseudoClassPlugin } from '../src/css';
import postcss, { type AcceptedPlugin } from 'postcss';
import { JSDOM } from 'jsdom';
import { splitCssText, stringifyStylesheet } from './../src/utils';
import { applyCssSplits } from './../src/rebuild';
import * as fs from 'fs';
import * as path from 'path';
import type {
serializedElementNodeWithId,
BuildCache,
textNode,
} from '../src/types';
import { NodeType } from '@hanzo/rrweb-types';
import { Window } from 'happy-dom';
describe('css parser', () => {
function parse(plugin: AcceptedPlugin, input: string): string {
const ast = postcss([plugin]).process(input, {});
return ast.css;
}
describe('mediaSelectorPlugin', () => {
it('selectors without device remain unchanged', () => {
const cssText =
'@media only screen and (min-width: 1200px) { .a { width: 10px; }}';
expect(parse(mediaSelectorPlugin, cssText)).toEqual(cssText);
});
it('can adapt media rules to replay context', () => {
[
['min', 'width'],
['min', 'height'],
['max', 'width'],
['max', 'height'],
].forEach(([first, second]) => {
expect(
parse(
mediaSelectorPlugin,
`@media only screen and (${first}-device-${second}: 1200px) { .a { width: 10px; }}`,
),
).toEqual(
`@media only screen and (${first}-${second}: 1200px) { .a { width: 10px; }}`,
);
});
});
});
describe('pseudoClassPlugin', () => {
it('parses nested commas in selectors correctly', () => {
const cssText =
'body > ul :is(li:not(:first-of-type) a.current, li:not(:first-of-type).active a) {background: red;}';
expect(parse(pseudoClassPlugin, cssText)).toEqual(cssText);
});
it("doesn't ignore :hover within :is brackets", () => {
const cssText =
'body > ul :is(li:not(:first-of-type) a:hover, li:not(:first-of-type).active a) {background: red;}';
expect(parse(pseudoClassPlugin, cssText))
.toEqual(`body > ul :is(li:not(:first-of-type) a:hover, li:not(:first-of-type).active a),
body > ul :is(li:not(:first-of-type) a.\\:hover, li:not(:first-of-type).active a) {background: red;}`);
});
it('should parse selector with comma nested inside ()', () => {
const cssText =
'[_nghost-ng-c4172599085]:not(.fit-content).aim-select:hover:not(:disabled, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--disabled, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--invalid, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--active) { border-color: rgb(84, 84, 84); }';
expect(parse(pseudoClassPlugin, cssText))
.toEqual(`[_nghost-ng-c4172599085]:not(.fit-content).aim-select:hover:not(:disabled, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--disabled, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--invalid, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--active),
[_nghost-ng-c4172599085]:not(.fit-content).aim-select.\\:hover:not(:disabled, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--disabled, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--invalid, [_nghost-ng-c4172599085]:not(.fit-content).aim-select--active) { border-color: rgb(84, 84, 84); }`);
});
it('ignores ( in strings', () => {
const cssText =
'li[attr="weirdly("] a:hover, li[attr="weirdly)"] a {background-color: red;}';
expect(parse(pseudoClassPlugin, cssText))
.toEqual(`li[attr="weirdly("] a:hover, li[attr="weirdly)"] a,
li[attr="weirdly("] a.\\:hover {background-color: red;}`);
});
it('ignores escaping in strings', () => {
const cssText = `li[attr="weirder\\"("] a:hover, li[attr="weirder\\")"] a {background-color: red;}`;
expect(parse(pseudoClassPlugin, cssText))
.toEqual(`li[attr="weirder\\"("] a:hover, li[attr="weirder\\")"] a,
li[attr="weirder\\"("] a.\\:hover {background-color: red;}`);
});
it('preserves escaped \\:hover in class names while transforming real :hover pseudo-class', () => {
const cssText = '.escaped\\:hover\\:classname:hover { color: red; }';
expect(parse(pseudoClassPlugin, cssText)).toEqual(
`.escaped\\:hover\\:classname:hover,
.escaped\\:hover\\:classname.\\:hover { color: red; }`,
);
});
it('leaves selectors unchanged when they only contain escaped \\:hover', () => {
const cssText = '.escaped\\:hover\\:classname { color: white; }';
expect(parse(pseudoClassPlugin, cssText)).toEqual(cssText);
});
it('ignores comma in string', () => {
const cssText = 'li[attr="has,comma"] a:hover {background: red;}';
expect(parse(pseudoClassPlugin, cssText)).toEqual(
`li[attr="has,comma"] a:hover,
li[attr="has,comma"] a.\\:hover {background: red;}`,
);
});
});
});