@testsmith/testblocks 0.6.0 → 0.7.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 (71) hide show
  1. package/dist/cli/executor.d.ts +4 -1
  2. package/dist/cli/executor.js +101 -5
  3. package/dist/cli/index.js +78 -3
  4. package/dist/cli/reporters/ConsoleReporter.d.ts +12 -0
  5. package/dist/cli/reporters/ConsoleReporter.js +39 -0
  6. package/dist/cli/reporters/HTMLReporter.d.ts +19 -0
  7. package/dist/cli/reporters/HTMLReporter.js +506 -0
  8. package/dist/cli/reporters/JSONReporter.d.ts +15 -0
  9. package/dist/cli/reporters/JSONReporter.js +80 -0
  10. package/dist/cli/reporters/JUnitReporter.d.ts +19 -0
  11. package/dist/cli/reporters/JUnitReporter.js +105 -0
  12. package/dist/cli/reporters/index.d.ts +17 -0
  13. package/dist/cli/reporters/index.js +31 -0
  14. package/dist/cli/reporters/types.d.ts +28 -0
  15. package/dist/cli/reporters/types.js +2 -0
  16. package/dist/cli/reporters/utils.d.ts +31 -0
  17. package/dist/cli/reporters/utils.js +136 -0
  18. package/dist/cli/reporters.d.ts +13 -62
  19. package/dist/cli/reporters.js +16 -719
  20. package/dist/client/assets/index-Boo8ZrY_.js +2195 -0
  21. package/dist/client/assets/{index-dXniUrbi.js.map → index-Boo8ZrY_.js.map} +1 -1
  22. package/dist/client/assets/index-OxNH9dW-.css +1 -0
  23. package/dist/client/index.html +2 -2
  24. package/dist/core/blocks/api.js +3 -6
  25. package/dist/core/blocks/assertions.d.ts +31 -0
  26. package/dist/core/blocks/assertions.js +72 -0
  27. package/dist/core/blocks/index.d.ts +1 -0
  28. package/dist/core/blocks/index.js +6 -1
  29. package/dist/core/blocks/lifecycle.js +5 -3
  30. package/dist/core/blocks/logic.js +2 -3
  31. package/dist/core/blocks/playwright/assertions.d.ts +5 -0
  32. package/dist/core/blocks/playwright/assertions.js +321 -0
  33. package/dist/core/blocks/playwright/index.d.ts +17 -0
  34. package/dist/core/blocks/playwright/index.js +49 -0
  35. package/dist/core/blocks/playwright/interactions.d.ts +5 -0
  36. package/dist/core/blocks/playwright/interactions.js +191 -0
  37. package/dist/core/blocks/playwright/navigation.d.ts +5 -0
  38. package/dist/core/blocks/playwright/navigation.js +133 -0
  39. package/dist/core/blocks/playwright/retrieval.d.ts +5 -0
  40. package/dist/core/blocks/playwright/retrieval.js +144 -0
  41. package/dist/core/blocks/playwright/types.d.ts +65 -0
  42. package/dist/core/blocks/playwright/types.js +5 -0
  43. package/dist/core/blocks/playwright/utils.d.ts +26 -0
  44. package/dist/core/blocks/playwright/utils.js +137 -0
  45. package/dist/core/blocks/playwright.d.ts +13 -2
  46. package/dist/core/blocks/playwright.js +14 -761
  47. package/dist/core/executor/BaseTestExecutor.d.ts +60 -0
  48. package/dist/core/executor/BaseTestExecutor.js +297 -0
  49. package/dist/core/executor/index.d.ts +1 -0
  50. package/dist/core/executor/index.js +5 -0
  51. package/dist/core/index.d.ts +1 -0
  52. package/dist/core/index.js +4 -0
  53. package/dist/core/types.d.ts +12 -0
  54. package/dist/core/utils/blocklyParser.d.ts +18 -0
  55. package/dist/core/utils/blocklyParser.js +84 -0
  56. package/dist/core/utils/dataLoader.d.ts +9 -0
  57. package/dist/core/utils/dataLoader.js +117 -0
  58. package/dist/core/utils/index.d.ts +2 -0
  59. package/dist/core/utils/index.js +12 -0
  60. package/dist/core/utils/logger.d.ts +14 -0
  61. package/dist/core/utils/logger.js +48 -0
  62. package/dist/core/utils/variableResolver.d.ts +24 -0
  63. package/dist/core/utils/variableResolver.js +92 -0
  64. package/dist/server/executor.d.ts +6 -0
  65. package/dist/server/executor.js +207 -47
  66. package/dist/server/globals.d.ts +6 -1
  67. package/dist/server/globals.js +7 -0
  68. package/dist/server/startServer.js +15 -0
  69. package/package.json +1 -1
  70. package/dist/client/assets/index-dXniUrbi.js +0 -2193
  71. package/dist/client/assets/index-oTTttNKd.css +0 -1
