@kbach/ui 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,86 @@
1
+ import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
2
+ import { transformSync } from '@babel/core';
3
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
4
+ const kbachBabelPlugin = require('./index.js');
5
+
6
+ // No kbach.config.js exists at this test's cwd, so the plugin falls back to
7
+ // the default theme and warns once (cached after) — expected, not a signal
8
+ // this test is checking.
9
+ let warnSpy: any;
10
+ beforeAll(() => { warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); });
11
+ afterAll(() => { warnSpy.mockRestore(); });
12
+
13
+ // Regression coverage for a fixed bug: when the FIRST of two class-bearing
14
+ // attributes on one element (e.g. `kb="group" className="p-4 bg-white"`)
15
+ // resolved to zero styles on its own (like `group`, a standalone marker with
16
+ // no styles of its own), the merge-tracking map (state.kbachElementInfo)
17
+ // never got populated for that element — it fell through an early `return`
18
+ // before the `.set()` call. The second attribute then never saw `existing`,
19
+ // transformed itself in isolation, and the first attribute was left
20
+ // completely untouched in the output (never renamed/removed), producing a
21
+ // stray `kb="group"` prop reaching the real component at runtime instead of
22
+ // being folded into the merge like the plugin's own doc comment promises.
23
+
24
+ function transform(code: string): string {
25
+ const result = transformSync(code, {
26
+ filename: '/project/src/App.tsx',
27
+ babelrc: false,
28
+ configFile: false,
29
+ parserOpts: { plugins: ['jsx'] },
30
+ plugins: [kbachBabelPlugin],
31
+ });
32
+ if (!result?.code) throw new Error('transform produced no output');
33
+ return result.code;
34
+ }
35
+
36
+ describe('babel-plugin-kbach — merging multiple class attributes on one element', () => {
37
+ it('merges two attributes that both have styles (baseline, already worked)', () => {
38
+ const out = transform(`<View kb="p-4" className="bg-white" />;`);
39
+ expect(out).not.toContain('kb=');
40
+ expect(out).not.toContain('className=');
41
+ expect(out.match(/__kbachClasses/g)?.length).toBe(1);
42
+ expect(out.match(/__kbachStyles/g)?.length).toBe(1);
43
+ expect(out).toContain('__kbachClasses="p-4 bg-white"');
44
+ });
45
+
46
+ it('merges when the FIRST attribute alone resolves to no styles (the fixed bug)', () => {
47
+ const out = transform(`<View kb="group" className="p-4 bg-white" />;`);
48
+ // The first, styleless attribute must be folded away, not left dangling.
49
+ expect(out).not.toContain('kb=');
50
+ expect(out).not.toContain('className=');
51
+ // Exactly one merged pair, carrying BOTH classes.
52
+ expect(out.match(/__kbachClasses/g)?.length).toBe(1);
53
+ expect(out.match(/__kbachStyles/g)?.length).toBe(1);
54
+ expect(out).toContain('__kbachClasses="group p-4 bg-white"');
55
+ });
56
+
57
+ it('merges when the SECOND attribute alone resolves to no styles', () => {
58
+ const out = transform(`<View kb="p-4 bg-white" className="group" />;`);
59
+ expect(out).not.toContain('kb=');
60
+ expect(out).not.toContain('className=');
61
+ expect(out.match(/__kbachClasses/g)?.length).toBe(1);
62
+ expect(out.match(/__kbachStyles/g)?.length).toBe(1);
63
+ expect(out).toContain('__kbachClasses="p-4 bg-white group"');
64
+ });
65
+
66
+ it('leaves both attributes untouched when NEITHER resolves to any styles', () => {
67
+ const out = transform(`<View kb="group" className="peer" />;`);
68
+ expect(out).toContain('kb="group"');
69
+ expect(out).toContain('className="peer"');
70
+ expect(out).not.toContain('__kbachClasses');
71
+ expect(out).not.toContain('__kbachStyles');
72
+ });
73
+
74
+ it('a single class attribute with styles still transforms normally (no merge involved)', () => {
75
+ const out = transform(`<View className="p-4" />;`);
76
+ expect(out).not.toContain('className=');
77
+ expect(out).toContain('__kbachClasses="p-4"');
78
+ expect(out.match(/__kbachStyles/g)?.length).toBe(1);
79
+ });
80
+
81
+ it('a single class attribute with no styles is left untouched', () => {
82
+ const out = transform(`<View className="group" />;`);
83
+ expect(out).toContain('className="group"');
84
+ expect(out).not.toContain('__kbachClasses');
85
+ });
86
+ });
package/types.d.ts ADDED
@@ -0,0 +1 @@
1
+ /// <reference path="./src/kbach-env.d.ts" />