atomirx 0.0.8 → 0.1.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.
Files changed (138) hide show
  1. package/README.md +198 -2234
  2. package/bin/cli.js +90 -0
  3. package/dist/core/derived.d.ts +2 -2
  4. package/dist/core/effect.d.ts +3 -2
  5. package/dist/core/onCreateHook.d.ts +15 -2
  6. package/dist/core/onErrorHook.d.ts +4 -1
  7. package/dist/core/pool.d.ts +78 -0
  8. package/dist/core/pool.test.d.ts +1 -0
  9. package/dist/core/select-boolean.test.d.ts +1 -0
  10. package/dist/core/select-pool.test.d.ts +1 -0
  11. package/dist/core/select.d.ts +278 -86
  12. package/dist/core/types.d.ts +233 -1
  13. package/dist/core/withAbort.d.ts +95 -0
  14. package/dist/core/withReady.d.ts +3 -3
  15. package/dist/devtools/constants.d.ts +41 -0
  16. package/dist/devtools/index.cjs +1 -0
  17. package/dist/devtools/index.d.ts +29 -0
  18. package/dist/devtools/index.js +429 -0
  19. package/dist/devtools/registry.d.ts +98 -0
  20. package/dist/devtools/registry.test.d.ts +1 -0
  21. package/dist/devtools/setup.d.ts +61 -0
  22. package/dist/devtools/types.d.ts +311 -0
  23. package/dist/index-BZEnfIcB.cjs +1 -0
  24. package/dist/index-BbPZhsDl.js +1653 -0
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.d.ts +4 -3
  27. package/dist/index.js +18 -14
  28. package/dist/onDispatchHook-C8yLzr-o.cjs +1 -0
  29. package/dist/onDispatchHook-SKbiIUaJ.js +5 -0
  30. package/dist/onErrorHook-BGGy3tqK.js +38 -0
  31. package/dist/onErrorHook-DHBASmYw.cjs +1 -0
  32. package/dist/react/index.cjs +1 -1
  33. package/dist/react/index.js +191 -151
  34. package/dist/react/onDispatchHook.d.ts +106 -0
  35. package/dist/react/useAction.d.ts +4 -1
  36. package/dist/react-devtools/DevToolsPanel.d.ts +93 -0
  37. package/dist/react-devtools/EntityDetails.d.ts +10 -0
  38. package/dist/react-devtools/EntityList.d.ts +15 -0
  39. package/dist/react-devtools/LogList.d.ts +12 -0
  40. package/dist/react-devtools/hooks.d.ts +50 -0
  41. package/dist/react-devtools/index.cjs +1 -0
  42. package/dist/react-devtools/index.d.ts +31 -0
  43. package/dist/react-devtools/index.js +1589 -0
  44. package/dist/react-devtools/styles.d.ts +148 -0
  45. package/package.json +26 -2
  46. package/skills/atomirx/SKILL.md +456 -0
  47. package/skills/atomirx/references/async-patterns.md +188 -0
  48. package/skills/atomirx/references/atom-patterns.md +238 -0
  49. package/skills/atomirx/references/deferred-loading.md +191 -0
  50. package/skills/atomirx/references/derived-patterns.md +428 -0
  51. package/skills/atomirx/references/effect-patterns.md +426 -0
  52. package/skills/atomirx/references/error-handling.md +140 -0
  53. package/skills/atomirx/references/hooks.md +322 -0
  54. package/skills/atomirx/references/pool-patterns.md +229 -0
  55. package/skills/atomirx/references/react-integration.md +411 -0
  56. package/skills/atomirx/references/rules.md +407 -0
  57. package/skills/atomirx/references/select-context.md +309 -0
  58. package/skills/atomirx/references/service-template.md +172 -0
  59. package/skills/atomirx/references/store-template.md +205 -0
  60. package/skills/atomirx/references/testing-patterns.md +431 -0
  61. package/coverage/base.css +0 -224
  62. package/coverage/block-navigation.js +0 -87
  63. package/coverage/clover.xml +0 -1440
  64. package/coverage/coverage-final.json +0 -14
  65. package/coverage/favicon.png +0 -0
  66. package/coverage/index.html +0 -131
  67. package/coverage/prettify.css +0 -1
  68. package/coverage/prettify.js +0 -2
  69. package/coverage/sort-arrow-sprite.png +0 -0
  70. package/coverage/sorter.js +0 -210
  71. package/coverage/src/core/atom.ts.html +0 -889
  72. package/coverage/src/core/batch.ts.html +0 -223
  73. package/coverage/src/core/define.ts.html +0 -805
  74. package/coverage/src/core/emitter.ts.html +0 -919
  75. package/coverage/src/core/equality.ts.html +0 -631
  76. package/coverage/src/core/hook.ts.html +0 -460
  77. package/coverage/src/core/index.html +0 -281
  78. package/coverage/src/core/isAtom.ts.html +0 -100
  79. package/coverage/src/core/isPromiseLike.ts.html +0 -133
  80. package/coverage/src/core/onCreateHook.ts.html +0 -138
  81. package/coverage/src/core/scheduleNotifyHook.ts.html +0 -94
  82. package/coverage/src/core/types.ts.html +0 -523
  83. package/coverage/src/core/withUse.ts.html +0 -253
  84. package/coverage/src/index.html +0 -116
  85. package/coverage/src/index.ts.html +0 -106
  86. package/dist/index-CBVj1kSj.js +0 -1350
  87. package/dist/index-Cxk9v0um.cjs +0 -1
  88. package/scripts/publish.js +0 -198
  89. package/src/core/atom.test.ts +0 -633
  90. package/src/core/atom.ts +0 -311
  91. package/src/core/atomState.test.ts +0 -342
  92. package/src/core/atomState.ts +0 -256
  93. package/src/core/batch.test.ts +0 -257
  94. package/src/core/batch.ts +0 -172
  95. package/src/core/define.test.ts +0 -343
  96. package/src/core/define.ts +0 -243
  97. package/src/core/derived.test.ts +0 -1215
  98. package/src/core/derived.ts +0 -450
  99. package/src/core/effect.test.ts +0 -802
  100. package/src/core/effect.ts +0 -188
  101. package/src/core/emitter.test.ts +0 -364
  102. package/src/core/emitter.ts +0 -392
  103. package/src/core/equality.test.ts +0 -392
  104. package/src/core/equality.ts +0 -182
  105. package/src/core/getAtomState.ts +0 -69
  106. package/src/core/hook.test.ts +0 -227
  107. package/src/core/hook.ts +0 -177
  108. package/src/core/isAtom.ts +0 -27
  109. package/src/core/isPromiseLike.test.ts +0 -72
  110. package/src/core/isPromiseLike.ts +0 -16
  111. package/src/core/onCreateHook.ts +0 -107
  112. package/src/core/onErrorHook.test.ts +0 -350
  113. package/src/core/onErrorHook.ts +0 -52
  114. package/src/core/promiseCache.test.ts +0 -241
  115. package/src/core/promiseCache.ts +0 -284
  116. package/src/core/scheduleNotifyHook.ts +0 -53
  117. package/src/core/select.ts +0 -729
  118. package/src/core/selector.test.ts +0 -799
  119. package/src/core/types.ts +0 -389
  120. package/src/core/withReady.test.ts +0 -534
  121. package/src/core/withReady.ts +0 -191
  122. package/src/core/withUse.test.ts +0 -249
  123. package/src/core/withUse.ts +0 -56
  124. package/src/index.test.ts +0 -80
  125. package/src/index.ts +0 -65
  126. package/src/react/index.ts +0 -21
  127. package/src/react/rx.test.tsx +0 -571
  128. package/src/react/rx.tsx +0 -531
  129. package/src/react/strictModeTest.tsx +0 -71
  130. package/src/react/useAction.test.ts +0 -987
  131. package/src/react/useAction.ts +0 -607
  132. package/src/react/useSelector.test.ts +0 -182
  133. package/src/react/useSelector.ts +0 -292
  134. package/src/react/useStable.test.ts +0 -553
  135. package/src/react/useStable.ts +0 -288
  136. package/tsconfig.json +0 -9
  137. package/v2.md +0 -725
  138. package/vite.config.ts +0 -42