@@ -0,0 +1 @@
1
+ :root{--ts-blue: #205d96;--ts-blue-light: #e0f2fe;--ts-blue-dark: #1a4a78;--ts-green: #9fc93c;--ts-green-light: #ecfccb;--ts-green-dark: #5c7a1f;--ts-gray: #59575d;--ts-gray-light: #6b7280;--ts-gray-bg: #f8fafc;--primary-color: var(--ts-blue);--primary-dark: var(--ts-blue-dark);--primary-light: var(--ts-blue-light);--secondary-color: var(--ts-gray);--background: var(--ts-gray-bg);--surface: #ffffff;--error: #d32f2f;--success: var(--ts-green-dark);--success-light: var(--ts-green-light);--warning: #e67e00;--text-primary: var(--ts-gray);--text-secondary: var(--ts-gray-light);--border-color: #e0e0e0}*{margin:0;padding:0;box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;background-color:var(--background);color:var(--text-primary)}.app{display:flex;flex-direction:column;height:100vh;overflow:hidden}.header{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:56px;background:var(--primary-color);color:#fff;box-shadow:0 2px 4px #0000001a;z-index:100}.header h1{font-size:20px;font-weight:500;display:flex;align-items:center;gap:8px}.header-actions{display:flex;gap:8px}.btn{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;border:none;border-radius:4px;font-size:14px;font-weight:500;cursor:pointer;transition:background-color .2s,opacity .2s}.btn:disabled{opacity:.6;cursor:not-allowed}.btn-primary{background:#fff;color:var(--primary-color)}.btn-primary:hover:not(:disabled){background:#ffffffe6}.btn-secondary{background:#ffffff26;color:#fff}.btn-secondary:hover:not(:disabled){background:#ffffff40}.btn-success{background:var(--ts-green);color:#fff}.btn-success:hover:not(:disabled){background:var(--ts-green-dark)}.btn-danger{background:var(--error);color:#fff}.btn-danger:hover:not(:disabled){background:#c62828}.main-content{display:flex;flex:1;overflow:hidden}.sidebar{width:280px;background:var(--surface);border-right:1px solid var(--border-color);display:flex;flex-direction:column;overflow:hidden;transition:width .2s ease}.sidebar.collapsed{width:40px}.sidebar-toggle-header{display:flex;align-items:center;justify-content:flex-end;padding:8px;border-bottom:1px solid var(--border-color)}.sidebar.collapsed .sidebar-toggle-header{justify-content:center}.sidebar-header{padding:16px;border-bottom:1px solid var(--border-color)}.sidebar-header h2{font-size:14px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px}.test-list{flex:1;overflow-y:auto;padding:8px}.test-item{padding:12px;border-radius:4px;cursor:pointer;border:1px solid transparent;margin-bottom:4px;transition:background-color .2s}.test-item:hover{background:var(--background)}.test-item.active{background:#1976d214;border-color:var(--primary-color)}.test-item-name{font-weight:500;font-size:14px;margin-bottom:4px}.test-item-steps{font-size:12px;color:var(--text-secondary)}.add-test-btn{margin:8px;padding:12px;border:2px dashed var(--border-color);border-radius:4px;background:transparent;color:var(--text-secondary);cursor:pointer;font-size:14px;transition:border-color .2s,color .2s}.add-test-btn:hover{border-color:var(--primary-color);color:var(--primary-color)}.editor-area{flex:1;display:flex;flex-direction:column;overflow:hidden}.editor-toolbar{display:flex;align-items:center;justify-content:space-between;padding:8px 16px;background:var(--surface);border-bottom:1px solid var(--border-color)}.test-name-input{font-size:16px;font-weight:500;padding:8px 12px;border:1px solid var(--border-color);border-radius:4px;width:300px}.test-name-input:focus{outline:none;border-color:var(--primary-color)}.blockly-container{flex:1;position:relative}#blockly-div{position:absolute;top:0;left:0;right:0;bottom:0}.blocklyTreeSeparator{height:1px!important;margin:12px 8px!important;background-color:#0006!important;border:none!important}.blocklyWidgetDiv .blocklyHtmlInput{max-width:350px;font-family:monospace;font-size:12px;line-height:1.4}.results-panel{width:350px;background:var(--surface);border-left:1px solid var(--border-color);display:flex;flex-direction:column;overflow:hidden;transition:width .2s ease}.results-panel.collapsed{width:40px}.results-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border-color);gap:12px}.results-panel.collapsed .results-header{justify-content:center;padding:12px 8px}.panel-toggle-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px;padding:4px 8px;border-radius:4px;flex-shrink:0}.panel-toggle-btn:hover{background:var(--hover-bg);color:var(--text-primary)}.results-header h2{font-size:14px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;flex:1;display:flex;align-items:center;gap:8px}.results-summary{display:flex;gap:8px;font-size:12px;font-weight:500;text-transform:none}.results-summary .passed-count{color:var(--success)}.results-summary .failed-count{color:var(--danger)}.results-actions{display:flex;gap:8px}.btn-report{padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--border-color);border-radius:4px;background:var(--surface);color:var(--text-secondary);cursor:pointer;transition:all .2s}.btn-report:hover{background:var(--primary-light);border-color:var(--primary-color);color:var(--primary-color)}.results-content{flex:1;overflow-y:auto;padding:16px}.result-item{padding:12px;border-radius:4px;margin-bottom:8px;border-left:4px solid}.result-item.passed{background:#388e3c14;border-left-color:var(--success)}.result-item.failed{background:#d32f2f14;border-left-color:var(--error)}.result-item.running{background:#1976d214;border-left-color:var(--primary-color)}.result-step{font-size:13px;margin-bottom:4px}.result-error{font-size:12px;color:var(--error);font-family:monospace;white-space:pre-wrap;margin-top:8px}.result-duration{font-size:11px;color:var(--text-secondary)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.modal{background:var(--surface);border-radius:8px;padding:24px;min-width:400px;max-width:600px;max-height:80vh;overflow-y:auto;box-shadow:0 4px 20px #00000026}.modal h2{margin-bottom:16px}.modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:24px}.folder-hooks-modal{background:var(--surface);border-radius:8px;width:90vw;max-width:1200px;height:80vh;display:flex;flex-direction:column;box-shadow:0 4px 20px #00000026}.folder-hooks-header{padding:16px 24px;border-bottom:1px solid var(--border-color);position:relative}.folder-hooks-header h2{margin:0 0 4px;font-size:18px}.folder-hooks-description{font-size:13px;color:var(--text-secondary);margin:0}.folder-hooks-tabs{display:flex;border-bottom:1px solid var(--border-color);padding:0 16px;background:var(--background)}.folder-hooks-tab{padding:12px 16px;border:none;background:transparent;color:var(--text-secondary);font-size:13px;font-weight:500;cursor:pointer;border-bottom:2px solid transparent;display:flex;align-items:center;gap:8px}.folder-hooks-tab:hover{color:var(--text-primary)}.folder-hooks-tab.active{color:var(--primary-color);border-bottom-color:var(--primary-color)}.folder-hooks-tab .tab-badge{font-size:10px;padding:2px 6px;border-radius:10px;background:var(--primary-color);color:#fff}.folder-hooks-workspace{flex:1;min-height:0}.folder-hooks-footer{padding:16px 24px;border-top:1px solid var(--border-color);display:flex;justify-content:flex-end;gap:8px}.form-group{margin-bottom:16px}.form-group label{display:block;font-size:14px;font-weight:500;margin-bottom:6px}.form-group input,.form-group textarea{width:100%;padding:10px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px}.form-group input:focus,.form-group textarea:focus{outline:none;border-color:var(--primary-color)}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--text-secondary);text-align:center;padding:40px}.empty-state h3{margin-bottom:8px;color:var(--text-primary)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--background)}::-webkit-scrollbar-thumb{background:#bdbdbd;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#9e9e9e}.status-indicator{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}.status-indicator.running{background:var(--primary-color);animation:pulse 1s infinite}.status-indicator.passed{background:var(--success)}.status-indicator.failed{background:var(--error)}.sidebar-section{border-bottom:1px solid var(--border-color)}.sidebar-section:last-child{border-bottom:none;flex:1;display:flex;flex-direction:column;overflow:hidden}.sidebar-header.clickable{cursor:pointer;-webkit-user-select:none;user-select:none}.sidebar-header.clickable:hover{background:var(--background)}.variables-list{padding:8px}.variable-item{display:flex;align-items:center;gap:8px;padding:6px 0}.variable-name{font-family:monospace;font-size:12px;color:var(--primary-color);min-width:80px;flex-shrink:0}.variable-value{flex:1;padding:4px 8px;border:1px solid var(--border-color);border-radius:4px;font-size:12px}.variable-value:focus{outline:none;border-color:var(--primary-color)}.global-variables{background:linear-gradient(to right,rgba(32,93,150,.05),transparent)}.variable-item.global{padding:4px 0}.variable-item.global .variable-name{color:var(--ts-blue);font-size:11px;word-break:break-all}.variable-value.readonly{background:var(--background);color:var(--text-secondary);font-family:monospace;font-size:11px;padding:2px 6px;border:none;border-radius:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.variable-value.global-input{flex:1;padding:4px 6px;border:1px solid rgba(32,93,150,.3);border-radius:4px;font-size:11px;font-family:monospace;background:#205d960d;color:var(--text-primary)}.variable-value.global-input:focus{outline:none;border-color:var(--ts-blue);background:#205d961a}.variable-group{margin-bottom:8px}.variable-group-header{font-weight:600;font-size:11px;color:var(--text-secondary);text-transform:uppercase;padding:4px 0;border-bottom:1px solid var(--border-color);margin-bottom:4px}.variable-group-content{padding-left:12px;border-left:2px solid rgba(32,93,150,.3)}.global-badge{font-size:12px;margin-left:8px;opacity:.7}.btn-icon{background:none;border:none;color:var(--text-secondary);cursor:pointer;padding:4px 8px;font-size:16px;line-height:1;border-radius:4px}.btn-icon:hover{background:var(--background);color:var(--error)}.add-variable-btn{width:100%;margin-top:8px;padding:8px;border:1px dashed var(--border-color);border-radius:4px;background:transparent;color:var(--text-secondary);cursor:pointer;font-size:12px}.add-variable-btn:hover{border-color:var(--primary-color);color:var(--primary-color)}.test-item{display:flex;align-items:center;justify-content:space-between}.test-item-content{flex:1;min-width:0}.test-item-name{display:flex;align-items:center;gap:6px}.data-driven-badge{font-size:10px;font-weight:600;background:#1565c0;color:#fff;padding:1px 5px;border-radius:8px;margin-left:4px}.btn-run-test{background:none;border:1px solid var(--border-color);border-radius:4px;padding:4px 8px;cursor:pointer;font-size:10px;color:var(--text-secondary);flex-shrink:0;margin-left:8px}.btn-run-test:hover:not(:disabled){background:var(--primary-color);border-color:var(--primary-color);color:#fff}.btn-run-test:disabled{opacity:.5;cursor:not-allowed}.status-dot{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0}.status-dot.passed{background:var(--success)}.status-dot.failed{background:var(--error)}.test-item.passed{background:#388e3c0d}.test-item.failed{background:#d32f2f0d}.test-item.passed.active{background:#388e3c1f}.test-item.failed.active{background:#d32f2f1f}.test-id-indicator{display:flex;align-items:center;gap:6px;color:#ffffffe6;font-size:13px;padding:6px 12px;border-radius:4px;background:#ffffff1a}.test-id-indicator code{font-family:Monaco,Menlo,monospace;background:#fff3;padding:2px 6px;border-radius:3px;font-size:12px}.headless-toggle{display:flex;align-items:center;gap:6px;color:#fff;font-size:14px;cursor:pointer;padding:8px 12px;border-radius:4px;background:#ffffff1a}.headless-toggle:hover{background:#fff3}.headless-toggle input[type=checkbox]{width:16px;height:16px;cursor:pointer}.create-block-modal{min-width:500px;max-width:600px}.create-block-modal h2{color:var(--text-primary);margin-bottom:20px}.helper-text{font-size:12px;color:var(--text-secondary);margin-bottom:8px}.color-picker{display:flex;gap:8px}.color-option{width:32px;height:32px;border-radius:4px;border:2px solid transparent;cursor:pointer;transition:transform .1s,border-color .1s}.color-option:hover{transform:scale(1.1)}.color-option.selected{border-color:var(--text-primary)}.param-list{max-height:200px;overflow-y:auto;border:1px solid var(--border-color);border-radius:4px;padding:8px}.empty-params{color:var(--text-secondary);font-size:13px;padding:12px;text-align:center}.param-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:4px;cursor:pointer;font-size:13px}.param-item:hover{background:var(--background)}.param-item input[type=checkbox]{flex-shrink:0}.param-name{font-weight:500;color:var(--primary-color)}.param-source{color:var(--text-secondary);font-size:11px}.param-default{color:var(--text-secondary);font-size:11px;margin-left:auto;font-family:monospace}.steps-preview{max-height:150px;overflow-y:auto;border:1px solid var(--border-color);border-radius:4px;padding:8px}.step-preview-item{display:flex;align-items:center;gap:8px;padding:4px 8px;font-size:13px}.step-number{color:var(--text-secondary);font-size:11px;width:20px}.step-type{color:var(--text-primary)}.create-block-modal .btn-primary{background:var(--primary-color);color:#fff}.create-block-modal .btn-primary:hover{background:var(--primary-dark)}.create-block-modal .btn-secondary{background:var(--background);color:var(--text-primary)}.result-test-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.result-file-name{color:var(--text-secondary);font-size:12px;margin-right:4px}.result-test-name{font-weight:500;flex:1}.result-steps{margin-top:8px;border-top:1px solid var(--border-color);padding-top:8px}.step-result-item{margin-bottom:6px;border-radius:4px;background:#00000005}.step-result-item.passed{border-left:3px solid var(--success)}.step-result-item.failed{border-left:3px solid var(--error)}.step-result-header{display:flex;align-items:center;gap:8px;padding:6px 8px;cursor:pointer;-webkit-user-select:none;user-select:none}.step-result-header:hover{background:#0000000a}.step-result-type{font-size:12px;color:var(--text-primary);white-space:nowrap}.step-result-summary{flex:1;font-size:11px;color:var(--text-secondary);font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:300px}.step-result-duration{font-size:11px;color:var(--text-secondary);white-space:nowrap}.step-result-expand{font-size:10px;color:var(--text-secondary);width:16px;text-align:center}.step-result-header.expandable{cursor:pointer}.step-result-header.expandable:hover{background:#0000000a}.step-result-details{padding:8px;background:var(--background);border-radius:0 0 4px 4px}.step-output{background:var(--surface);border-radius:4px;padding:8px}.step-result-error{padding:6px 8px;font-size:11px;color:var(--error);background:#d32f2f0d;font-family:monospace}.step-screenshot{margin-bottom:12px}.screenshot-label{font-size:11px;font-weight:600;color:var(--text-secondary);margin-bottom:6px;text-transform:uppercase;letter-spacing:.5px}.failure-screenshot{max-width:100%;max-height:300px;border:2px solid var(--error);border-radius:6px;cursor:pointer;transition:transform .2s,box-shadow .2s;display:block}.failure-screenshot:hover{transform:scale(1.02);box-shadow:0 4px 12px #d32f2f4d}.stack-trace{font-size:10px;line-height:1.4;color:var(--error);max-height:200px;overflow-y:auto}.step-result-response{padding:8px;background:var(--background);border-radius:0 0 4px 4px}.response-status{display:flex;align-items:center;gap:8px;margin-bottom:8px}.response-label{font-size:11px;color:var(--text-secondary)}.response-status-code{font-family:monospace;font-size:12px;font-weight:600;padding:2px 6px;border-radius:3px;background:var(--surface)}.response-status-code.status-success{color:var(--success);background:#388e3c1a}.response-status-code.status-client-error{color:var(--warning);background:#f57c001a}.response-status-code.status-server-error{color:var(--error);background:#d32f2f1a}.response-section{margin-top:8px}.response-section summary{font-size:11px;color:var(--text-secondary);cursor:pointer;padding:4px 0;-webkit-user-select:none;user-select:none}.response-section summary:hover{color:var(--primary-color)}.response-pre{margin:4px 0 0;padding:8px;background:var(--surface);border:1px solid var(--border-color);border-radius:4px;font-size:11px;font-family:monospace;overflow-x:auto;max-height:200px;overflow-y:auto;white-space:pre-wrap;word-break:break-all}.lifecycle-badge{display:inline-block;font-size:10px;font-weight:600;text-transform:uppercase;padding:2px 6px;border-radius:3px;background:var(--ts-gray);color:#fff;letter-spacing:.5px}.result-item.lifecycle,.result-item.lifecycle.passed{border-left-color:var(--ts-gray);background:#59575d14}.result-item.lifecycle.failed{border-left-color:#d32f2f;background:#d32f2f14}.editor-tabs{display:flex;background:var(--surface);border-bottom:1px solid var(--border-color);padding:0 8px}.editor-tab{padding:10px 16px;border:none;background:transparent;color:var(--text-secondary);font-size:13px;font-weight:500;cursor:pointer;border-bottom:2px solid transparent;transition:all .2s;display:flex;align-items:center;gap:6px}.editor-tab:hover{color:var(--text-primary);background:var(--background)}.editor-tab.active{color:var(--primary-color);border-bottom-color:var(--primary-color)}.editor-tab.test-tab{margin:0 auto 0 0;font-weight:600}.editor-tab.test-tab.active{color:var(--primary-color)}.tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;font-size:11px;font-weight:600;background:var(--ts-gray);color:#fff;border-radius:9px}.editor-tab.active .tab-badge{background:var(--primary-color)}.lifecycle-toolbar-info{display:flex;align-items:center;gap:8px;color:var(--text-primary);font-size:14px;font-weight:500}.lifecycle-icon{font-size:16px}.lifecycle-hint{color:var(--text-secondary);font-weight:400;font-size:13px}.sidebar-tabs{display:flex;border-bottom:1px solid var(--border-color)}.sidebar-tab{flex:1;padding:10px;border:none;background:transparent;color:var(--text-secondary);font-size:13px;font-weight:500;cursor:pointer;border-bottom:2px solid transparent;transition:all .2s}.sidebar-tab:hover{color:var(--text-primary);background:var(--background)}.sidebar-tab.active{color:var(--primary-color);border-bottom-color:var(--primary-color)}.file-tree-section,.file-tree{flex:1;overflow:hidden;display:flex;flex-direction:column}.file-tree-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid var(--border-color);background:var(--background)}.file-tree-root-name{font-weight:600;font-size:13px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-tree-refresh{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:16px;padding:4px;border-radius:4px}.file-tree-refresh:hover{background:var(--surface);color:var(--primary-color)}.file-tree-header-actions{display:flex;align-items:center;gap:4px}.file-tree-action-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px;padding:4px 6px;border-radius:4px}.file-tree-action-btn:hover{background:var(--surface);color:var(--primary-color)}.folder-actions{position:relative;margin-left:auto}.folder-action-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:14px;font-weight:700;width:20px;height:20px;border-radius:4px;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s}.file-tree-item:hover .folder-action-btn{opacity:1}.folder-action-btn:hover{background:var(--primary-light);color:var(--primary-color)}.folder-actions-menu{position:absolute;top:100%;right:0;background:#fff;border:1px solid var(--border-color);border-radius:6px;box-shadow:0 4px 12px #00000026;z-index:100;min-width:140px;padding:4px 0}.folder-actions-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:none;background:none;text-align:left;font-size:13px;color:var(--text-primary);cursor:pointer}.folder-actions-menu button:hover{background:var(--primary-light);color:var(--primary-color)}.folder-actions-menu button.delete-action:hover{background:#fee2e2;color:#dc2626}.folder-actions-menu button.run-action{color:#16a34a;font-weight:500}.folder-actions-menu button.run-action:hover{background:#dcfce7;color:#15803d}.folder-actions-menu button:disabled{opacity:.5;cursor:not-allowed}.file-tree-run-btn{color:#16a34a!important}.file-tree-run-btn:hover:not(:disabled){background:#dcfce7!important}.file-tree-run-btn:disabled{opacity:.5;cursor:not-allowed}.file-tree-content{flex:1;overflow-y:auto;padding:4px 0}.file-tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px 16px;color:var(--text-secondary);text-align:center}.file-tree-empty p{margin:4px 0;font-size:13px}.file-tree-hint{font-size:12px;opacity:.7}.file-tree-item{display:flex;align-items:center;gap:6px;padding:6px 8px;cursor:pointer;font-size:13px;color:var(--text-primary);border-left:2px solid transparent;transition:all .15s;position:relative}.file-tree-item:hover{background:var(--background)}.file-tree-item.selected{background:#1976d214;border-left-color:var(--primary-color)}.file-tree-item.folder{color:var(--text-secondary)}.file-tree-item[draggable=true]{cursor:grab}.file-tree-item[draggable=true]:active{cursor:grabbing}.file-tree-item.dragging{opacity:.5;background:var(--background)}.file-tree-item.drag-over{background:#1976d226;border-left-color:var(--primary-color);border-left-width:3px}.file-tree-item.drag-over:after{content:"";position:absolute;left:0;right:0;top:0;bottom:0;border:2px dashed var(--primary-color);border-radius:4px;pointer-events:none}.file-tree-icon{font-size:14px;flex-shrink:0}.file-tree-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.file-tree-badge{font-size:10px;font-weight:600;padding:2px 6px;border-radius:10px;background:var(--primary-color);color:#fff;flex-shrink:0}.file-tree-failed-indicator{color:#ef4444;font-size:10px;margin-left:4px;flex-shrink:0}.folder-hooks-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px;padding:2px 4px;opacity:0;transition:opacity .2s;flex-shrink:0}.file-tree-item.folder:hover .folder-hooks-btn{opacity:1}.folder-hooks-btn:hover{color:var(--primary-color)}.folder-hooks-indicator{font-size:10px;color:var(--primary-color);margin-left:4px;flex-shrink:0}.header-version{margin-left:8px;font-size:11px;font-weight:400;color:#ffffff80;background:#ffffff1a;padding:2px 6px;border-radius:4px}.header-file-path{margin-left:12px;font-size:12px;font-weight:400;color:#ffffffb3;max-width:400px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-flex;align-items:center;gap:8px}.auto-save-indicator{font-size:11px;padding:2px 8px;border-radius:4px;flex-shrink:0}.auto-save-indicator.saving{background:#ffc10733;color:#ffc107;animation:pulse 1s ease-in-out infinite}.auto-save-indicator.saved{background:#4caf5033;color:#4caf50}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.folder-hooks-label{background:rgba(var(--ts-blue),.1);background:#e0f2fe;color:var(--ts-blue);padding:2px 8px;border-radius:4px;font-size:11px;font-weight:500;margin-right:6px}.help-modal{width:950px;max-width:95vw;height:85vh;max-height:85vh;display:flex;flex-direction:column;padding:0;overflow:hidden}.help-header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border-color);flex-shrink:0}.help-header h2{margin:0;font-size:20px;font-weight:500}.btn-close{background:none;border:none;font-size:24px;cursor:pointer;color:var(--text-secondary);padding:4px 8px;border-radius:4px;line-height:1}.btn-close:hover{background:var(--background);color:var(--text-primary)}.help-layout{display:flex;flex:1;overflow:hidden}.help-nav{width:200px;flex-shrink:0;background:var(--background);border-right:1px solid var(--border-color);padding:12px 0;overflow-y:auto}.help-nav-item{display:block;width:100%;padding:10px 20px;border:none;background:none;text-align:left;cursor:pointer;font-size:14px;color:var(--text-secondary);transition:background .2s,color .2s}.help-nav-item:hover{background:#0000000a;color:var(--text-primary)}.help-nav-item.active{background:#1976d21a;color:var(--primary-color);font-weight:500;border-left:3px solid var(--primary-color);padding-left:17px}.help-content{flex:1;overflow-y:auto;padding:24px 32px}.help-content h3{margin:0 0 8px;font-size:22px;font-weight:600;color:var(--text-primary)}.help-content>p{margin:0 0 24px;color:var(--text-secondary);font-size:15px;line-height:1.5}.help-feature{margin-bottom:24px;padding:16px 20px;background:var(--background);border-radius:8px}.help-feature h4{margin:0 0 12px;font-size:15px;font-weight:600;color:var(--text-primary)}.help-feature ol,.help-feature ul{margin:0;padding-left:20px}.help-feature li{margin-bottom:8px;line-height:1.5;color:var(--text-primary)}.help-feature li:last-child{margin-bottom:0}.help-feature p{margin:0 0 12px;line-height:1.5}.help-feature code{background:#0000000f;padding:2px 6px;border-radius:4px;font-family:SF Mono,Monaco,Courier New,monospace;font-size:13px;color:var(--primary-dark)}.help-tip{margin-bottom:24px;padding:14px 18px;background:#1976d214;border-left:3px solid var(--primary-color);border-radius:0 8px 8px 0;font-size:14px;line-height:1.5}.help-tip code{background:#0000000f;padding:2px 6px;border-radius:4px;font-family:SF Mono,Monaco,Courier New,monospace;font-size:13px}.help-code{margin:12px 0 0;padding:12px 16px;background:#1e1e1e;color:#d4d4d4;border-radius:6px;font-family:SF Mono,Monaco,Courier New,monospace;font-size:13px;line-height:1.5;overflow-x:auto;white-space:pre}.scan-project-btn{margin-top:8px}.scan-project-btn:disabled{opacity:.6;cursor:not-allowed}.matches-section{margin-top:12px}.matches-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;font-size:13px;color:var(--text-secondary)}.matches-actions{display:flex;gap:12px}.btn-link{background:none;border:none;color:var(--primary-color);cursor:pointer;font-size:12px;padding:0}.btn-link:hover{text-decoration:underline}.matches-list{max-height:200px;overflow-y:auto;border:1px solid var(--border-color);border-radius:6px;background:var(--surface)}.match-file-group{border-bottom:1px solid var(--border-color)}.match-file-group:last-child{border-bottom:none}.match-file-name{font-size:12px;font-weight:600;color:var(--text-primary);padding:8px 12px 4px;background:var(--background)}.match-item{display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;transition:background .15s}.match-item:hover{background:#00000008}.match-item input[type=checkbox]{flex-shrink:0}.match-location{font-size:13px;color:var(--text-primary);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.match-detail{font-size:12px;color:var(--text-secondary);margin-left:4px}.record-dialog{min-width:500px;max-width:600px}.record-dialog .modal-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid var(--border-color)}.record-dialog .modal-header h2{margin:0;font-size:18px}.record-dialog .modal-body{min-height:150px}.record-url-input{display:flex;flex-direction:column;gap:12px}.record-url-input p{margin:0;color:var(--text-primary)}.url-input{width:100%;padding:10px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px}.url-input:focus{outline:none;border-color:var(--primary-color)}.record-hint{font-size:13px;color:var(--text-secondary);margin-top:4px}.record-status{display:flex;align-items:center;gap:16px;padding:20px;background:var(--background);border-radius:8px;margin:16px 0}.record-status.recording{border-left:4px solid var(--error);background:#d32f2f0d}.record-status.processing{border-left:4px solid var(--warning);background:#f57c000d;justify-content:center}.recording-indicator{width:16px;height:16px;background:var(--error);border-radius:50%;animation:pulse 1.5s ease-in-out infinite;flex-shrink:0}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.9)}}.recording-info h3{margin:0 0 8px;font-size:16px;color:var(--text-primary)}.recording-info p{margin:0;font-size:13px;color:var(--text-secondary)}.processing-spinner{width:24px;height:24px;border:3px solid var(--border-color);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.record-preview h3{margin:0 0 12px;font-size:15px}.steps-preview{max-height:300px;overflow-y:auto;border:1px solid var(--border-color);border-radius:6px;background:var(--surface)}.step-preview-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-bottom:1px solid var(--border-color);font-size:13px}.step-preview-item:last-child{border-bottom:none}.step-number{font-weight:600;color:var(--text-secondary);min-width:24px}.step-description{color:var(--text-primary);font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.record-empty{text-align:center;padding:24px;color:var(--text-secondary)}.record-empty p{margin:0 0 8px}.record-error{color:var(--error);font-size:13px;padding:8px 12px;background:#d32f2f1a;border-radius:4px}.record-error-state{text-align:center;padding:20px}.record-error-state h3{margin:0 0 12px;color:var(--error)}.record-error-state .record-error{margin-bottom:16px}.btn-warning{background:var(--warning);color:#fff}.btn-warning:hover:not(:disabled){background:#e65100}.advanced-options{margin-top:16px;border-top:1px solid var(--border-color);padding-top:12px}.advanced-toggle{display:flex;align-items:center;gap:8px;background:none;border:none;padding:8px 0;font-size:13px;color:var(--text-secondary);cursor:pointer;width:100%;text-align:left}.advanced-toggle:hover{color:var(--text-primary)}.advanced-toggle .toggle-icon{font-size:10px;width:12px}.advanced-content{padding:12px 0 4px 20px}.option-row{display:flex;align-items:center;gap:12px;margin-bottom:8px}.option-row label{font-size:13px;color:var(--text-primary);white-space:nowrap;min-width:120px}.option-input{flex:1;padding:6px 10px;border:1px solid var(--border-color);border-radius:4px;font-size:13px;font-family:Monaco,Menlo,Ubuntu Mono,monospace}.option-input:focus{outline:none;border-color:var(--primary-color)}.option-hint{font-size:12px;color:var(--text-secondary);margin:4px 0 0}.json-editor-modal{width:600px;max-width:90vw;min-height:400px;max-height:80vh;display:flex;flex-direction:column;padding:0}.json-editor-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--border-color)}.json-editor-header h3{margin:0;font-size:16px;font-weight:600}.json-editor-toolbar{display:flex;align-items:center;gap:8px;padding:12px 20px;background:var(--background);border-bottom:1px solid var(--border-color)}.json-editor-toolbar .btn-small{padding:4px 12px;font-size:12px}.json-status{margin-left:auto;font-size:12px;font-weight:500;padding:4px 8px;border-radius:4px}.json-status.valid{color:var(--success);background:var(--success-light)}.json-status.invalid{color:var(--error);background:#fef2f2}.json-editor-content{flex:1;display:flex;flex-direction:column;padding:16px 20px;min-height:200px}.json-textarea{flex:1;width:100%;min-height:250px;padding:12px;border:1px solid var(--border-color);border-radius:4px;font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace;font-size:13px;line-height:1.5;resize:vertical;background:#fafafa}.json-textarea:focus{outline:none;border-color:var(--primary-color);background:#fff}.json-textarea.has-error{border-color:var(--error);background:#fef8f8}.json-error{margin-top:8px;padding:8px 12px;background:#fef2f2;border:1px solid #fecaca;border-radius:4px;color:var(--error);font-size:12px;font-family:monospace}.json-editor-footer{display:flex;justify-content:flex-end;gap:8px;padding:16px 20px;border-top:1px solid var(--border-color);background:var(--background)}.json-edit-button{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;margin-left:4px;background:var(--primary-light);border:1px solid var(--primary-color);border-radius:3px;color:var(--primary-color);font-size:11px;cursor:pointer;transition:background .2s}.json-edit-button:hover{background:var(--primary-color);color:#fff}.reopen-folder-prompt{display:flex;flex-direction:column;gap:8px;padding:12px;margin:8px;background:var(--primary-light);border:1px solid var(--primary-color);border-radius:6px;font-size:13px}.reopen-folder-prompt span{color:var(--text-secondary)}.reopen-folder-prompt strong{color:var(--text-primary);word-break:break-all}.reopen-folder-prompt .btn{align-self:flex-start}.toast-container{position:fixed;top:16px;right:16px;z-index:10000;display:flex;flex-direction:column;gap:8px;max-width:400px}.toast{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:6px;background:#fff;box-shadow:0 4px 12px #00000026;animation:toast-slide-in .3s ease}@keyframes toast-slide-in{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}.toast-icon{flex-shrink:0;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:50%;font-size:12px;font-weight:700}.toast-success .toast-icon{background:var(--success-light);color:var(--success)}.toast-error .toast-icon{background:#ffebee;color:var(--error)}.toast-warning .toast-icon{background:#fff3e0;color:var(--warning)}.toast-info .toast-icon{background:var(--primary-light);color:var(--primary-color)}.toast-message{flex:1;font-size:13px;color:var(--text-primary)}.toast-dismiss{flex-shrink:0;background:none;border:none;font-size:18px;color:var(--text-secondary);cursor:pointer;padding:0;line-height:1}.toast-dismiss:hover{color:var(--text-primary)}.variables-editor{display:flex;flex-direction:column;gap:8px}.variable-editor-item{display:flex;align-items:flex-start;gap:8px;padding:8px;background:var(--background);border-radius:4px}.variable-editor-item .var-name{flex:0 0 120px;position:relative}.variable-editor-item .var-value{flex:1;min-width:0}.variable-editor-item input,.variable-editor-item textarea{width:100%;padding:6px 8px;border:1px solid var(--border-color);border-radius:4px;font-size:13px;font-family:monospace}.variable-editor-item input:focus,.variable-editor-item textarea:focus{outline:none;border-color:var(--primary-color)}.variable-editor-item .var-actions{display:flex;gap:4px}.variable-editor-item .btn-icon{padding:4px 8px;background:none;border:1px solid var(--border-color);border-radius:4px;cursor:pointer;font-size:12px}.variable-editor-item .btn-icon:hover{background:var(--border-color)}.variable-editor-item .btn-icon.delete:hover{background:#ffebee;border-color:var(--error);color:var(--error)}.variable-editor-item.duplicate{background:#fff3e0}.variable-editor-item .duplicate-warning{position:absolute;right:6px;top:50%;transform:translateY(-50%);color:#f57c00;font-size:14px;cursor:help}.add-variable-btn{align-self:flex-start;padding:6px 12px;background:var(--primary-light);border:1px dashed var(--primary-color);border-radius:4px;color:var(--primary-color);font-size:13px;cursor:pointer}.add-variable-btn:hover{background:var(--primary-color);color:#fff;border-style:solid}.variables-section-header{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--border-color);margin-bottom:8px}.variables-section-header h4{margin:0;font-size:13px;font-weight:600;color:var(--text-primary)}.variables-empty{padding:16px;text-align:center;color:var(--text-secondary);font-size:13px;background:var(--background);border-radius:4px}.context-menu{position:fixed;background:#fff;border:1px solid var(--border-color);border-radius:6px;box-shadow:0 4px 12px #00000026;min-width:180px;z-index:10000;padding:4px 0}.context-menu-item{display:block;width:100%;padding:8px 12px;border:none;background:none;text-align:left;font-size:13px;color:var(--text-primary);cursor:pointer}.context-menu-item:hover:not(.disabled){background:var(--primary-light);color:var(--primary-color)}.context-menu-item.disabled{color:var(--text-secondary);cursor:not-allowed}.create-variable-dialog{background:var(--surface);border-radius:8px;min-width:400px;max-width:500px;box-shadow:0 4px 20px #00000026}.create-variable-dialog .modal-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--border-color)}.create-variable-dialog .modal-header h2{margin:0;font-size:16px;font-weight:600}.create-variable-dialog .modal-close{background:none;border:none;font-size:24px;color:var(--text-secondary);cursor:pointer;padding:0;line-height:1}.create-variable-dialog .modal-close:hover{color:var(--text-primary)}.create-variable-dialog .modal-body{padding:16px 20px}.create-variable-dialog .form-group{margin-bottom:16px}.create-variable-dialog .form-group:last-child{margin-bottom:0}.create-variable-dialog .form-group label{display:block;font-size:13px;font-weight:500;margin-bottom:6px;color:var(--text-primary)}.create-variable-dialog .form-group code{background:var(--background);padding:2px 6px;border-radius:3px;font-size:12px}.create-variable-dialog .field-values-list{display:flex;flex-direction:column;gap:6px}.create-variable-dialog .field-value-option{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--border-color);border-radius:4px;cursor:pointer;font-size:13px}.create-variable-dialog .field-value-option:hover{background:var(--background)}.create-variable-dialog .field-value-option input[type=radio]{margin:0}.create-variable-dialog .field-label{font-weight:500;color:var(--text-secondary);flex-shrink:0}.create-variable-dialog .field-value{color:var(--primary-color);font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.create-variable-dialog .single-field-value{display:flex;gap:8px;padding:8px 10px;background:var(--background);border-radius:4px;font-size:13px}.create-variable-dialog .variable-type-options{display:flex;flex-direction:column;gap:8px}.create-variable-dialog .type-option{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--border-color);border-radius:4px;cursor:pointer}.create-variable-dialog .type-option:hover{background:var(--background)}.create-variable-dialog .type-option input[type=radio]{margin:0}.create-variable-dialog .type-option span:nth-child(2){font-weight:500}.create-variable-dialog .type-hint{width:100%;margin-left:22px;font-size:12px;color:var(--text-secondary)}.create-variable-dialog .form-group input[type=text]{width:100%;padding:8px 10px;border:1px solid var(--border-color);border-radius:4px;font-size:14px}.create-variable-dialog .form-group input[type=text]:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 2px var(--primary-light)}.create-variable-dialog .variable-preview{margin-top:6px;font-size:12px;color:var(--text-secondary)}.create-variable-dialog .variable-preview code{background:var(--success-light);color:var(--success)}.create-variable-dialog .modal-footer{display:flex;justify-content:flex-end;gap:8px;padding:16px 20px;border-top:1px solid var(--border-color)}.prompt-dialog{min-width:400px;max-width:450px}.prompt-dialog .modal-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:16px;margin-bottom:16px;border-bottom:1px solid var(--border-color)}.prompt-dialog .modal-header h2{margin:0;font-size:18px}.prompt-dialog .modal-body{padding:0}.prompt-field{margin-bottom:16px}.prompt-field:last-child{margin-bottom:0}.prompt-field label{display:block;margin-bottom:6px;font-weight:500;color:var(--text-primary)}.prompt-field input[type=text]{width:100%;padding:10px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px;background:var(--bg-primary);color:var(--text-primary);box-sizing:border-box}.prompt-field input[type=text]:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 2px var(--primary-light)}
@@ -16,8 +16,8 @@
16
16
  overflow: hidden;
17
17
  }
