termcast 1.5.0 → 1.6.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.
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +22 -5
- package/dist/build.js.map +1 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +7 -1
- package/dist/compile.js.map +1 -1
- package/dist/components/bar-graph.d.ts +4 -4
- package/dist/components/bar-graph.js +2 -2
- package/dist/components/list.d.ts +7 -0
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +74 -11
- package/dist/components/list.js.map +1 -1
- package/dist/examples/list-detail-height-ratchet.d.ts +2 -0
- package/dist/examples/list-detail-height-ratchet.d.ts.map +1 -0
- package/dist/examples/list-detail-height-ratchet.js +26 -0
- package/dist/examples/list-detail-height-ratchet.js.map +1 -0
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +1 -0
- package/dist/extensions/dev.js.map +1 -1
- package/dist/globals.js +8 -0
- package/dist/globals.js.map +1 -1
- package/dist/package-json.d.ts +2 -0
- package/dist/package-json.d.ts.map +1 -1
- package/dist/package-json.js +20 -17
- package/dist/package-json.js.map +1 -1
- package/dist/profiler.d.ts +2 -0
- package/dist/profiler.d.ts.map +1 -0
- package/dist/profiler.js +390 -0
- package/dist/profiler.js.map +1 -0
- package/package.json +14 -15
- package/src/build.tsx +27 -5
- package/src/cli.tsx +0 -0
- package/src/compile.tsx +9 -1
- package/src/compile.vitest.tsx +8 -8
- package/src/components/bar-graph.tsx +9 -9
- package/src/components/list.tsx +92 -11
- package/src/examples/action-shortcut.vitest.tsx +4 -4
- package/src/examples/actions-context.vitest.tsx +2 -2
- package/src/examples/bar-graph-weekly.vitest.tsx +97 -97
- package/src/examples/github.vitest.tsx +17 -26
- package/src/examples/graph-bar-chart.vitest.tsx +36 -36
- package/src/examples/graph-polymarket.vitest.tsx +24 -24
- package/src/examples/graph-row.vitest.tsx +4 -4
- package/src/examples/graph-styles.vitest.tsx +65 -65
- package/src/examples/horizontal-bar-graph-weekly.vitest.tsx +52 -52
- package/src/examples/list-detail-height-ratchet.tsx +48 -0
- package/src/examples/list-detail-height-ratchet.vitest.tsx +161 -0
- package/src/examples/list-detail-metadata.vitest.tsx +49 -49
- package/src/examples/list-dropdown-default.vitest.tsx +27 -27
- package/src/examples/list-fetch-data.vitest.tsx +3 -3
- package/src/examples/list-loading-empty-view.vitest.tsx +1 -1
- package/src/examples/list-no-actions.vitest.tsx +3 -3
- package/src/examples/list-scrollbox.vitest.tsx +6 -6
- package/src/examples/list-spacing-mode.vitest.tsx +1 -1
- package/src/examples/list-with-detail.vitest.tsx +9 -9
- package/src/examples/list-with-dropdown.vitest.tsx +6 -6
- package/src/examples/list-with-sections.vitest.tsx +20 -20
- package/src/examples/list-with-toast.vitest.tsx +4 -4
- package/src/examples/simple-candle-chart.vitest.tsx +61 -59
- package/src/examples/simple-navigation.vitest.tsx +25 -25
- package/src/examples/simple-progress-bar.vitest.tsx +7 -7
- package/src/examples/swift-extension.vitest.tsx +3 -3
- package/src/examples/toast-action.vitest.tsx +4 -4
- package/src/extensions/dev.tsx +2 -1
- package/src/extensions/dev.vitest.tsx +17 -17
- package/src/globals.ts +9 -0
- package/src/package-json.tsx +24 -23
- package/src/profiler.tsx +487 -0
package/src/components/list.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
TextareaRenderable,
|
|
7
7
|
} from '@opentui/core'
|
|
8
8
|
import type { MouseEvent as OpenTUIMouseEvent } from '@opentui/core'
|
|
9
|
-
import { useKeyboard, flushSync } from '@opentui/react'
|
|
9
|
+
import { useKeyboard, flushSync, useTerminalDimensions } from '@opentui/react'
|
|
10
10
|
import React, {
|
|
11
11
|
ReactElement,
|
|
12
12
|
ReactNode,
|
|
@@ -225,8 +225,17 @@ function CurrentItemDetail(props: {
|
|
|
225
225
|
}): any {
|
|
226
226
|
const theme = useTheme()
|
|
227
227
|
const descendantsMap = useListDescendantsRerender()
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
const boxRef = React.useRef<BoxRenderable>(null)
|
|
229
|
+
// Grow-only height ratchet: once the detail panel reaches a certain height,
|
|
230
|
+
// it never shrinks below that. This prevents the footer from jumping up
|
|
231
|
+
// when navigating from a tall detail to a short one.
|
|
232
|
+
const maxHeightRef = React.useRef(0)
|
|
233
|
+
|
|
234
|
+
if (!props.isShowingDetail) {
|
|
235
|
+
// Reset ratchet when detail is hidden so next show starts fresh
|
|
236
|
+
maxHeightRef.current = 0
|
|
237
|
+
return null
|
|
238
|
+
}
|
|
230
239
|
|
|
231
240
|
const currentItem = Object.values(descendantsMap)
|
|
232
241
|
.find((item) => item.index === props.selectedIndex)
|
|
@@ -236,6 +245,14 @@ function CurrentItemDetail(props: {
|
|
|
236
245
|
|
|
237
246
|
return (
|
|
238
247
|
<box
|
|
248
|
+
ref={boxRef}
|
|
249
|
+
minHeight={maxHeightRef.current || undefined}
|
|
250
|
+
onSizeChange={() => {
|
|
251
|
+
const h = boxRef.current?.height ?? 0
|
|
252
|
+
if (h > maxHeightRef.current) {
|
|
253
|
+
maxHeightRef.current = h
|
|
254
|
+
}
|
|
255
|
+
}}
|
|
239
256
|
style={{
|
|
240
257
|
width: '50%',
|
|
241
258
|
paddingLeft: 1,
|
|
@@ -406,6 +423,13 @@ export interface ListProps
|
|
|
406
423
|
searchBarPlaceholder?: string
|
|
407
424
|
selectedItemId?: string
|
|
408
425
|
isShowingDetail?: boolean
|
|
426
|
+
/**
|
|
427
|
+
* Minimum terminal width in columns required to show the detail panel.
|
|
428
|
+
* When the terminal is narrower than this value, the detail panel is
|
|
429
|
+
* automatically hidden even if `isShowingDetail` is true.
|
|
430
|
+
* @default 80
|
|
431
|
+
*/
|
|
432
|
+
detailMinWidth?: number
|
|
409
433
|
/**
|
|
410
434
|
* Controls the vertical spacing of list items.
|
|
411
435
|
* - 'default': Single-line items with title and subtitle on same row
|
|
@@ -1060,6 +1084,7 @@ export const List: ListType = (props) => {
|
|
|
1060
1084
|
isLoading,
|
|
1061
1085
|
navigationTitle,
|
|
1062
1086
|
isShowingDetail,
|
|
1087
|
+
detailMinWidth = 80,
|
|
1063
1088
|
selectedItemId,
|
|
1064
1089
|
searchBarAccessory,
|
|
1065
1090
|
logo,
|
|
@@ -1070,6 +1095,9 @@ export const List: ListType = (props) => {
|
|
|
1070
1095
|
} = props
|
|
1071
1096
|
|
|
1072
1097
|
const theme = useTheme()
|
|
1098
|
+
const { width: terminalWidth } = useTerminalDimensions()
|
|
1099
|
+
const effectiveIsShowingDetail = isShowingDetail && terminalWidth >= detailMinWidth
|
|
1100
|
+
|
|
1073
1101
|
const currentStackSelectedListIndex = useStore((state) => {
|
|
1074
1102
|
const stack = state.navigationStack
|
|
1075
1103
|
const currentItem = stack[stack.length - 1]
|
|
@@ -1262,14 +1290,14 @@ export const List: ListType = (props) => {
|
|
|
1262
1290
|
setSelectedIndex: setSelectedIndexWithPersistence,
|
|
1263
1291
|
searchText,
|
|
1264
1292
|
isFiltering: isFilteringEnabled,
|
|
1265
|
-
isShowingDetail,
|
|
1293
|
+
isShowingDetail: effectiveIsShowingDetail,
|
|
1266
1294
|
customEmptyViewRef,
|
|
1267
1295
|
isLoading,
|
|
1268
1296
|
hasDropdown: !!searchBarAccessory,
|
|
1269
1297
|
spacingMode,
|
|
1270
1298
|
accessoryTagWidths: accessoryTagsLayout,
|
|
1271
1299
|
}),
|
|
1272
|
-
[isDropdownOpen, selectedIndex, searchText, isFilteringEnabled,
|
|
1300
|
+
[isDropdownOpen, selectedIndex, searchText, isFilteringEnabled, effectiveIsShowingDetail, isLoading, searchBarAccessory, spacingMode, accessoryTagsLayout],
|
|
1273
1301
|
)
|
|
1274
1302
|
|
|
1275
1303
|
// Handle selectedItemId prop changes (before paint to avoid flash)
|
|
@@ -1356,6 +1384,46 @@ export const List: ListType = (props) => {
|
|
|
1356
1384
|
}
|
|
1357
1385
|
}
|
|
1358
1386
|
|
|
1387
|
+
// Trigger pagination when the user mouse-scrolls near the bottom of the list.
|
|
1388
|
+
// Only fires on scroll-down so scrolling up near the bottom doesn't spuriously
|
|
1389
|
+
// re-trigger onLoadMore. Uses queueMicrotask because opentui calls onMouseScroll
|
|
1390
|
+
// before ScrollBox.onMouseEvent updates scrollTop in the same call stack;
|
|
1391
|
+
// a microtask runs after the synchronous handler chain finishes.
|
|
1392
|
+
const checkScrollPagination = (event: OpenTUIMouseEvent) => {
|
|
1393
|
+
if (event.scroll?.direction !== 'down') return
|
|
1394
|
+
|
|
1395
|
+
queueMicrotask(() => {
|
|
1396
|
+
const scrollBox = scrollBoxRef.current
|
|
1397
|
+
if (!scrollBox || !props.pagination?.hasMore) return
|
|
1398
|
+
|
|
1399
|
+
// Reset pagination lock when new items arrive (same logic as in move())
|
|
1400
|
+
const items = Object.values(descendantsContext.map.current)
|
|
1401
|
+
.filter((item) => item.index !== -1 && item.props?.visible !== false)
|
|
1402
|
+
if (items.length !== prevItemCountRef.current) {
|
|
1403
|
+
prevItemCountRef.current = items.length
|
|
1404
|
+
paginationCalledRef.current = false
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
if (paginationCalledRef.current) return
|
|
1408
|
+
|
|
1409
|
+
const scrollTop = scrollBox.scrollTop || 0
|
|
1410
|
+
const viewportHeight = scrollBox.viewport?.height || 0
|
|
1411
|
+
const contentHeight = scrollBox.scrollHeight || 0
|
|
1412
|
+
|
|
1413
|
+
// Nothing to paginate if content fits in viewport
|
|
1414
|
+
if (contentHeight <= viewportHeight) return
|
|
1415
|
+
|
|
1416
|
+
// Trigger when within 20% of the bottom (or 3 rows, whichever is larger)
|
|
1417
|
+
const threshold = Math.max(3, Math.floor(viewportHeight * 0.2))
|
|
1418
|
+
const distanceFromBottom = contentHeight - (scrollTop + viewportHeight)
|
|
1419
|
+
|
|
1420
|
+
if (distanceFromBottom <= threshold) {
|
|
1421
|
+
paginationCalledRef.current = true
|
|
1422
|
+
props.pagination.onLoadMore()
|
|
1423
|
+
}
|
|
1424
|
+
})
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1359
1427
|
const move = (direction: -1 | 1) => {
|
|
1360
1428
|
// Get all visible items
|
|
1361
1429
|
const items = Object.values(descendantsContext.map.current)
|
|
@@ -1612,7 +1680,8 @@ export const List: ListType = (props) => {
|
|
|
1612
1680
|
return
|
|
1613
1681
|
}
|
|
1614
1682
|
|
|
1615
|
-
// Ctrl+d
|
|
1683
|
+
// Ctrl+d / Ctrl+u for half-page down/up
|
|
1684
|
+
// Ctrl+f / Ctrl+b for full-page down/up
|
|
1616
1685
|
if (evt.ctrl && evt.name === 'd') {
|
|
1617
1686
|
const viewportHeight = scrollBoxRef.current?.viewport?.height || 20
|
|
1618
1687
|
moveByN(Math.floor(viewportHeight / 2))
|
|
@@ -1625,6 +1694,18 @@ export const List: ListType = (props) => {
|
|
|
1625
1694
|
evt.stopPropagation()
|
|
1626
1695
|
return
|
|
1627
1696
|
}
|
|
1697
|
+
if (evt.ctrl && evt.name === 'f') {
|
|
1698
|
+
const viewportHeight = scrollBoxRef.current?.viewport?.height || 20
|
|
1699
|
+
moveByN(viewportHeight)
|
|
1700
|
+
evt.stopPropagation()
|
|
1701
|
+
return
|
|
1702
|
+
}
|
|
1703
|
+
if (evt.ctrl && evt.name === 'b') {
|
|
1704
|
+
const viewportHeight = scrollBoxRef.current?.viewport?.height || 20
|
|
1705
|
+
moveByN(-viewportHeight)
|
|
1706
|
+
evt.stopPropagation()
|
|
1707
|
+
return
|
|
1708
|
+
}
|
|
1628
1709
|
|
|
1629
1710
|
// / to enter search mode
|
|
1630
1711
|
if (evt.sequence === '/' && !evt.ctrl && !evt.meta) {
|
|
@@ -1799,14 +1880,15 @@ export const List: ListType = (props) => {
|
|
|
1799
1880
|
{/* Main content area with optional detail view */}
|
|
1800
1881
|
<box style={{ flexDirection: 'row', flexGrow: 1, flexShrink: 1 }}>
|
|
1801
1882
|
{/* List content - render children which will register themselves */}
|
|
1802
|
-
<box style={{ width:
|
|
1883
|
+
<box style={{ width: effectiveIsShowingDetail ? '50%' : '100%', flexGrow: 1, flexShrink: 1, flexDirection: 'column' }}>
|
|
1803
1884
|
{/* Scrollable list items */}
|
|
1804
1885
|
<ScrollBox
|
|
1805
1886
|
ref={scrollBoxRef}
|
|
1806
1887
|
focused={false}
|
|
1807
1888
|
flexGrow={1}
|
|
1808
1889
|
flexShrink={1}
|
|
1809
|
-
minHeight={
|
|
1890
|
+
minHeight={10}
|
|
1891
|
+
onMouseScroll={checkScrollPagination}
|
|
1810
1892
|
style={{
|
|
1811
1893
|
rootOptions: {
|
|
1812
1894
|
backgroundColor: undefined,
|
|
@@ -1836,7 +1918,7 @@ export const List: ListType = (props) => {
|
|
|
1836
1918
|
{/* Detail panel on the right */}
|
|
1837
1919
|
<CurrentItemDetail
|
|
1838
1920
|
selectedIndex={selectedIndex}
|
|
1839
|
-
isShowingDetail={
|
|
1921
|
+
isShowingDetail={effectiveIsShowingDetail}
|
|
1840
1922
|
/>
|
|
1841
1923
|
</box>
|
|
1842
1924
|
</box>
|
|
@@ -1990,8 +2072,7 @@ const ListItem: ListItemType = (props) => {
|
|
|
1990
2072
|
}
|
|
1991
2073
|
}
|
|
1992
2074
|
|
|
1993
|
-
|
|
1994
|
-
const showAccessories = !props.detail && props.accessories
|
|
2075
|
+
const showAccessories = Boolean(props.accessories)
|
|
1995
2076
|
|
|
1996
2077
|
// Get icon string and color from props.icon (can be string or object with value/tintColor)
|
|
1997
2078
|
const { iconValue, iconColor } = (() => {
|
|
@@ -49,7 +49,7 @@ test('ctrl+r shortcut should trigger Refresh action directly', async () => {
|
|
|
49
49
|
|
|
50
50
|
> Search...
|
|
51
51
|
|
|
52
|
-
›
|
|
52
|
+
›Refres...unt: 1Press ctrl+r to refresh...ter then select Refresh
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
|
|
@@ -57,11 +57,11 @@ test('ctrl+r shortcut should trigger Refresh action directly', async () => {
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
↵ refresh ↑↓ navigate ^k actions :vim
|
|
61
60
|
|
|
62
61
|
|
|
63
62
|
|
|
64
63
|
|
|
64
|
+
↵ refresh ↑↓ navigate ^k actions :vim
|
|
65
65
|
"
|
|
66
66
|
`)
|
|
67
67
|
}, 30000)
|
|
@@ -85,6 +85,7 @@ test('action shortcut is displayed in action panel', async () => {
|
|
|
85
85
|
expect(actionsPanel).toMatchInlineSnapshot(`
|
|
86
86
|
"
|
|
87
87
|
|
|
88
|
+
|
|
88
89
|
╭────────────────────────────────────────────────────────────────╮
|
|
89
90
|
│ │
|
|
90
91
|
│ Actions esc │
|
|
@@ -102,8 +103,7 @@ test('action shortcut is displayed in action panel', async () => {
|
|
|
102
103
|
│ │
|
|
103
104
|
│ │
|
|
104
105
|
│ │
|
|
105
|
-
│ ↵ select ↑↓ navigate │
|
|
106
|
-
│ │"
|
|
106
|
+
│ ↵ select ↑↓ navigate │"
|
|
107
107
|
`)
|
|
108
108
|
}, 30000)
|
|
109
109
|
|
|
@@ -38,6 +38,7 @@ test('actions preserve React context through portal', async () => {
|
|
|
38
38
|
expect(actionsPanel).toMatchInlineSnapshot(`
|
|
39
39
|
"
|
|
40
40
|
|
|
41
|
+
|
|
41
42
|
╭────────────────────────────────────────────────────────────────╮
|
|
42
43
|
│ │
|
|
43
44
|
│ Actions esc │
|
|
@@ -55,8 +56,7 @@ test('actions preserve React context through portal', async () => {
|
|
|
55
56
|
│ │
|
|
56
57
|
│ │
|
|
57
58
|
│ │
|
|
58
|
-
│ ↵ select ↑↓ navigate │
|
|
59
|
-
│ │"
|
|
59
|
+
│ ↵ select ↑↓ navigate │"
|
|
60
60
|
`)
|
|
61
61
|
|
|
62
62
|
// Select "Show Counter" (first action, already selected)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// E2E tests for BarGraph vertical stacked bar chart.
|
|
2
|
-
// Bar segments use
|
|
2
|
+
// Bar segments use █ (full block) chars for solid, gap-free columns.
|
|
3
3
|
|
|
4
4
|
import { test, expect, afterEach, beforeEach } from 'vitest'
|
|
5
5
|
import { launchTerminal, Session } from 'tuistory/src'
|
|
@@ -35,28 +35,28 @@ test('bar graph renders bars, labels, and legend', async () => {
|
|
|
35
35
|
|
|
36
36
|
> Search...
|
|
37
37
|
|
|
38
|
-
›
|
|
39
|
-
|
|
40
|
-
Server Load CPU / Memory / IO │ 82.5
|
|
41
|
-
Many ...
|
|
42
|
-
Many Series (8) Legend overflow test │ 55.0
|
|
43
|
-
|
|
44
|
-
Week 1 vs Week 2 Two graphs in a Row │ 27.5
|
|
45
|
-
│
|
|
46
|
-
│ 0.0
|
|
47
|
-
│ Mon Tue Wed Thu
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
38
|
+
›Weekly Traffi 3 channel...oss 6 days │ 110.0│ ██
|
|
39
|
+
Revenue by Regio EMEA / A...Americas │ │██ ██ ██ ██
|
|
40
|
+
Server Load CPU / Memory / IO │ 82.5│██ ██ ██ ██
|
|
41
|
+
Many C...ns (20)Overflow...h 20 bars │ │██ ██ ██ ██ ██
|
|
42
|
+
Many Series (8) Legend overflow test │ 55.0│██ ██ ██ ██ ██ ██
|
|
43
|
+
Long Label Labels wide...bar columns │ │██ ██ ██ ██ ██ ██
|
|
44
|
+
Week 1 vs Week 2 Two graphs in a Row │ 27.5│██ ██ ██ ██ ██ ██
|
|
45
|
+
│ │██ ██ ██ ██ ██ ██
|
|
46
|
+
│ 0.0│██ ██ ██ ██ ██ ██
|
|
47
|
+
│ Mon Tue Wed Thu FriSat
|
|
48
|
+
│ ■ Direct ■ Organic ■ Referral
|
|
49
|
+
│
|
|
50
|
+
│
|
|
51
|
+
│
|
|
52
|
+
│
|
|
53
|
+
│
|
|
54
|
+
│
|
|
55
|
+
│
|
|
56
|
+
│
|
|
57
|
+
│
|
|
58
|
+
│
|
|
59
|
+
↵ open detail ↑↓ navigate ^k act │
|
|
60
60
|
|
|
61
61
|
"
|
|
62
62
|
`)
|
|
@@ -64,7 +64,7 @@ test('bar graph renders bars, labels, and legend', async () => {
|
|
|
64
64
|
expect(text).toContain('Mon')
|
|
65
65
|
expect(text).toContain('Direct')
|
|
66
66
|
expect(text).toContain('0.0│')
|
|
67
|
-
expect(text).toContain('
|
|
67
|
+
expect(text).toContain('█')
|
|
68
68
|
}, 30000)
|
|
69
69
|
|
|
70
70
|
test('many columns (20) clips with overflow hidden', async () => {
|
|
@@ -75,7 +75,7 @@ test('many columns (20) clips with overflow hidden', async () => {
|
|
|
75
75
|
session.sendKey('down')
|
|
76
76
|
|
|
77
77
|
await session.text({
|
|
78
|
-
waitFor: (t) => t.includes('›Many
|
|
78
|
+
waitFor: (t) => t.includes('›Many') && t.includes('(20)'),
|
|
79
79
|
timeout: 10000,
|
|
80
80
|
})
|
|
81
81
|
await session.waitIdle()
|
|
@@ -83,13 +83,13 @@ test('many columns (20) clips with overflow hidden', async () => {
|
|
|
83
83
|
|
|
84
84
|
// Bar graph rendering has non-deterministic ANSI highlights, so use toContain checks
|
|
85
85
|
// instead of inline snapshot for the bars area
|
|
86
|
-
expect(text).toContain('›Many
|
|
86
|
+
expect(text).toContain('›Many')
|
|
87
87
|
expect(text).toContain('BarGraph Showcase')
|
|
88
|
-
expect(text).toContain('
|
|
88
|
+
expect(text).toContain('█')
|
|
89
89
|
|
|
90
90
|
// Some labels visible, overflow clips the rest
|
|
91
91
|
expect(text).toContain('D')
|
|
92
|
-
expect(text).toContain('
|
|
92
|
+
expect(text).toContain('█')
|
|
93
93
|
}, 30000)
|
|
94
94
|
|
|
95
95
|
test('many series (8) bottom legend clips on one row', async () => {
|
|
@@ -113,28 +113,28 @@ test('many series (8) bottom legend clips on one row', async () => {
|
|
|
113
113
|
|
|
114
114
|
> Search...
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Server Load CPU / Memory / IO │ 246.0
|
|
119
|
-
Many ...
|
|
120
|
-
›Many Series (8) Legend overflow test │ 164.0
|
|
121
|
-
|
|
122
|
-
Week 1 vs Week 2 Two graphs in a Row │ 82.0
|
|
123
|
-
│
|
|
124
|
-
│ 0.0
|
|
125
|
-
│ Mon Tue Wed Thu
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
116
|
+
Weekly Traffi 3 channel...oss 6 days │ 328.0│██ ██ ██ ██ ██
|
|
117
|
+
Revenue by Regio EMEA / A...Americas │ │██ ██ ██ ██ ██ ██
|
|
118
|
+
Server Load CPU / Memory / IO │ 246.0│██ ██ ██ ██ ██ ██
|
|
119
|
+
Many C...ns (20)Overflow...h 20 bars │ │██ ██ ██ ██ ██ ██
|
|
120
|
+
›Many Series (8) Legend overflow test │ 164.0│██ ██ ██ ██ ██ ██
|
|
121
|
+
Long Label Labels wide...bar columns │ │██ ██ ██ ██ ██ ██
|
|
122
|
+
Week 1 vs Week 2 Two graphs in a Row │ 82.0│██ ██ ██ ██ ██ ██
|
|
123
|
+
│ │██ ██ ██ ██ ██ ██
|
|
124
|
+
│ 0.0│██ ██ ██ ██ ██ ██
|
|
125
|
+
│ Mon Tue Wed Thu FriSat
|
|
126
|
+
│ ■ Series 1 ■ Series 2 ■ Series 3
|
|
127
|
+
│
|
|
128
|
+
│
|
|
129
|
+
│
|
|
130
|
+
│
|
|
131
|
+
│
|
|
132
|
+
│
|
|
133
|
+
│
|
|
134
|
+
│
|
|
135
|
+
│
|
|
136
|
+
│
|
|
137
|
+
↑↓ navigate ^k actions :vim │
|
|
138
138
|
|
|
139
139
|
"
|
|
140
140
|
`)
|
|
@@ -142,11 +142,11 @@ test('many series (8) bottom legend clips on one row', async () => {
|
|
|
142
142
|
// Bottom legend is a single clipped row by default.
|
|
143
143
|
expect(text).toContain('Series 1')
|
|
144
144
|
expect(text).toContain('Series 3')
|
|
145
|
-
expect(text).toContain('
|
|
145
|
+
expect(text).toContain('█')
|
|
146
146
|
}, 30000)
|
|
147
147
|
|
|
148
148
|
test('long labels truncated by overflow hidden', async () => {
|
|
149
|
-
await session.text({ waitFor: (t) => t.includes('
|
|
149
|
+
await session.text({ waitFor: (t) => t.includes('Labels wide'), timeout: 10000 })
|
|
150
150
|
// Navigate: Weekly, Revenue, Server, Many Columns, Many Series, Long Labels = 5 downs
|
|
151
151
|
session.sendKey('down')
|
|
152
152
|
session.sendKey('down')
|
|
@@ -155,7 +155,7 @@ test('long labels truncated by overflow hidden', async () => {
|
|
|
155
155
|
session.sendKey('down')
|
|
156
156
|
|
|
157
157
|
const text = await session.text({
|
|
158
|
-
waitFor: (t) => t.includes('›Lon...bels'),
|
|
158
|
+
waitFor: (t) => t.includes('›Long Label') || t.includes('›Lon...bels'),
|
|
159
159
|
timeout: 10000,
|
|
160
160
|
})
|
|
161
161
|
|
|
@@ -167,34 +167,34 @@ test('long labels truncated by overflow hidden', async () => {
|
|
|
167
167
|
|
|
168
168
|
> Search...
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
Server Load CPU / Memory / IO │ 56.3
|
|
173
|
-
Many ...
|
|
174
|
-
Many Series (8) Legend overflow test │ 37.5
|
|
175
|
-
›
|
|
176
|
-
Week 1 vs Week 2 Two graphs in a Row │ 18.8
|
|
177
|
-
│
|
|
178
|
-
│ 0.0
|
|
170
|
+
Weekly Traffi 3 channel...oss 6 days │ 75.0│ ██
|
|
171
|
+
Revenue by Regio EMEA / A...Americas │ │██ ██ ██
|
|
172
|
+
Server Load CPU / Memory / IO │ 56.3│██ ██ ██ ██
|
|
173
|
+
Many C...ns (20)Overflow...h 20 bars │ │██ ██ ██ ██
|
|
174
|
+
Many Series (8) Legend overflow test │ 37.5│██ ██ ██ ██ ██
|
|
175
|
+
›Long Label Labels wide...bar columns │ │██ ██ ██ ██ ██ ██
|
|
176
|
+
Week 1 vs Week 2 Two graphs in a Row │ 18.8│██ ██ ██ ██ ██ ██
|
|
177
|
+
│ │██ ██ ██ ██ ██ ██
|
|
178
|
+
│ 0.0│██ ██ ██ ██ ██ ██
|
|
179
179
|
│ Monday Thursday
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
180
|
+
│ ■ Views ■ Clicks
|
|
181
|
+
│
|
|
182
|
+
│
|
|
183
|
+
│
|
|
184
|
+
│
|
|
185
|
+
│
|
|
186
|
+
│
|
|
187
|
+
│
|
|
188
|
+
│
|
|
189
|
+
│
|
|
190
|
+
│
|
|
191
|
+
↑↓ navigate ^k actions :vim │
|
|
192
192
|
|
|
193
193
|
"
|
|
194
194
|
`)
|
|
195
195
|
|
|
196
|
-
expect(text).toContain('
|
|
197
|
-
expect(text).toContain('
|
|
196
|
+
expect(text).toContain('Labels wide')
|
|
197
|
+
expect(text).toContain('█')
|
|
198
198
|
}, 30000)
|
|
199
199
|
|
|
200
200
|
test('side-by-side bar graphs in a Row', async () => {
|
|
@@ -220,28 +220,28 @@ test('side-by-side bar graphs in a Row', async () => {
|
|
|
220
220
|
|
|
221
221
|
> Search...
|
|
222
222
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
Server Load CPU / Memory / IO │ 82.5
|
|
226
|
-
Many ...
|
|
227
|
-
Many Series (8) Legend overflow test │ 55.0
|
|
228
|
-
|
|
229
|
-
›Week 1 vs Week 2 Two graphs in a Row │ 27.5
|
|
230
|
-
│
|
|
231
|
-
│ 0.0
|
|
223
|
+
Weekly Traffi 3 channel...oss 6 days │ 110.0│ 130.0│
|
|
224
|
+
Revenue by Regio EMEA / A...Americas │ │██ ██ │██
|
|
225
|
+
Server Load CPU / Memory / IO │ 82.5│██ ██ 97.5│██ ██
|
|
226
|
+
Many C...ns (20)Overflow...h 20 bars │ │██ ██ ██ │██ ██ ██
|
|
227
|
+
Many Series (8) Legend overflow test │ 55.0│██ ██ ██ 65.0│██ ██ ██
|
|
228
|
+
Long Label Labels wide...bar columns │ │██ ██ ██ │██ ██ ██
|
|
229
|
+
›Week 1 vs Week 2 Two graphs in a Row │ 27.5│██ ██ ██ 32.5│██ ██ ██
|
|
230
|
+
│ │██ ██ ██ │██ ██ ██
|
|
231
|
+
│ 0.0│██ ██ ██ 0.0│██ ██ ██
|
|
232
232
|
│ Mon Tue Wed Mon Tue We
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
233
|
+
│ ■ Direct ■ Organ ■ Direct ■ Orga
|
|
234
|
+
│
|
|
235
|
+
│
|
|
236
|
+
│
|
|
237
|
+
│
|
|
238
|
+
│
|
|
239
|
+
│
|
|
240
|
+
│
|
|
241
|
+
│
|
|
242
|
+
│
|
|
243
|
+
│
|
|
244
|
+
↵ open detail ↑↓ navigate ^k act │
|
|
245
245
|
|
|
246
246
|
"
|
|
247
247
|
`)
|
|
@@ -54,22 +54,13 @@ afterEach(() => {
|
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
test.skipIf(!extensionExists)('github extension shows command list on launch', async () => {
|
|
57
|
-
// Wait for command list to appear (extension has multiple commands)
|
|
58
|
-
// Don't match "Commands" alone - it falsely matches "Building 18 commands..." build log
|
|
59
57
|
const initialView = await session.text({
|
|
60
|
-
waitFor: (text) =>
|
|
58
|
+
waitFor: (text) => text.includes('My Pul...quests') && text.includes('Search Repositorie'),
|
|
61
59
|
timeout: 30000,
|
|
62
60
|
})
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
await session.text({
|
|
67
|
-
waitFor: (text) => text.includes('My Pu...uest') && text.includes('Search ...sitories'),
|
|
68
|
-
timeout: 30000,
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
expect(initialView).toContain('My Pu...uest')
|
|
72
|
-
expect(initialView).toContain('Search ...sitories')
|
|
62
|
+
expect(initialView).toContain('My Pul...quests')
|
|
63
|
+
expect(initialView).toContain('Search Repositorie')
|
|
73
64
|
expect(initialView).toMatchInlineSnapshot(`
|
|
74
65
|
"
|
|
75
66
|
|
|
@@ -79,19 +70,19 @@ test.skipIf(!extensionExists)('github extension shows command list on launch', a
|
|
|
79
70
|
> Search commands...
|
|
80
71
|
|
|
81
72
|
Commands
|
|
82
|
-
›My
|
|
83
|
-
Search
|
|
84
|
-
Create
|
|
73
|
+
›My Pul...questsList pull requests you cr... in, or were mentioned in. view
|
|
74
|
+
Search Pull Request Search recent pull requ...ly in all repositories. view
|
|
75
|
+
Create Pull Reques Create a pull request i...our GitHub repositories. view
|
|
85
76
|
My IssuesList issues created by you, ...ned to you or mentioning you. view
|
|
86
77
|
Search Issues Search recent issues globally in all repositories. view
|
|
87
78
|
Create Issue Create an issue in one of your GitHub repositories. view
|
|
88
79
|
Create Branch Create a branch in one of your GitHub repositories view
|
|
89
|
-
Search
|
|
80
|
+
Search Repositorie Search in your public o...te repositories by name. view
|
|
90
81
|
My Latest Repositories List your repositories by latest updated view
|
|
91
82
|
My Starred Repositories List repositories you have starred view
|
|
92
83
|
Workflow Runs Manage workflow runs for a selected GitHub repository. view
|
|
93
|
-
|
|
94
|
-
Search
|
|
84
|
+
Notification List inbox notifications f...s or a selected repository. view
|
|
85
|
+
Search DiscussionsSearch recent Discussion...ally in all repositories view
|
|
95
86
|
My Discussions Show your Discussions view
|
|
96
87
|
My Projects Show your Projects view
|
|
97
88
|
|
|
@@ -108,7 +99,7 @@ test.skipIf(!extensionExists)('github extension shows command list on launch', a
|
|
|
108
99
|
test.skipIf(!extensionExists)('github extension can navigate commands', async () => {
|
|
109
100
|
// Wait for command list
|
|
110
101
|
await session.text({
|
|
111
|
-
waitFor: (text) => text.includes('My
|
|
102
|
+
waitFor: (text) => text.includes('My Pul...quests') && text.includes('Search Repositorie'),
|
|
112
103
|
timeout: 30000,
|
|
113
104
|
})
|
|
114
105
|
|
|
@@ -128,19 +119,19 @@ test.skipIf(!extensionExists)('github extension can navigate commands', async ()
|
|
|
128
119
|
> Search commands...
|
|
129
120
|
|
|
130
121
|
Commands
|
|
131
|
-
My
|
|
132
|
-
Search
|
|
133
|
-
›Create
|
|
122
|
+
My Pul...questsList pull requests you cr... in, or were mentioned in. view
|
|
123
|
+
Search Pull Request Search recent pull requ...ly in all repositories. view
|
|
124
|
+
›Create Pull Reques Create a pull request i...our GitHub repositories. view
|
|
134
125
|
My IssuesList issues created by you, ...ned to you or mentioning you. view
|
|
135
126
|
Search Issues Search recent issues globally in all repositories. view
|
|
136
127
|
Create Issue Create an issue in one of your GitHub repositories. view
|
|
137
128
|
Create Branch Create a branch in one of your GitHub repositories view
|
|
138
|
-
Search
|
|
129
|
+
Search Repositorie Search in your public o...te repositories by name. view
|
|
139
130
|
My Latest Repositories List your repositories by latest updated view
|
|
140
131
|
My Starred Repositories List repositories you have starred view
|
|
141
132
|
Workflow Runs Manage workflow runs for a selected GitHub repository. view
|
|
142
|
-
|
|
143
|
-
Search
|
|
133
|
+
Notification List inbox notifications f...s or a selected repository. view
|
|
134
|
+
Search DiscussionsSearch recent Discussion...ally in all repositories view
|
|
144
135
|
My Discussions Show your Discussions view
|
|
145
136
|
My Projects Show your Projects view
|
|
146
137
|
|
|
@@ -239,11 +230,11 @@ test.skipIf(!extensionExists)('github extension can search commands', async () =
|
|
|
239
230
|
|
|
240
231
|
|
|
241
232
|
|
|
242
|
-
↵ run command ↑↓ navigate ^k actions :vim powered by termcast.app
|
|
243
233
|
|
|
244
234
|
|
|
245
235
|
|
|
246
236
|
|
|
237
|
+
↵ run command ↑↓ navigate ^k actions :vim powered by termcast.app
|
|
247
238
|
|
|
248
239
|
|
|
249
240
|
|