@@ -0,0 +1,431 @@
1
+ # Testing Patterns
2
+
3
+ ## Core Principles
4
+
5
+ 1. **Isolate** — Each test gets fresh atoms
6
+ 2. **Override** — Use `define().override()` for mocks
7
+ 3. **Reset hooks** — Clear between tests
8
+ 4. **Test behaviors** — Not internals
9
+
10
+ ## Testing Atoms
11
+
12
+ ### Basic
13
+
14
+ ```typescript
15
+ describe("counterAtom", () => {
16
+ it("should initialize to 0", () => {
17
+ const count$ = atom(0, { meta: { key: "test.count" } });
18
+ expect(count$.get()).toBe(0);
19
+ });
20
+
21
+ it("should update value", () => {
22
+ const count$ = atom(0);
23
+ count$.set(5);
24
+ expect(count$.get()).toBe(5);
25
+ });
26
+
27
+ it("should use reducer", () => {
28
+ const count$ = atom(0);
29
+ count$.set((prev) => prev + 1);
30
+ expect(count$.get()).toBe(1);
31
+ });
32
+
33
+ it("should reset to initial", () => {
34
+ const count$ = atom(() => 10);
35
+ count$.set(99);
36
+ count$.reset();
37
+ expect(count$.get()).toBe(10);
38
+ });
39
+
40
+ it("should track dirty state", () => {
41
+ const form$ = atom({ name: "" });
42
+ expect(form$.dirty()).toBe(false);
43
+ form$.set({ name: "John" });
44
+ expect(form$.dirty()).toBe(true);
45
+ form$.reset();
46
+ expect(form$.dirty()).toBe(false);
47
+ });
48
+ });
49
+ ```
50
+
51
+ ### Subscriptions
52
+
53
+ ```typescript
54
+ it("should notify on change", () => {
55
+ const count$ = atom(0);
56
+ const values: number[] = [];
57
+ const unsub = count$.on(() => values.push(count$.get()));
58
+
59
+ count$.set(1);
60
+ count$.set(2);
61
+ expect(values).toEqual([1, 2]);
62
+
63
+ unsub();
64
+ count$.set(3);
65
+ expect(values).toEqual([1, 2]); // No 3
66
+ });
67
+ ```
68
+
69
+ ### Async Atoms
70
+
71
+ ```typescript
72
+ it("should handle async", async () => {
73
+ const user$ = atom(Promise.resolve({ name: "John" }));
74
+ const result = await user$.get();
75
+ expect(result.name).toBe("John");
76
+ });
77
+
78
+ it("should refetch on reset", async () => {
79
+ let callCount = 0;
80
+ const data$ = atom(() => {
81
+ callCount++;
82
+ return Promise.resolve(callCount);
83
+ });
84
+
85
+ expect(await data$.get()).toBe(1);
86
+ data$.reset();
87
+ expect(await data$.get()).toBe(2);
88
+ });
89
+ ```
90
+
91
+ ## Testing Derived
92
+
93
+ ```typescript
94
+ describe("derived", () => {
95
+ it("should compute from source", async () => {
96
+ const count$ = atom(5);
97
+ const doubled$ = derived(({ read }) => read(count$) * 2);
98
+ expect(await doubled$.get()).toBe(10);
99
+ });
100
+
101
+ it("should update on source change", async () => {
102
+ const count$ = atom(5);
103
+ const doubled$ = derived(({ read }) => read(count$) * 2);
104
+
105
+ count$.set(10);
106
+ expect(await doubled$.get()).toBe(20);
107
+ });
108
+
109
+ it("should combine atoms", async () => {
110
+ const a$ = atom(1);
111
+ const b$ = atom(2);
112
+ const sum$ = derived(({ read }) => read(a$) + read(b$));
113
+
114
+ expect(await sum$.get()).toBe(3);
115
+ a$.set(10);
116
+ expect(await sum$.get()).toBe(12);
117
+ });
118
+
119
+ it("should handle async sources", async () => {
120
+ const user$ = atom(Promise.resolve({ name: "John" }));
121
+ const greeting$ = derived(({ read }) => `Hello, ${read(user$).name}`);
122
+ expect(await greeting$.get()).toBe("Hello, John");
123
+ });
124
+
125
+ it("should use fallback during loading", () => {
126
+ const data$ = derived(({ read }) => read(atom(Promise.resolve(42))), {
127
+ fallback: 0,
128
+ });
129
+ expect(data$.staleValue).toBe(0);
130
+ });
131
+ });
132
+ ```
133
+
134
+ ## Testing Effects
135
+
136
+ ```typescript
137
+ describe("effect", () => {
138
+ it("should run on creation", () => {
139
+ const log: number[] = [];
140
+ const count$ = atom(5);
141
+ effect(({ read }) => log.push(read(count$)));
142
+ expect(log).toEqual([5]);
143
+ });
144
+
145
+ it("should run on change", () => {
146
+ const log: number[] = [];
147
+ const count$ = atom(0);
148
+ effect(({ read }) => log.push(read(count$)));
149
+
150
+ count$.set(1);
151
+ count$.set(2);
152
+ expect(log).toEqual([0, 1, 2]);
153
+ });
154
+
155
+ it("should cleanup", () => {
156
+ const cleanups: number[] = [];
157
+ const count$ = atom(0);
158
+
159
+ effect(({ read, onCleanup }) => {
160
+ const val = read(count$);
161
+ onCleanup(() => cleanups.push(val));
162
+ });
163
+
164
+ count$.set(1);
165
+ expect(cleanups).toEqual([0]);
166
+ count$.set(2);
167
+ expect(cleanups).toEqual([0, 1]);
168
+ });
169
+
170
+ it("should dispose", () => {
171
+ const log: number[] = [];
172
+ const count$ = atom(0);
173
+ const e = effect(({ read }) => log.push(read(count$)));
174
+
175
+ count$.set(1);
176
+ expect(log).toEqual([0, 1]);
177
+
178
+ e.dispose();
179
+ count$.set(2);
180
+ expect(log).toEqual([0, 1]); // No 2
181
+ });
182
+ });
183
+ ```
184
+
185
+ ## Testing Stores (define)
186
+
187
+ ### Mocking Services
188
+
189
+ ```typescript
190
+ const authService = define((): AuthService => ({
191
+ login: async () => ({ success: true, user: { id: "1", name: "Test" } }),
192
+ logout: async () => {},
193
+ }));
194
+
195
+ const authStore = define(() => {
196
+ const auth = authService();
197
+ const user$ = atom<User | null>(null);
198
+
199
+ return {
200
+ ...readonly({ user$ }),
201
+ login: async () => {
202
+ const result = await auth.login();
203
+ if (result.success) user$.set(result.user);
204
+ },
205
+ logout: () => user$.set(null),
206
+ };
207
+ });
208
+
209
+ describe("authStore", () => {
210
+ beforeEach(() => {
211
+ authService.reset();
212
+ authStore.reset();
213
+ });
214
+
215
+ it("should login with mock", async () => {
216
+ authService.override(() => ({
217
+ login: async () => ({ success: true, user: { id: "mock", name: "Mock" } }),
218
+ logout: async () => {},
219
+ }));
220
+
221
+ const store = authStore();
222
+ await store.login();
223
+ expect(store.user$.get()).toEqual({ id: "mock", name: "Mock" });
224
+ });
225
+
226
+ it("should handle login failure", async () => {
227
+ authService.override(() => ({
228
+ login: async () => ({ success: false, error: "Invalid" }),
229
+ logout: async () => {},
230
+ }));
231
+
232
+ const store = authStore();
233
+ await store.login();
234
+ expect(store.user$.get()).toBeNull();
235
+ });
236
+ });
237
+ ```
238
+
239
+ ### Isolation
240
+
241
+ ```typescript
242
+ describe("counterStore", () => {
243
+ const counterStore = define(() => {
244
+ const count$ = atom(0);
245
+ return {
246
+ ...readonly({ count$ }),
247
+ increment: () => count$.set((p) => p + 1),
248
+ };
249
+ });
250
+
251
+ beforeEach(() => counterStore.reset());
252
+
253
+ it("test 1", () => {
254
+ const store = counterStore();
255
+ store.increment();
256
+ expect(store.count$.get()).toBe(1);
257
+ });
258
+
259
+ it("test 2 (isolated)", () => {
260
+ const store = counterStore();
261
+ expect(store.count$.get()).toBe(0); // Fresh
262
+ });
263
+ });
264
+ ```
265
+
266
+ ## Testing Pools
267
+
268
+ ```typescript
269
+ describe("userPool", () => {
270
+ const userPool = pool(
271
+ (id: string) => ({ id, name: `User ${id}`, posts: [] }),
272
+ { gcTime: 60_000 }
273
+ );
274
+
275
+ afterEach(() => userPool.clear());
276
+
277
+ it("should create entries", () => {
278
+ expect(userPool.has("1")).toBe(false);
279
+ userPool.get("1");
280
+ expect(userPool.has("1")).toBe(true);
281
+ });
282
+
283
+ it("should update entries", () => {
284
+ userPool.get("1");
285
+ userPool.set("1", (p) => ({ ...p, name: "Updated" }));
286
+ expect(userPool.get("1").name).toBe("Updated");
287
+ });
288
+
289
+ it("should remove entries", () => {
290
+ userPool.get("1");
291
+ userPool.remove("1");
292
+ expect(userPool.has("1")).toBe(false);
293
+ });
294
+
295
+ it("should work with derived", async () => {
296
+ userPool.set("1", { id: "1", name: "John", posts: [] });
297
+
298
+ const userName$ = derived(({ read, from }) => {
299
+ const user$ = from(userPool, "1");
300
+ return read(user$).name;
301
+ });
302
+
303
+ expect(await userName$.get()).toBe("John");
304
+ });
305
+ });
306
+ ```
307
+
308
+ ## Testing Hooks
309
+
310
+ ```typescript
311
+ describe("onCreateHook", () => {
312
+ beforeEach(() => {
313
+ onCreateHook.reset();
314
+ onErrorHook.reset();
315
+ });
316
+
317
+ afterEach(() => {
318
+ onCreateHook.reset();
319
+ onErrorHook.reset();
320
+ });
321
+
322
+ it("should track atoms", () => {
323
+ const created: string[] = [];
324
+ onCreateHook.override((prev) => (info) => {
325
+ prev?.(info);
326
+ if (info.key) created.push(info.key);
327
+ });
328
+
329
+ atom(0, { meta: { key: "test.a" } });
330
+ atom(0, { meta: { key: "test.b" } });
331
+
332
+ expect(created).toContain("test.a");
333
+ expect(created).toContain("test.b");
334
+ });
335
+ });
336
+
337
+ describe("onErrorHook", () => {
338
+ beforeEach(() => onErrorHook.reset());
339
+ afterEach(() => onErrorHook.reset());
340
+
341
+ it("should capture errors", async () => {
342
+ const errors: unknown[] = [];
343
+ onErrorHook.override((prev) => (info) => {
344
+ prev?.(info);
345
+ errors.push(info.error);
346
+ });
347
+
348
+ const buggy$ = derived(() => { throw new Error("test"); });
349
+
350
+ try { await buggy$.get(); } catch {}
351
+ expect(errors).toHaveLength(1);
352
+ });
353
+ });
354
+ ```
355
+
356
+ ## Testing React
357
+
358
+ ```tsx
359
+ import { render, screen, act } from "@testing-library/react";
360
+ import { Suspense } from "react";
361
+
362
+ describe("useSelector", () => {
363
+ const count$ = atom(0, { meta: { key: "test.count" } });
364
+
365
+ beforeEach(() => count$.reset());
366
+
367
+ it("should read value", () => {
368
+ function Counter() {
369
+ const count = useSelector(count$);
370
+ return <span data-testid="count">{count}</span>;
371
+ }
372
+
373
+ render(<Counter />);
374
+ expect(screen.getByTestId("count")).toHaveTextContent("0");
375
+ });
376
+
377
+ it("should update on change", async () => {
378
+ function Counter() {
379
+ const count = useSelector(count$);
380
+ return <span data-testid="count">{count}</span>;
381
+ }
382
+
383
+ render(<Counter />);
384
+ await act(() => count$.set(5));
385
+ expect(screen.getByTestId("count")).toHaveTextContent("5");
386
+ });
387
+ });
388
+
389
+ describe("rx", () => {
390
+ it("should render inline", () => {
391
+ const name$ = atom("John");
392
+
393
+ render(
394
+ <div data-testid="greeting">
395
+ {rx(({ read }) => <>Hello, {read(name$)}</>)}
396
+ </div>
397
+ );
398
+
399
+ expect(screen.getByTestId("greeting")).toHaveTextContent("Hello, John");
400
+ });
401
+ });
402
+
403
+ describe("useAction", () => {
404
+ it("should handle async", async () => {
405
+ function Form() {
406
+ const submit = useAction(async () => "done");
407
+ return (
408
+ <>
409
+ <button onClick={() => submit()}>Submit</button>
410
+ <span data-testid="status">{submit.status}</span>
411
+ </>
412
+ );
413
+ }
414
+
415
+ render(<Form />);
416
+ expect(screen.getByTestId("status")).toHaveTextContent("idle");
417
+ });
418
+ });
419
+ ```
420
+
421
+ ## Best Practices
422
+
423
+ | Practice | Description |
424
+ | --------------------- | ----------------------------------- |
425
+ | `reset()` in beforeEach | Fresh state per test |
426
+ | `override()` for mocks | Swap implementations |
427
+ | Test behaviors | Not implementation details |
428
+ | Test subscriptions | Verify reactive updates |
429
+ | Test cleanup | Verify resources released |
430
+ | Use act() | For React state updates |
431
+ | Wrap Suspense | For async atoms in React |
package/coverage/base.css DELETED
@@ -1,224 +0,0 @@
1
- body, html {
2
- margin:0; padding: 0;
3
- height: 100%;
4
- }
5
- body {
6
- font-family: Helvetica Neue, Helvetica, Arial;
7
- font-size: 14px;
8
- color:#333;
9
- }
10
- .small { font-size: 12px; }
11
- *, *:after, *:before {
12
- -webkit-box-sizing:border-box;
13
- -moz-box-sizing:border-box;
14
- box-sizing:border-box;
15
- }
16
- h1 { font-size: 20px; margin: 0;}
17
- h2 { font-size: 14px; }
18
- pre {
19
- font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
20
- margin: 0;
21
- padding: 0;
22
- -moz-tab-size: 2;
23
- -o-tab-size: 2;
24
- tab-size: 2;
25
- }
26
- a { color:#0074D9; text-decoration:none; }
27
- a:hover { text-decoration:underline; }
28
- .strong { font-weight: bold; }
29
- .space-top1 { padding: 10px 0 0 0; }
30
- .pad2y { padding: 20px 0; }
31
- .pad1y { padding: 10px 0; }
32
- .pad2x { padding: 0 20px; }
33
- .pad2 { padding: 20px; }
34
- .pad1 { padding: 10px; }
35
- .space-left2 { padding-left:55px; }
36
- .space-right2 { padding-right:20px; }
37
- .center { text-align:center; }
38
- .clearfix { display:block; }
39
- .clearfix:after {
40
- content:'';
41
- display:block;
42
- height:0;
43
- clear:both;
44
- visibility:hidden;
45
- }
46
- .fl { float: left; }
47
- @media only screen and (max-width:640px) {
48
- .col3 { width:100%; max-width:100%; }
49
- .hide-mobile { display:none!important; }
50
- }
51
-
52
- .quiet {
53
- color: #7f7f7f;
54
- color: rgba(0,0,0,0.5);
55
- }
56
- .quiet a { opacity: 0.7; }
57
-
58
- .fraction {
59
- font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
60
- font-size: 10px;
61
- color: #555;
62
- background: #E8E8E8;
63
- padding: 4px 5px;
64
- border-radius: 3px;
65
- vertical-align: middle;
66
- }
67
-
68
- div.path a:link, div.path a:visited { color: #333; }
69
- table.coverage {
70
- border-collapse: collapse;
71
- margin: 10px 0 0 0;
72
- padding: 0;
73
- }
74
-
75
- table.coverage td {
76
- margin: 0;
77
- padding: 0;
78
- vertical-align: top;
79
- }
80
- table.coverage td.line-count {
81
- text-align: right;
82
- padding: 0 5px 0 20px;
83
- }
84
- table.coverage td.line-coverage {
85
- text-align: right;
86
- padding-right: 10px;
87
- min-width:20px;
88
- }
89
-
90
- table.coverage td span.cline-any {
91
- display: inline-block;
92
- padding: 0 5px;
93
- width: 100%;
94
- }
95
- .missing-if-branch {
96
- display: inline-block;
97
- margin-right: 5px;
98
- border-radius: 3px;
99
- position: relative;
100
- padding: 0 4px;
101
- background: #333;
102
- color: yellow;
103
- }
104
-
105
- .skip-if-branch {
106
- display: none;
107
- margin-right: 10px;
108
- position: relative;
109
- padding: 0 4px;
110
- background: #ccc;
111
- color: white;
112
- }
113
- .missing-if-branch .typ, .skip-if-branch .typ {
114
- color: inherit !important;
115
- }
116
- .coverage-summary {
117
- border-collapse: collapse;
118
- width: 100%;
119
- }
120
- .coverage-summary tr { border-bottom: 1px solid #bbb; }
121
- .keyline-all { border: 1px solid #ddd; }
122
- .coverage-summary td, .coverage-summary th { padding: 10px; }
123
- .coverage-summary tbody { border: 1px solid #bbb; }
124
- .coverage-summary td { border-right: 1px solid #bbb; }
125
- .coverage-summary td:last-child { border-right: none; }
126
- .coverage-summary th {
127
- text-align: left;
128
- font-weight: normal;
129
- white-space: nowrap;
130
- }
131
- .coverage-summary th.file { border-right: none !important; }
132
- .coverage-summary th.pct { }
133
- .coverage-summary th.pic,
134
- .coverage-summary th.abs,
135
- .coverage-summary td.pct,
136
- .coverage-summary td.abs { text-align: right; }
137
- .coverage-summary td.file { white-space: nowrap; }
138
- .coverage-summary td.pic { min-width: 120px !important; }
139
- .coverage-summary tfoot td { }
140
-
141
- .coverage-summary .sorter {
142
- height: 10px;
143
- width: 7px;
144
- display: inline-block;
145
- margin-left: 0.5em;
146
- background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
147
- }
148
- .coverage-summary .sorted .sorter {
149
- background-position: 0 -20px;
150
- }
151
- .coverage-summary .sorted-desc .sorter {
152
- background-position: 0 -10px;
153
- }
154
- .status-line { height: 10px; }
155
- /* yellow */
156
- .cbranch-no { background: yellow !important; color: #111; }
157
- /* dark red */
158
- .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
159
- .low .chart { border:1px solid #C21F39 }
160
- .highlighted,
161
- .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
162
- background: #C21F39 !important;
163
- }
164
- /* medium red */
165
- .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
166
- /* light red */
167
- .low, .cline-no { background:#FCE1E5 }
168
- /* light green */
169
- .high, .cline-yes { background:rgb(230,245,208) }
170
- /* medium green */
171
- .cstat-yes { background:rgb(161,215,106) }
172
- /* dark green */
173
- .status-line.high, .high .cover-fill { background:rgb(77,146,33) }
174
- .high .chart { border:1px solid rgb(77,146,33) }
175
- /* dark yellow (gold) */
176
- .status-line.medium, .medium .cover-fill { background: #f9cd0b; }
177
- .medium .chart { border:1px solid #f9cd0b; }
178
- /* light yellow */
179
- .medium { background: #fff4c2; }
180
-
181
- .cstat-skip { background: #ddd; color: #111; }
182
- .fstat-skip { background: #ddd; color: #111 !important; }
183
- .cbranch-skip { background: #ddd !important; color: #111; }
184
-
185
- span.cline-neutral { background: #eaeaea; }
186
-
187
- .coverage-summary td.empty {
188
- opacity: .5;
189
- padding-top: 4px;
190
- padding-bottom: 4px;
191
- line-height: 1;
192
- color: #888;
193
- }
194
-
195
- .cover-fill, .cover-empty {
196
- display:inline-block;
197
- height: 12px;
198
- }
199
- .chart {
200
- line-height: 0;
201
- }
202
- .cover-empty {
203
- background: white;
204
- }
205
- .cover-full {
206
- border-right: none !important;
207
- }
208
- pre.prettyprint {
209
- border: none !important;
210
- padding: 0 !important;
211
- margin: 0 !important;
212
- }
213
- .com { color: #999 !important; }
214
- .ignore-none { color: #999; font-weight: normal; }
215
-
216
- .wrapper {
217
- min-height: 100%;
218
- height: auto !important;
219
- height: 100%;
220
- margin: 0 auto -48px;
221
- }
222
- .footer, .push {
223
- height: 48px;
224
- }