tui-td 0.2.21 → 0.2.22
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -1
- data/bin/check_tans_parser.sh +21 -0
- data/lib/tui_td/matchers.rb +111 -66
- data/lib/tui_td/mcp/server.rb +11 -1
- data/lib/tui_td/minitest/assertions.rb +70 -40
- data/lib/tui_td/test_runner.rb +32 -14
- data/lib/tui_td/version.rb +1 -1
- data/lib/tui_td.rb +13 -13
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01ea7851a70d867ca80389e3c824d6fb6b5874c6d24b5f8faf26b5daa23ee50c
|
|
4
|
+
data.tar.gz: 5a71d54ef5c978d300ee9d912852a98c04c03489270e06241fea2236b7d6c81b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd5f7d8a501a056e40033d1fd97f99c1fa15b3e6c8a352836acd5ab1e899d0d65f98c9c7e0d0b12fb13c1c199ade39b041ff292164094e5bd894593ff0f31afd
|
|
7
|
+
data.tar.gz: bf225f89e3270971bbbe0968a6bab9b7cb6761a5746d935211f1f6843dca48940917360feb69bed43e3a565d7a2aefe8f6e45b9d1a7ead94855a0f094bc67fdc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,39 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
## 0.2.
|
|
3
|
+
## 0.2.22
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **tans-parser 0.1.5 integration**: Confidence scoring for UI element detection
|
|
8
|
+
- `Element#confidence` attribute (0.0–1.0) — higher values indicate more reliable detection
|
|
9
|
+
- `Element#confident?` — returns true when confidence ≥ 0.5 or nil
|
|
10
|
+
- RSpec matchers: `min_confidence:` keyword on `have_button`, `have_dialog`,
|
|
11
|
+
`have_checkbox`, `have_input`, `have_label`, `have_menu`, `have_tab`,
|
|
12
|
+
`have_statusbar`, `have_progress_bar`, `have_role`
|
|
13
|
+
- JSON test steps: `min_confidence` field on all `assert_*` role steps
|
|
14
|
+
- MCP `tui_find_elements`: `min_confidence` argument and `[conf=...]` in output
|
|
15
|
+
- Minitest assertions: `min_confidence:` keyword on all selector-based assertions
|
|
16
|
+
- Confidence attribute visible in `Element#to_h`
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Reduced false positives from tans-parser 0.1.5 (numeric brackets, short progress bars,
|
|
21
|
+
digit-colon patterns, URL schemes are now excluded)
|
|
22
|
+
- Dialog detection confidence boosted for titled borders (+0.05)
|
|
23
|
+
- Multi-word labels get higher confidence (0.85 vs 0.8)
|
|
24
|
+
- Tab confidence varies by count (≥3 tabs → 0.85, otherwise 0.7)
|
|
25
|
+
- `TestRunner#check_role` includes confidence scores in result messages
|
|
26
|
+
- Minitest assertions pass through `min_confidence` to element detection
|
|
27
|
+
|
|
28
|
+
### Testing
|
|
29
|
+
|
|
30
|
+
- 8 new confidence-specific spec tests (matchers_spec.rb)
|
|
31
|
+
- All 440 RSpec tests pass, all smoke tests pass (91/91 MCP, 11/11 Minitest)
|
|
32
|
+
- SimpleCov coverage tracking with minimum threshold (84.0%)
|
|
33
|
+
|
|
34
|
+
## 0.2.20 (yanked — incorrect tans-parser dependency)
|
|
35
|
+
|
|
36
|
+
## 0.2.21
|
|
4
37
|
|
|
5
38
|
### Added
|
|
6
39
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Check for new tans-parser versions and integrate if found
|
|
3
|
+
# Called by crontab every 15 minutes
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
cd /Users/halukdurmus/Development/tui-td
|
|
8
|
+
|
|
9
|
+
# Get the latest tans-parser version
|
|
10
|
+
LATEST=$(gem search tans-parser --remote --exact 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -1)
|
|
11
|
+
CURRENT=$(grep "tans-parser" Gemfile.lock | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
|
|
12
|
+
|
|
13
|
+
echo "$(date): Latest tans-parser: $LATEST, Current: $CURRENT"
|
|
14
|
+
|
|
15
|
+
if [ "$LATEST" != "$CURRENT" ] && [ -n "$LATEST" ]; then
|
|
16
|
+
echo "$(date): New version $LATEST detected! Triggering integration..."
|
|
17
|
+
# Write a trigger file for the next claude session to pick up
|
|
18
|
+
echo "$LATEST" > /tmp/tui_td_tans_parser_update_trigger
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
exit 0
|
data/lib/tui_td/matchers.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# rubocop:disable Metrics/ModuleLength, Metrics/
|
|
3
|
+
# rubocop:disable Metrics/ModuleLength, Metrics/ParameterLists, Layout/LineLength, Metrics/BlockLength
|
|
4
4
|
|
|
5
5
|
require "rspec/expectations"
|
|
6
6
|
|
|
@@ -167,29 +167,58 @@ module TUITD
|
|
|
167
167
|
|
|
168
168
|
# Selector-based matchers — work with both State and Driver (auto-wait)
|
|
169
169
|
|
|
170
|
-
RSpec::Matchers.define :have_button do |expected|
|
|
170
|
+
RSpec::Matchers.define :have_button do |expected, min_confidence: nil|
|
|
171
171
|
match do |actual|
|
|
172
172
|
Matchers.auto_wait(actual) do |s|
|
|
173
|
-
Selector.new(s).button(text: expected)
|
|
173
|
+
el = Selector.new(s).button(text: expected)
|
|
174
|
+
if min_confidence && el
|
|
175
|
+
el.confidence && el.confidence >= min_confidence
|
|
176
|
+
else
|
|
177
|
+
el
|
|
178
|
+
end
|
|
174
179
|
end
|
|
175
180
|
end
|
|
176
181
|
|
|
177
|
-
description
|
|
178
|
-
|
|
179
|
-
|
|
182
|
+
description do
|
|
183
|
+
desc = "have button #{expected.inspect}"
|
|
184
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
185
|
+
desc
|
|
186
|
+
end
|
|
187
|
+
failure_message do |_actual|
|
|
188
|
+
desc = "expected terminal to have a button #{expected.inspect}"
|
|
189
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
190
|
+
desc
|
|
191
|
+
end
|
|
192
|
+
failure_message_when_negated do |_actual|
|
|
193
|
+
"expected terminal NOT to have a button #{expected.inspect}"
|
|
194
|
+
end
|
|
180
195
|
end
|
|
181
196
|
|
|
182
|
-
RSpec::Matchers.define :have_dialog do
|
|
197
|
+
RSpec::Matchers.define :have_dialog do |min_confidence: nil|
|
|
183
198
|
match do |actual|
|
|
184
|
-
Matchers.auto_wait(actual)
|
|
199
|
+
Matchers.auto_wait(actual) do |s|
|
|
200
|
+
elements = Selector.new(s).dialogs
|
|
201
|
+
elements = elements.select { |e| e.confidence && e.confidence >= min_confidence } if min_confidence
|
|
202
|
+
elements.any?
|
|
203
|
+
end
|
|
185
204
|
end
|
|
186
205
|
|
|
187
|
-
description
|
|
188
|
-
|
|
189
|
-
|
|
206
|
+
description do
|
|
207
|
+
desc = "have a dialog"
|
|
208
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
209
|
+
desc
|
|
210
|
+
end
|
|
211
|
+
failure_message do |_actual|
|
|
212
|
+
desc = "expected terminal to have a dialog"
|
|
213
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
214
|
+
desc
|
|
215
|
+
end
|
|
216
|
+
failure_message_when_negated do |_actual|
|
|
217
|
+
"expected terminal NOT to have a dialog"
|
|
218
|
+
end
|
|
190
219
|
end
|
|
191
220
|
|
|
192
|
-
RSpec::Matchers.define :have_checkbox do |expected|
|
|
221
|
+
RSpec::Matchers.define :have_checkbox do |expected, min_confidence: nil|
|
|
193
222
|
chain(:checked) { @checked = true }
|
|
194
223
|
chain(:unchecked) { @checked = false }
|
|
195
224
|
|
|
@@ -197,7 +226,12 @@ module TUITD
|
|
|
197
226
|
Matchers.auto_wait(actual) do |s|
|
|
198
227
|
filters = { text: expected }
|
|
199
228
|
filters[:checked] = @checked unless @checked.nil?
|
|
200
|
-
Selector.new(s).checkbox(**filters)
|
|
229
|
+
el = Selector.new(s).checkbox(**filters)
|
|
230
|
+
if min_confidence && el
|
|
231
|
+
el.confidence && el.confidence >= min_confidence
|
|
232
|
+
else
|
|
233
|
+
el
|
|
234
|
+
end
|
|
201
235
|
end
|
|
202
236
|
end
|
|
203
237
|
|
|
@@ -205,12 +239,14 @@ module TUITD
|
|
|
205
239
|
desc = "have checkbox #{expected.inspect}"
|
|
206
240
|
desc += " (checked)" if @checked == true
|
|
207
241
|
desc += " (unchecked)" if @checked == false
|
|
242
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
208
243
|
desc
|
|
209
244
|
end
|
|
210
245
|
failure_message do |_actual|
|
|
211
246
|
desc = "expected terminal to have checkbox #{expected.inspect}"
|
|
212
247
|
desc += " (checked)" if @checked == true
|
|
213
248
|
desc += " (unchecked)" if @checked == false
|
|
249
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
214
250
|
desc
|
|
215
251
|
end
|
|
216
252
|
failure_message_when_negated do |_actual|
|
|
@@ -220,15 +256,16 @@ module TUITD
|
|
|
220
256
|
desc
|
|
221
257
|
end
|
|
222
258
|
end
|
|
223
|
-
|
|
224
|
-
RSpec::Matchers.define :have_role do |role, text: nil, checked: nil, disabled: nil|
|
|
259
|
+
RSpec::Matchers.define :have_role do |role, text: nil, checked: nil, disabled: nil, min_confidence: nil|
|
|
225
260
|
match do |actual|
|
|
226
261
|
Matchers.auto_wait(actual) do |s|
|
|
227
262
|
filters = {}
|
|
228
263
|
filters[:text] = text if text
|
|
229
264
|
filters[:checked] = checked unless checked.nil?
|
|
230
265
|
filters[:disabled] = disabled unless disabled.nil?
|
|
231
|
-
Selector.new(s).get_by_role(role, **filters)
|
|
266
|
+
elements = Selector.new(s).get_by_role(role, **filters)
|
|
267
|
+
elements = elements.select { |e| e.confidence && e.confidence >= min_confidence } if min_confidence
|
|
268
|
+
elements.any?
|
|
232
269
|
end
|
|
233
270
|
end
|
|
234
271
|
|
|
@@ -237,6 +274,7 @@ module TUITD
|
|
|
237
274
|
desc += " with text #{text.inspect}" if text
|
|
238
275
|
desc += " (checked)" if checked == true
|
|
239
276
|
desc += " (disabled)" if disabled == true
|
|
277
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
240
278
|
desc
|
|
241
279
|
end
|
|
242
280
|
failure_message do |_actual|
|
|
@@ -244,30 +282,37 @@ module TUITD
|
|
|
244
282
|
desc += " with text #{text.inspect}" if text
|
|
245
283
|
desc += " (checked)" if checked == true
|
|
246
284
|
desc += " (disabled)" if disabled == true
|
|
285
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
247
286
|
desc
|
|
248
287
|
end
|
|
249
288
|
failure_message_when_negated do |_actual|
|
|
250
289
|
desc = "expected terminal NOT to have a :#{role}"
|
|
251
290
|
desc += " with text #{text.inspect}" if text
|
|
291
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
252
292
|
desc
|
|
253
293
|
end
|
|
254
294
|
end
|
|
295
|
+
# rubocop:enable Metrics/BlockLength
|
|
255
296
|
|
|
256
|
-
# New role matchers (tans-parser 0.1.2)
|
|
297
|
+
# New role matchers (tans-parser 0.1.2+) with confidence support (0.1.5+)
|
|
257
298
|
|
|
258
|
-
RSpec::Matchers.define :have_input do |expected = nil|
|
|
299
|
+
RSpec::Matchers.define :have_input do |expected = nil, min_confidence: nil|
|
|
259
300
|
match do |actual|
|
|
260
301
|
Matchers.auto_wait(actual) do |s|
|
|
261
302
|
if expected
|
|
262
|
-
Selector.new(s).input(text: expected)
|
|
303
|
+
el = Selector.new(s).input(text: expected)
|
|
304
|
+
min_confidence ? (el&.confidence && el.confidence >= min_confidence) : el
|
|
263
305
|
else
|
|
264
|
-
Selector.new(s).inputs
|
|
306
|
+
elements = Selector.new(s).inputs
|
|
307
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
265
308
|
end
|
|
266
309
|
end
|
|
267
310
|
end
|
|
268
311
|
|
|
269
312
|
description do
|
|
270
|
-
expected ? "have input #{expected.inspect}" : "have an input field"
|
|
313
|
+
desc = expected ? "have input #{expected.inspect}" : "have an input field"
|
|
314
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
315
|
+
desc
|
|
271
316
|
end
|
|
272
317
|
failure_message do |_actual|
|
|
273
318
|
expected ? "expected terminal to have an input #{expected.inspect}" : "expected terminal to have an input field"
|
|
@@ -277,19 +322,18 @@ module TUITD
|
|
|
277
322
|
end
|
|
278
323
|
end
|
|
279
324
|
|
|
280
|
-
RSpec::Matchers.define :have_label do |expected = nil|
|
|
325
|
+
RSpec::Matchers.define :have_label do |expected = nil, min_confidence: nil|
|
|
281
326
|
match do |actual|
|
|
282
327
|
Matchers.auto_wait(actual) do |s|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
else
|
|
286
|
-
Selector.new(s).labels.any?
|
|
287
|
-
end
|
|
328
|
+
elements = expected ? [Selector.new(s).label(text: expected)].compact : Selector.new(s).labels
|
|
329
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
288
330
|
end
|
|
289
331
|
end
|
|
290
332
|
|
|
291
333
|
description do
|
|
292
|
-
expected ? "have label #{expected.inspect}" : "have a label"
|
|
334
|
+
desc = expected ? "have label #{expected.inspect}" : "have a label"
|
|
335
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
336
|
+
desc
|
|
293
337
|
end
|
|
294
338
|
failure_message do |_actual|
|
|
295
339
|
expected ? "expected terminal to have a label #{expected.inspect}" : "expected terminal to have a label"
|
|
@@ -299,19 +343,18 @@ module TUITD
|
|
|
299
343
|
end
|
|
300
344
|
end
|
|
301
345
|
|
|
302
|
-
RSpec::Matchers.define :have_menu do |expected = nil|
|
|
346
|
+
RSpec::Matchers.define :have_menu do |expected = nil, min_confidence: nil|
|
|
303
347
|
match do |actual|
|
|
304
348
|
Matchers.auto_wait(actual) do |s|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
else
|
|
308
|
-
Selector.new(s).menus.any?
|
|
309
|
-
end
|
|
349
|
+
elements = expected ? [Selector.new(s).menu(text: expected)].compact : Selector.new(s).menus
|
|
350
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
310
351
|
end
|
|
311
352
|
end
|
|
312
353
|
|
|
313
354
|
description do
|
|
314
|
-
expected ? "have menu #{expected.inspect}" : "have a menu"
|
|
355
|
+
desc = expected ? "have menu #{expected.inspect}" : "have a menu"
|
|
356
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
357
|
+
desc
|
|
315
358
|
end
|
|
316
359
|
failure_message do |_actual|
|
|
317
360
|
expected ? "expected terminal to have a menu #{expected.inspect}" : "expected terminal to have a menu"
|
|
@@ -321,19 +364,18 @@ module TUITD
|
|
|
321
364
|
end
|
|
322
365
|
end
|
|
323
366
|
|
|
324
|
-
RSpec::Matchers.define :have_tab do |expected = nil|
|
|
367
|
+
RSpec::Matchers.define :have_tab do |expected = nil, min_confidence: nil|
|
|
325
368
|
match do |actual|
|
|
326
369
|
Matchers.auto_wait(actual) do |s|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
else
|
|
330
|
-
Selector.new(s).tabs.any?
|
|
331
|
-
end
|
|
370
|
+
elements = expected ? [Selector.new(s).tab(text: expected)].compact : Selector.new(s).tabs
|
|
371
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
332
372
|
end
|
|
333
373
|
end
|
|
334
374
|
|
|
335
375
|
description do
|
|
336
|
-
expected ? "have tab #{expected.inspect}" : "have a tab"
|
|
376
|
+
desc = expected ? "have tab #{expected.inspect}" : "have a tab"
|
|
377
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
378
|
+
desc
|
|
337
379
|
end
|
|
338
380
|
failure_message do |_actual|
|
|
339
381
|
expected ? "expected terminal to have a tab #{expected.inspect}" : "expected terminal to have a tab"
|
|
@@ -343,19 +385,18 @@ module TUITD
|
|
|
343
385
|
end
|
|
344
386
|
end
|
|
345
387
|
|
|
346
|
-
RSpec::Matchers.define :have_statusbar do |expected = nil|
|
|
388
|
+
RSpec::Matchers.define :have_statusbar do |expected = nil, min_confidence: nil|
|
|
347
389
|
match do |actual|
|
|
348
390
|
Matchers.auto_wait(actual) do |s|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
else
|
|
352
|
-
Selector.new(s).statusbars.any?
|
|
353
|
-
end
|
|
391
|
+
elements = expected ? [Selector.new(s).statusbar(text: expected)].compact : Selector.new(s).statusbars
|
|
392
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
354
393
|
end
|
|
355
394
|
end
|
|
356
395
|
|
|
357
396
|
description do
|
|
358
|
-
expected ? "have status bar #{expected.inspect}" : "have a status bar"
|
|
397
|
+
desc = expected ? "have status bar #{expected.inspect}" : "have a status bar"
|
|
398
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
399
|
+
desc
|
|
359
400
|
end
|
|
360
401
|
failure_message do |_actual|
|
|
361
402
|
expected ? "expected terminal to have a status bar #{expected.inspect}" : "expected terminal to have a status bar"
|
|
@@ -365,19 +406,23 @@ module TUITD
|
|
|
365
406
|
end
|
|
366
407
|
end
|
|
367
408
|
|
|
368
|
-
RSpec::Matchers.define :have_progress_bar do |expected = nil|
|
|
409
|
+
RSpec::Matchers.define :have_progress_bar do |expected = nil, min_confidence: nil|
|
|
369
410
|
match do |actual|
|
|
370
411
|
Matchers.auto_wait(actual) do |s|
|
|
371
412
|
if expected
|
|
372
|
-
Selector.new(s).progress_bar(text: expected)
|
|
413
|
+
el = Selector.new(s).progress_bar(text: expected)
|
|
414
|
+
min_confidence ? (el&.confidence && el.confidence >= min_confidence) : el
|
|
373
415
|
else
|
|
374
|
-
Selector.new(s).progress_bars
|
|
416
|
+
elements = Selector.new(s).progress_bars
|
|
417
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
375
418
|
end
|
|
376
419
|
end
|
|
377
420
|
end
|
|
378
421
|
|
|
379
422
|
description do
|
|
380
|
-
expected ? "have progress bar #{expected.inspect}" : "have a progress bar"
|
|
423
|
+
desc = expected ? "have progress bar #{expected.inspect}" : "have a progress bar"
|
|
424
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
425
|
+
desc
|
|
381
426
|
end
|
|
382
427
|
failure_message do |_actual|
|
|
383
428
|
expected ? "expected terminal to have a progress bar #{expected.inspect}" : "expected terminal to have a progress bar"
|
|
@@ -386,7 +431,6 @@ module TUITD
|
|
|
386
431
|
expected ? "expected terminal NOT to have a progress bar #{expected.inspect}" : "expected terminal NOT to have a progress bar"
|
|
387
432
|
end
|
|
388
433
|
end
|
|
389
|
-
|
|
390
434
|
# Snapshot comparison matcher — works with both State and Driver (auto-wait).
|
|
391
435
|
# Snapshot comparison matcher — supports both named (disk-based) and
|
|
392
436
|
# legacy in-memory State objects.
|
|
@@ -402,14 +446,15 @@ module TUITD
|
|
|
402
446
|
# pre = driver.snapshot
|
|
403
447
|
# expect(driver).to match_snapshot(pre, chars_only: true)
|
|
404
448
|
#
|
|
449
|
+
# rubocop:disable Metrics/BlockLength
|
|
405
450
|
RSpec::Matchers.define :match_snapshot do |ref, type: nil, wait: false, chars_only: nil, ignore_rows: nil, region: nil|
|
|
406
451
|
match do |actual|
|
|
407
452
|
# Normalize type: backward compat for chars_only parameter
|
|
408
|
-
effective_type = type
|
|
409
|
-
if effective_type.nil? && !chars_only.nil?
|
|
410
|
-
effective_type = chars_only ? :text : :full
|
|
453
|
+
@effective_type = type
|
|
454
|
+
if @effective_type.nil? && !chars_only.nil?
|
|
455
|
+
@effective_type = chars_only ? :text : :full
|
|
411
456
|
end
|
|
412
|
-
effective_type ||= :text
|
|
457
|
+
@effective_type ||= :text
|
|
413
458
|
|
|
414
459
|
@snapshot_name = nil
|
|
415
460
|
@diff_result = nil
|
|
@@ -417,7 +462,7 @@ module TUITD
|
|
|
417
462
|
# Legacy path: snapshot_ref is a State object (responds to diff)
|
|
418
463
|
if ref.respond_to?(:diff)
|
|
419
464
|
Matchers.auto_wait(actual) do |s|
|
|
420
|
-
chars = effective_type == :text
|
|
465
|
+
chars = @effective_type == :text
|
|
421
466
|
diffs = ref.diff(s, chars_only: chars)
|
|
422
467
|
diffs.select! { |d| Array(region).include?(d[:row]) } if region
|
|
423
468
|
diffs.reject! { |d| Array(ignore_rows).include?(d[:row]) } if ignore_rows
|
|
@@ -427,7 +472,7 @@ module TUITD
|
|
|
427
472
|
else
|
|
428
473
|
# Named snapshot path
|
|
429
474
|
@snapshot_name = ref.to_s
|
|
430
|
-
snap = Snapshot.new(@snapshot_name, type: effective_type)
|
|
475
|
+
snap = Snapshot.new(@snapshot_name, type: @effective_type)
|
|
431
476
|
|
|
432
477
|
# Get state_data from actual
|
|
433
478
|
if wait && actual.respond_to?(:wait_for_stable)
|
|
@@ -450,8 +495,8 @@ module TUITD
|
|
|
450
495
|
true
|
|
451
496
|
elsif !snap.exists?
|
|
452
497
|
snap.save(state_data)
|
|
453
|
-
@diff_result = TUITD::Snapshot::ComparisonResult.new(passed: true, diff_count: 0, type: effective_type,
|
|
454
|
-
message: "Snapshot '#{@snapshot_name}' created (#{effective_type})",)
|
|
498
|
+
@diff_result = TUITD::Snapshot::ComparisonResult.new(passed: true, diff_count: 0, type: @effective_type,
|
|
499
|
+
message: "Snapshot '#{@snapshot_name}' created (#{@effective_type})",)
|
|
455
500
|
true
|
|
456
501
|
else
|
|
457
502
|
@diff_result = snap.compare(state_data, ignore_rows: ignore_rows, region: region)
|
|
@@ -462,10 +507,10 @@ module TUITD
|
|
|
462
507
|
|
|
463
508
|
description do
|
|
464
509
|
if @snapshot_name
|
|
465
|
-
"match snapshot #{@snapshot_name.inspect} (type: #{effective_type})"
|
|
510
|
+
"match snapshot #{@snapshot_name.inspect} (type: #{@effective_type})"
|
|
466
511
|
else
|
|
467
|
-
desc = "match snapshot"
|
|
468
|
-
desc << " (chars only)" if effective_type == :text
|
|
512
|
+
desc = +"match snapshot"
|
|
513
|
+
desc << " (chars only)" if @effective_type == :text
|
|
469
514
|
desc
|
|
470
515
|
end
|
|
471
516
|
end
|
|
@@ -488,4 +533,4 @@ module TUITD
|
|
|
488
533
|
end
|
|
489
534
|
end
|
|
490
535
|
end
|
|
491
|
-
# rubocop:enable Metrics/ModuleLength, Metrics/
|
|
536
|
+
# rubocop:enable Metrics/ModuleLength, Metrics/ParameterLists, Layout/LineLength, Metrics/BlockLength
|
data/lib/tui_td/mcp/server.rb
CHANGED
|
@@ -291,7 +291,7 @@ module TUITD
|
|
|
291
291
|
},
|
|
292
292
|
{
|
|
293
293
|
name: "tui_find_elements",
|
|
294
|
-
description: "Search for UI elements in the terminal state. Returns buttons, checkboxes, dialogs, statusbars, progress bars, inputs, labels, menus, and tabs detected by heuristic analysis. Optionally filter by role, text, checked, and/or
|
|
294
|
+
description: "Search for UI elements in the terminal state. Returns buttons, checkboxes, dialogs, statusbars, progress bars, inputs, labels, menus, and tabs detected by heuristic analysis. Optionally filter by role, text, checked, disabled state, and/or minimum confidence score (0.0-1.0). Elements include a confidence score from tans-parser 0.1.5+.",
|
|
295
295
|
inputSchema: {
|
|
296
296
|
type: "object",
|
|
297
297
|
properties: {
|
|
@@ -311,6 +311,10 @@ module TUITD
|
|
|
311
311
|
type: "boolean",
|
|
312
312
|
description: "Filter by disabled state. Optional.",
|
|
313
313
|
},
|
|
314
|
+
min_confidence: {
|
|
315
|
+
type: "number",
|
|
316
|
+
description: "Minimum confidence score (0.0-1.0) for element detection. Higher values reduce false positives. Default: no filter. Example: 0.8.",
|
|
317
|
+
},
|
|
314
318
|
},
|
|
315
319
|
},
|
|
316
320
|
},
|
|
@@ -693,6 +697,7 @@ module TUITD
|
|
|
693
697
|
text = args["text"]
|
|
694
698
|
checked = args.key?("checked") ? args["checked"] : nil
|
|
695
699
|
disabled = args.key?("disabled") ? args["disabled"] : nil
|
|
700
|
+
min_confidence = args["min_confidence"]
|
|
696
701
|
|
|
697
702
|
filters = {}
|
|
698
703
|
filters[:text] = text if text
|
|
@@ -709,11 +714,15 @@ module TUITD
|
|
|
709
714
|
result
|
|
710
715
|
end
|
|
711
716
|
|
|
717
|
+
# Apply confidence filter (tans-parser 0.1.5+)
|
|
718
|
+
elements = elements.select { |e| e.confidence && e.confidence >= min_confidence } if min_confidence
|
|
719
|
+
|
|
712
720
|
if elements.empty?
|
|
713
721
|
desc = role ? "role :#{role}" : "any role"
|
|
714
722
|
desc += " with text #{text.inspect}" if text
|
|
715
723
|
desc += " checked=#{checked}" unless checked.nil?
|
|
716
724
|
desc += " disabled=#{disabled}" unless disabled.nil?
|
|
725
|
+
desc += " min_confidence=#{min_confidence}" if min_confidence
|
|
717
726
|
"No elements found for #{desc}"
|
|
718
727
|
else
|
|
719
728
|
lines = ["Found #{elements.size} element(s):"]
|
|
@@ -725,6 +734,7 @@ module TUITD
|
|
|
725
734
|
parts << "(checked)" if el.checked
|
|
726
735
|
parts << "(disabled)" if el.disabled
|
|
727
736
|
parts << "(focused)" if el.focused
|
|
737
|
+
parts << "[conf=#{format("%.2f", el.confidence)}]" if el.confidence
|
|
728
738
|
lines << parts.join(" ")
|
|
729
739
|
end
|
|
730
740
|
lines.join("\n")
|
|
@@ -110,9 +110,18 @@ module TUITD
|
|
|
110
110
|
|
|
111
111
|
# --- Selector-based ---
|
|
112
112
|
|
|
113
|
-
def assert_button(actual, expected)
|
|
114
|
-
result = auto_wait(actual)
|
|
115
|
-
|
|
113
|
+
def assert_button(actual, expected, min_confidence: nil)
|
|
114
|
+
result = auto_wait(actual) do |s|
|
|
115
|
+
el = TUITD::Selector.new(s).button(text: expected)
|
|
116
|
+
if min_confidence && el
|
|
117
|
+
el.confidence && el.confidence >= min_confidence
|
|
118
|
+
else
|
|
119
|
+
el
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
msg = "Expected terminal to have a button #{expected.inspect}"
|
|
123
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
124
|
+
assert(result, msg)
|
|
116
125
|
end
|
|
117
126
|
|
|
118
127
|
def refute_button(actual, expected)
|
|
@@ -120,9 +129,14 @@ module TUITD
|
|
|
120
129
|
assert(result, "Expected terminal NOT to have a button #{expected.inspect}")
|
|
121
130
|
end
|
|
122
131
|
|
|
123
|
-
def assert_dialog(actual)
|
|
124
|
-
result = auto_wait(actual)
|
|
125
|
-
|
|
132
|
+
def assert_dialog(actual, min_confidence: nil)
|
|
133
|
+
result = auto_wait(actual) do |s|
|
|
134
|
+
elements = TUITD::Selector.new(s).dialogs
|
|
135
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
136
|
+
end
|
|
137
|
+
msg = "Expected terminal to have a dialog"
|
|
138
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
139
|
+
assert(result, msg)
|
|
126
140
|
end
|
|
127
141
|
|
|
128
142
|
def refute_dialog(actual)
|
|
@@ -130,107 +144,123 @@ module TUITD
|
|
|
130
144
|
assert(result, "Expected terminal NOT to have a dialog")
|
|
131
145
|
end
|
|
132
146
|
|
|
133
|
-
def assert_checkbox(actual, expected, checked: nil, unchecked: nil)
|
|
147
|
+
def assert_checkbox(actual, expected, checked: nil, unchecked: nil, min_confidence: nil)
|
|
134
148
|
checked = false if unchecked
|
|
135
149
|
result = auto_wait(actual) do |s|
|
|
136
150
|
filters = { text: expected }
|
|
137
151
|
filters[:checked] = checked unless checked.nil?
|
|
138
|
-
TUITD::Selector.new(s).checkbox(**filters)
|
|
152
|
+
el = TUITD::Selector.new(s).checkbox(**filters)
|
|
153
|
+
if min_confidence && el
|
|
154
|
+
el.confidence && el.confidence >= min_confidence
|
|
155
|
+
else
|
|
156
|
+
el
|
|
157
|
+
end
|
|
139
158
|
end
|
|
140
159
|
msg = "Expected terminal to have checkbox #{expected.inspect}"
|
|
141
160
|
msg += " (checked)" if checked == true
|
|
142
161
|
msg += " (unchecked)" if checked == false
|
|
162
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
143
163
|
assert(result, msg)
|
|
144
164
|
end
|
|
145
165
|
|
|
146
|
-
def assert_role(actual, role, text: nil, checked: nil, disabled: nil)
|
|
166
|
+
def assert_role(actual, role, text: nil, checked: nil, disabled: nil, min_confidence: nil)
|
|
147
167
|
result = auto_wait(actual) do |s|
|
|
148
168
|
filters = {}
|
|
149
169
|
filters[:text] = text if text
|
|
150
170
|
filters[:checked] = checked unless checked.nil?
|
|
151
171
|
filters[:disabled] = disabled unless disabled.nil?
|
|
152
|
-
TUITD::Selector.new(s).get_by_role(role, **filters)
|
|
172
|
+
elements = TUITD::Selector.new(s).get_by_role(role, **filters)
|
|
173
|
+
if min_confidence
|
|
174
|
+
elements.any? { |e| e.confidence && e.confidence >= min_confidence }
|
|
175
|
+
else
|
|
176
|
+
elements.any?
|
|
177
|
+
end
|
|
153
178
|
end
|
|
154
179
|
msg = "Expected terminal to have role :#{role}"
|
|
155
180
|
msg += " with text #{text.inspect}" if text
|
|
181
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
156
182
|
assert(result, msg)
|
|
157
183
|
end
|
|
158
184
|
|
|
159
|
-
def assert_input(actual, expected = nil)
|
|
185
|
+
def assert_input(actual, expected = nil, min_confidence: nil)
|
|
160
186
|
result = auto_wait(actual) do |s|
|
|
187
|
+
sel = TUITD::Selector.new(s)
|
|
161
188
|
if expected
|
|
162
|
-
|
|
189
|
+
el = sel.input(text: expected)
|
|
190
|
+
min_confidence ? (el&.confidence && el.confidence >= min_confidence) : el
|
|
163
191
|
else
|
|
164
|
-
|
|
192
|
+
elements = sel.inputs
|
|
193
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
165
194
|
end
|
|
166
195
|
end
|
|
167
196
|
msg = "Expected terminal to have an input field"
|
|
168
197
|
msg += " #{expected.inspect}" if expected
|
|
198
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
169
199
|
assert(result, msg)
|
|
170
200
|
end
|
|
171
201
|
|
|
172
|
-
def assert_label(actual, expected = nil)
|
|
202
|
+
def assert_label(actual, expected = nil, min_confidence: nil)
|
|
173
203
|
result = auto_wait(actual) do |s|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
TUITD::Selector.new(s).labels.any?
|
|
178
|
-
end
|
|
204
|
+
sel = TUITD::Selector.new(s)
|
|
205
|
+
elements = expected ? [sel.label(text: expected)].compact : sel.labels
|
|
206
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
179
207
|
end
|
|
180
208
|
msg = "Expected terminal to have a label"
|
|
181
209
|
msg += " #{expected.inspect}" if expected
|
|
210
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
182
211
|
assert(result, msg)
|
|
183
212
|
end
|
|
184
213
|
|
|
185
|
-
def assert_menu(actual, expected = nil)
|
|
214
|
+
def assert_menu(actual, expected = nil, min_confidence: nil)
|
|
186
215
|
result = auto_wait(actual) do |s|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
TUITD::Selector.new(s).menus.any?
|
|
191
|
-
end
|
|
216
|
+
sel = TUITD::Selector.new(s)
|
|
217
|
+
elements = expected ? [sel.menu(text: expected)].compact : sel.menus
|
|
218
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
192
219
|
end
|
|
193
220
|
msg = "Expected terminal to have a menu"
|
|
194
221
|
msg += " #{expected.inspect}" if expected
|
|
222
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
195
223
|
assert(result, msg)
|
|
196
224
|
end
|
|
197
225
|
|
|
198
|
-
def assert_tab(actual, expected = nil)
|
|
226
|
+
def assert_tab(actual, expected = nil, min_confidence: nil)
|
|
199
227
|
result = auto_wait(actual) do |s|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
TUITD::Selector.new(s).tabs.any?
|
|
204
|
-
end
|
|
228
|
+
sel = TUITD::Selector.new(s)
|
|
229
|
+
elements = expected ? [sel.tab(text: expected)].compact : sel.tabs
|
|
230
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
205
231
|
end
|
|
206
232
|
msg = "Expected terminal to have a tab"
|
|
207
233
|
msg += " #{expected.inspect}" if expected
|
|
234
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
208
235
|
assert(result, msg)
|
|
209
236
|
end
|
|
210
237
|
|
|
211
|
-
def assert_statusbar(actual, expected = nil)
|
|
238
|
+
def assert_statusbar(actual, expected = nil, min_confidence: nil)
|
|
212
239
|
result = auto_wait(actual) do |s|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
TUITD::Selector.new(s).statusbars.any?
|
|
217
|
-
end
|
|
240
|
+
sel = TUITD::Selector.new(s)
|
|
241
|
+
elements = expected ? [sel.statusbar(text: expected)].compact : sel.statusbars
|
|
242
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
218
243
|
end
|
|
219
244
|
msg = "Expected terminal to have a status bar"
|
|
220
245
|
msg += " #{expected.inspect}" if expected
|
|
246
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
221
247
|
assert(result, msg)
|
|
222
248
|
end
|
|
223
249
|
|
|
224
|
-
def assert_progress_bar(actual, expected = nil)
|
|
250
|
+
def assert_progress_bar(actual, expected = nil, min_confidence: nil)
|
|
225
251
|
result = auto_wait(actual) do |s|
|
|
252
|
+
sel = TUITD::Selector.new(s)
|
|
226
253
|
if expected
|
|
227
|
-
|
|
254
|
+
el = sel.progress_bar(text: expected)
|
|
255
|
+
min_confidence ? (el&.confidence && el.confidence >= min_confidence) : el
|
|
228
256
|
else
|
|
229
|
-
|
|
257
|
+
elements = sel.progress_bars
|
|
258
|
+
min_confidence ? elements.any? { |e| e.confidence && e.confidence >= min_confidence } : elements.any?
|
|
230
259
|
end
|
|
231
260
|
end
|
|
232
261
|
msg = "Expected terminal to have a progress bar"
|
|
233
262
|
msg += " #{expected.inspect}" if expected
|
|
263
|
+
msg += " (min_confidence: #{min_confidence})" if min_confidence
|
|
234
264
|
assert(result, msg)
|
|
235
265
|
end
|
|
236
266
|
|
data/lib/tui_td/test_runner.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/BlockLength, Metrics/ClassLength
|
|
3
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/BlockLength, Metrics/ClassLength, Metrics/ParameterLists, Layout/LineLength
|
|
4
4
|
|
|
5
5
|
require "json"
|
|
6
6
|
require "shellwords"
|
|
@@ -164,35 +164,43 @@ module TUITD
|
|
|
164
164
|
end
|
|
165
165
|
|
|
166
166
|
when "assert_button"
|
|
167
|
-
check_role(driver, :button, value.to_s)
|
|
167
|
+
check_role(driver, :button, value.to_s, min_confidence: step[:min_confidence])
|
|
168
168
|
|
|
169
169
|
when "assert_dialog"
|
|
170
|
-
check_role(driver, :dialog, nil)
|
|
170
|
+
check_role(driver, :dialog, nil, min_confidence: step[:min_confidence])
|
|
171
171
|
|
|
172
172
|
when "assert_checkbox"
|
|
173
|
-
check_role(driver, :checkbox, value.to_s, checked: step[:checked],
|
|
173
|
+
check_role(driver, :checkbox, value.to_s, checked: step[:checked],
|
|
174
|
+
disabled: step[:disabled], min_confidence: step[:min_confidence],)
|
|
174
175
|
|
|
175
176
|
when "assert_role"
|
|
176
177
|
role = step[:role]&.to_sym
|
|
177
|
-
check_role(driver, role, value.to_s, checked: step[:checked],
|
|
178
|
+
check_role(driver, role, value.to_s, checked: step[:checked],
|
|
179
|
+
disabled: step[:disabled], min_confidence: step[:min_confidence],)
|
|
178
180
|
|
|
179
181
|
when "assert_input"
|
|
180
|
-
check_role(driver, :input, value == true ? nil : value.to_s
|
|
182
|
+
check_role(driver, :input, value == true ? nil : value.to_s,
|
|
183
|
+
min_confidence: step[:min_confidence],)
|
|
181
184
|
|
|
182
185
|
when "assert_label"
|
|
183
|
-
check_role(driver, :label, value == true ? nil : value.to_s
|
|
186
|
+
check_role(driver, :label, value == true ? nil : value.to_s,
|
|
187
|
+
min_confidence: step[:min_confidence],)
|
|
184
188
|
|
|
185
189
|
when "assert_menu"
|
|
186
|
-
check_role(driver, :menu, value == true ? nil : value.to_s
|
|
190
|
+
check_role(driver, :menu, value == true ? nil : value.to_s,
|
|
191
|
+
min_confidence: step[:min_confidence],)
|
|
187
192
|
|
|
188
193
|
when "assert_tab"
|
|
189
|
-
check_role(driver, :tab, value == true ? nil : value.to_s
|
|
194
|
+
check_role(driver, :tab, value == true ? nil : value.to_s,
|
|
195
|
+
min_confidence: step[:min_confidence],)
|
|
190
196
|
|
|
191
197
|
when "assert_statusbar"
|
|
192
|
-
check_role(driver, :statusbar, value == true ? nil : value.to_s
|
|
198
|
+
check_role(driver, :statusbar, value == true ? nil : value.to_s,
|
|
199
|
+
min_confidence: step[:min_confidence],)
|
|
193
200
|
|
|
194
201
|
when "assert_progress_bar"
|
|
195
|
-
check_role(driver, :progress, value == true ? nil : value.to_s
|
|
202
|
+
check_role(driver, :progress, value == true ? nil : value.to_s,
|
|
203
|
+
min_confidence: step[:min_confidence],)
|
|
196
204
|
|
|
197
205
|
when "snapshot"
|
|
198
206
|
ensure_driver!(driver)
|
|
@@ -305,7 +313,7 @@ module TUITD
|
|
|
305
313
|
|
|
306
314
|
private
|
|
307
315
|
|
|
308
|
-
def check_role(driver, role, text, checked: nil, disabled: nil)
|
|
316
|
+
def check_role(driver, role, text, checked: nil, disabled: nil, min_confidence: nil)
|
|
309
317
|
ensure_driver!(driver)
|
|
310
318
|
state = State.new(driver.state_data)
|
|
311
319
|
selector = Selector.new(state)
|
|
@@ -316,6 +324,8 @@ module TUITD
|
|
|
316
324
|
filters[:disabled] = disabled unless disabled.nil?
|
|
317
325
|
elements = selector.get_by_role(role, **filters)
|
|
318
326
|
|
|
327
|
+
elements = elements.select { |e| e.confidence && e.confidence >= min_confidence } if min_confidence
|
|
328
|
+
|
|
319
329
|
action = "assert_#{role}"
|
|
320
330
|
if elements.any?
|
|
321
331
|
count = elements.size
|
|
@@ -323,11 +333,19 @@ module TUITD
|
|
|
323
333
|
desc += " (checked)" if checked == true
|
|
324
334
|
desc += " (unchecked)" if checked == false
|
|
325
335
|
desc += " (disabled)" if disabled == true
|
|
326
|
-
|
|
336
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
337
|
+
confidence_info = if min_confidence
|
|
338
|
+
confs = elements.map { |e| e.confidence || 0 }.sort
|
|
339
|
+
" [#{confs.map { |c| format("%.2f", c) }.join(", ")}]"
|
|
340
|
+
else
|
|
341
|
+
""
|
|
342
|
+
end
|
|
343
|
+
Result.new(step: action, passed: true, message: "Found #{count} #{desc} element(s)#{confidence_info}")
|
|
327
344
|
else
|
|
328
345
|
desc = text ? "#{role} with text #{text.inspect}" : role.to_s
|
|
329
346
|
desc += " (checked)" if checked == true
|
|
330
347
|
desc += " (disabled)" if disabled == true
|
|
348
|
+
desc += " (min_confidence: #{min_confidence})" if min_confidence
|
|
331
349
|
Result.new(step: action, passed: false, message: "No #{desc} found")
|
|
332
350
|
end
|
|
333
351
|
end
|
|
@@ -436,4 +454,4 @@ module TUITD
|
|
|
436
454
|
end
|
|
437
455
|
end
|
|
438
456
|
end
|
|
439
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/BlockLength, Metrics/ClassLength
|
|
457
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/BlockLength, Metrics/ClassLength, Metrics/ParameterLists, Layout/LineLength
|
data/lib/tui_td/version.rb
CHANGED
data/lib/tui_td.rb
CHANGED
|
@@ -9,19 +9,19 @@ end
|
|
|
9
9
|
# The convenience method below reopens the module after requires, intentional for bootstrapping.
|
|
10
10
|
|
|
11
11
|
require_relative "tui_td/version"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
require "tui_td/driver"
|
|
13
|
+
require "tui_td/ansi_parser"
|
|
14
|
+
require "tui_td/ansi_utils"
|
|
15
|
+
require "tui_td/state"
|
|
16
|
+
require "tui_td/configuration"
|
|
17
|
+
require "tui_td/snapshot"
|
|
18
|
+
require "tui_td/screenshot"
|
|
19
|
+
require "tui_td/video_recorder"
|
|
20
|
+
require "tui_td/html_renderer"
|
|
21
|
+
require "tui_td/test_runner"
|
|
22
|
+
require "tui_td/selector"
|
|
23
|
+
require "tui_td/mcp/server"
|
|
24
|
+
require "tui_td/cli"
|
|
25
25
|
|
|
26
26
|
module TUITD
|
|
27
27
|
# Convenience method: start a TUI driver, capture initial state
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tui-td
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.22
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Haluk Durmus
|
|
@@ -71,14 +71,14 @@ dependencies:
|
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: 0.1.
|
|
74
|
+
version: 0.1.5
|
|
75
75
|
type: :runtime
|
|
76
76
|
prerelease: false
|
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
|
79
79
|
- - "~>"
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: 0.1.
|
|
81
|
+
version: 0.1.5
|
|
82
82
|
- !ruby/object:Gem::Dependency
|
|
83
83
|
name: bundler-audit
|
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -177,6 +177,7 @@ files:
|
|
|
177
177
|
- CHANGELOG.md
|
|
178
178
|
- LICENSE.txt
|
|
179
179
|
- README.md
|
|
180
|
+
- bin/check_tans_parser.sh
|
|
180
181
|
- bin/tui-td
|
|
181
182
|
- lib/tui_td.rb
|
|
182
183
|
- lib/tui_td/ansi_parser.rb
|