18
18
  </style>
19
- <script type="module" crossorigin src="/assets/index-dXniUrbi.js"></script>
20
- <link rel="stylesheet" crossorigin href="/assets/index-oTTttNKd.css">
19
+ <script type="module" crossorigin src="/assets/index-Boo8ZrY_.js"></script>
20
+ <link rel="stylesheet" crossorigin href="/assets/index-OxNH9dW-.css">
21
21
  </head>
22
22
  <body>
23
23
  <div id="root"></div>
@@ -7,6 +7,7 @@ exports.apiBlocks = void 0;
7
7
  const jsonpath_plus_1 = require("jsonpath-plus");
8
8
  const xpath_1 = __importDefault(require("xpath"));
9
9
  const xmldom_1 = require("xmldom");
10
+ const assertions_1 = require("./assertions");
10
11
  // API Testing Blocks
11
12
  exports.apiBlocks = [
12
13
  // ============================================
@@ -278,9 +279,7 @@ exports.apiBlocks = [
278
279
  throw new Error('No response available. Make sure to call an API request first.');
279
280
  }
280
281
  const expectedStatus = params.STATUS;
281
- if (response.status !== expectedStatus) {
282
- throw new Error(`Expected status ${expectedStatus} but got ${response.status}`);
283
- }
282
+ (0, assertions_1.handleAssertion)(context, response.status === expectedStatus, `Expected status ${expectedStatus} but got ${response.status}`, { stepType: 'api_assert_status', expected: expectedStatus, actual: response.status });
284
283
  context.logger.info(`✓ Status is ${expectedStatus}`);
285
284
  return {
286
285
  _summary: `✓ Status ${response.status} === ${expectedStatus}`,
@@ -310,9 +309,7 @@ exports.apiBlocks = [
310
309
  const expectedValue = resolveVariables(params.VALUE, context);
311
310
  const actualValue = path ? getValueByPath(response.body, path) : response.body;
312
311
  const actualStr = typeof actualValue === 'string' ? actualValue : JSON.stringify(actualValue);
313
- if (!actualStr.includes(expectedValue)) {
314
- throw new Error(`Expected ${path || 'body'} to contain "${expectedValue}" but got "${actualStr}"`);
315
- }
312
+ (0, assertions_1.handleAssertion)(context, actualStr.includes(expectedValue), `Expected ${path || 'body'} to contain "${expectedValue}" but got "${actualStr}"`, { stepType: 'api_assert_body_contains', expected: expectedValue, actual: actualStr });
316
313
  context.logger.info(`✓ ${path || 'body'} contains "${expectedValue}"`);
317
314
  return {
318
315
  _summary: `✓ ${path || 'body'} contains "${expectedValue}"`,
@@ -0,0 +1,31 @@
1
+ import { ExecutionContext, SoftAssertionError } from '../types';
2
+ /**
3
+ * Handle an assertion result - either throw immediately or collect as soft assertion
4
+ * @param context - The execution context
5
+ * @param condition - Whether the assertion passed
6
+ * @param errorMessage - The error message if assertion fails
7
+ * @param details - Additional details about the assertion
8
+ */
9
+ export declare function handleAssertion(context: ExecutionContext, condition: boolean, errorMessage: string, details?: {
10
+ stepId?: string;
11
+ stepType?: string;
12
+ expected?: unknown;
13
+ actual?: unknown;
14
+ }): void;
15
+ /**
16
+ * Check if there are any soft assertion errors and throw a combined error if so
17
+ * @param context - The execution context
18
+ * @returns The collected errors (for reporting)
19
+ */
20
+ export declare function flushSoftAssertionErrors(context: ExecutionContext): SoftAssertionError[];
21
+ /**
22
+ * Get soft assertion errors without throwing
23
+ * @param context - The execution context
24
+ * @returns The collected errors
25
+ */
26
+ export declare function getSoftAssertionErrors(context: ExecutionContext): SoftAssertionError[];
27
+ /**
28
+ * Clear soft assertion errors
29
+ * @param context - The execution context
30
+ */
31
+ export declare function clearSoftAssertionErrors(context: ExecutionContext): void;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleAssertion = handleAssertion;
4
+ exports.flushSoftAssertionErrors = flushSoftAssertionErrors;
5
+ exports.getSoftAssertionErrors = getSoftAssertionErrors;
6
+ exports.clearSoftAssertionErrors = clearSoftAssertionErrors;
7
+ /**
8
+ * Handle an assertion result - either throw immediately or collect as soft assertion
9
+ * @param context - The execution context
10
+ * @param condition - Whether the assertion passed
11
+ * @param errorMessage - The error message if assertion fails
12
+ * @param details - Additional details about the assertion
13
+ */
14
+ function handleAssertion(context, condition, errorMessage, details) {
15
+ if (condition) {
16
+ return; // Assertion passed
17
+ }
18
+ // Assertion failed
19
+ if (context.softAssertions) {
20
+ // Soft assertion mode - collect error instead of throwing
21
+ const softError = {
22
+ message: errorMessage,
23
+ stepId: details?.stepId,
24
+ stepType: details?.stepType,
25
+ expected: details?.expected,
26
+ actual: details?.actual,
27
+ timestamp: new Date().toISOString(),
28
+ };
29
+ if (!context.softAssertionErrors) {
30
+ context.softAssertionErrors = [];
31
+ }
32
+ context.softAssertionErrors.push(softError);
33
+ // Log the soft assertion failure
34
+ context.logger.warn(`Soft assertion failed: ${errorMessage}`);
35
+ }
36
+ else {
37
+ // Hard assertion mode - throw immediately
38
+ throw new Error(errorMessage);
39
+ }
40
+ }
41
+ /**
42
+ * Check if there are any soft assertion errors and throw a combined error if so
43
+ * @param context - The execution context
44
+ * @returns The collected errors (for reporting)
45
+ */
46
+ function flushSoftAssertionErrors(context) {
47
+ const errors = context.softAssertionErrors || [];
48
+ if (errors.length > 0) {
49
+ // Clear the errors from context
50
+ context.softAssertionErrors = [];
51
+ // Create a combined error message
52
+ const errorMessages = errors.map((e, i) => ` ${i + 1}. ${e.message}`).join('\n');
53
+ const combinedMessage = `${errors.length} assertion(s) failed:\n${errorMessages}`;
54
+ throw new Error(combinedMessage);
55
+ }
56
+ return errors;
57
+ }
58
+ /**
59
+ * Get soft assertion errors without throwing
60
+ * @param context - The execution context
61
+ * @returns The collected errors
62
+ */
63
+ function getSoftAssertionErrors(context) {
64
+ return context.softAssertionErrors || [];
65
+ }
66
+ /**
67
+ * Clear soft assertion errors
68
+ * @param context - The execution context
69
+ */
70
+ function clearSoftAssertionErrors(context) {
71
+ context.softAssertionErrors = [];
72
+ }
@@ -4,6 +4,7 @@ export { logicBlocks } from './logic';
4
4
  export { lifecycleBlocks } from './lifecycle';
5
5
  export { dataDrivenBlocks } from './data-driven';
6
6
  export { procedureBlocks, registerProcedure, getProcedure, clearProcedures } from './procedures';
7
+ export { handleAssertion, flushSoftAssertionErrors, getSoftAssertionErrors, clearSoftAssertionErrors } from './assertions';
7
8
  import { BlockDefinition } from '../types';
8
9
  export declare const builtInBlocks: BlockDefinition[];
9
10
  export declare const blockRegistry: Map<string, BlockDefinition>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.blockRegistry = exports.builtInBlocks = exports.clearProcedures = exports.getProcedure = exports.registerProcedure = exports.procedureBlocks = exports.dataDrivenBlocks = exports.lifecycleBlocks = exports.logicBlocks = exports.playwrightBlocks = exports.apiBlocks = void 0;
3
+ exports.blockRegistry = exports.builtInBlocks = exports.clearSoftAssertionErrors = exports.getSoftAssertionErrors = exports.flushSoftAssertionErrors = exports.handleAssertion = exports.clearProcedures = exports.getProcedure = exports.registerProcedure = exports.procedureBlocks = exports.dataDrivenBlocks = exports.lifecycleBlocks = exports.logicBlocks = exports.playwrightBlocks = exports.apiBlocks = void 0;
4
4
  exports.registerBlock = registerBlock;
5
5
  exports.registerBlocks = registerBlocks;
6
6
  exports.getBlock = getBlock;
@@ -22,6 +22,11 @@ Object.defineProperty(exports, "procedureBlocks", { enumerable: true, get: funct
22
22
  Object.defineProperty(exports, "registerProcedure", { enumerable: true, get: function () { return procedures_1.registerProcedure; } });
23
23
  Object.defineProperty(exports, "getProcedure", { enumerable: true, get: function () { return procedures_1.getProcedure; } });
24
24
  Object.defineProperty(exports, "clearProcedures", { enumerable: true, get: function () { return procedures_1.clearProcedures; } });
25
+ var assertions_1 = require("./assertions");
26
+ Object.defineProperty(exports, "handleAssertion", { enumerable: true, get: function () { return assertions_1.handleAssertion; } });
27
+ Object.defineProperty(exports, "flushSoftAssertionErrors", { enumerable: true, get: function () { return assertions_1.flushSoftAssertionErrors; } });
28
+ Object.defineProperty(exports, "getSoftAssertionErrors", { enumerable: true, get: function () { return assertions_1.getSoftAssertionErrors; } });
29
+ Object.defineProperty(exports, "clearSoftAssertionErrors", { enumerable: true, get: function () { return assertions_1.clearSoftAssertionErrors; } });
25
30
  const api_2 = require("./api");
26
31
  const playwright_2 = require("./playwright");
27
32
  const logic_2 = require("./logic");
@@ -11,11 +11,12 @@ exports.lifecycleBlocks = [
11
11
  tooltip: 'A test case containing steps to execute',
12
12
  inputs: [
13
13
  { name: 'NAME', type: 'field', fieldType: 'multiline', default: 'Test Case' },
14
+ { name: 'SOFT_ASSERTIONS', type: 'field', fieldType: 'checkbox', default: false },
14
15
  { name: 'STEPS', type: 'statement' },
15
16
  ],
16
17
  execute: async (params, _context) => {
17
18
  // Marker block - steps are executed by the executor
18
- return { testCase: true, name: params.NAME, statement: 'STEPS' };
19
+ return { testCase: true, name: params.NAME, softAssertions: params.SOFT_ASSERTIONS, statement: 'STEPS' };
19
20
  },
20
21
  },
21
22
  // Data-Driven Test Case - runs multiple times with different data
@@ -26,6 +27,7 @@ exports.lifecycleBlocks = [
26
27
  tooltip: 'A data-driven test case that runs for each row of data (CSV format: header row, then data rows)',
27
28
  inputs: [
28
29
  { name: 'NAME', type: 'field', fieldType: 'text', default: 'Data-Driven Test' },
30
+ { name: 'SOFT_ASSERTIONS', type: 'field', fieldType: 'checkbox', default: false },
29
31
  { name: 'DATA', type: 'field', fieldType: 'multiline', default: 'username,password,expected\nuser1,pass1,true\nuser2,pass2,false' },
30
32
  { name: 'STEPS', type: 'statement' },
31
33
  ],
@@ -34,7 +36,7 @@ exports.lifecycleBlocks = [
34
36
  const csvData = params.DATA;
35
37
  const rows = csvData.trim().split('\n').map(row => row.split(',').map(cell => cell.trim()));
36
38
  if (rows.length < 2) {
37
- return { testCase: true, name: params.NAME, dataDriven: true, data: [], statement: 'STEPS' };
39
+ return { testCase: true, name: params.NAME, softAssertions: params.SOFT_ASSERTIONS, dataDriven: true, data: [], statement: 'STEPS' };
38
40
  }
39
41
  const headers = rows[0];
40
42
  const data = rows.slice(1).map((row, index) => {
@@ -52,7 +54,7 @@ exports.lifecycleBlocks = [
52
54
  });
53
55
  return { name: `Row ${index + 1}`, values };
54
56
  });
55
- return { testCase: true, name: params.NAME, dataDriven: true, data, statement: 'STEPS' };
57
+ return { testCase: true, name: params.NAME, softAssertions: params.SOFT_ASSERTIONS, dataDriven: true, data, statement: 'STEPS' };
56
58
  },
57
59
  },
58
60
  // Before All - runs once before all tests
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.logicBlocks = void 0;
4
+ const assertions_1 = require("./assertions");
4
5
  // Logic and Control Flow Blocks
5
6
  exports.logicBlocks = [
6
7
  // Set Variable
@@ -323,9 +324,7 @@ exports.logicBlocks = [
323
324
  execute: async (params, context) => {
324
325
  const condition = params.CONDITION;
325
326
  const message = resolveVariables(params.MESSAGE, context);
326
- if (!condition) {
327
- throw new Error(message);
328
- }
327
+ (0, assertions_1.handleAssertion)(context, condition, message, { stepType: 'logic_assert', expected: true, actual: condition });
329
328
  context.logger.info('✓ Assertion passed');
330
329
  },
331
330
  },
@@ -0,0 +1,5 @@
1
+ import { BlockDefinition } from '../../types';
2
+ /**
3
+ * Assertion blocks for Playwright (visibility, text, values)
4
+ */
5
+ export declare const assertionBlocks: BlockDefinition[];