@kirrosh/zond 0.19.0 → 0.21.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.
@@ -816,6 +816,325 @@ h3 { font-size: 1.05rem; margin: 1rem 0 0.25rem; }
816
816
  .history-row:hover { background: var(--bg-hover); }
817
817
  .pagination { display: flex; gap: 0.5rem; margin: 1.5rem 0; align-items: center; }
818
818
 
819
+ /* ── Step method+path+status labels ── */
820
+ .step-path { font-family: var(--font-mono); font-size: 0.8rem; }
821
+ .step-status-code {
822
+ display: inline-block;
823
+ font-family: var(--font-mono);
824
+ font-size: 0.65rem;
825
+ font-weight: 600;
826
+ padding: 0.1rem 0.35rem;
827
+ border-radius: 3px;
828
+ margin-left: 0.35rem;
829
+ vertical-align: middle;
830
+ }
831
+ .step-status-code.status-ok { background: var(--pass-dim); color: var(--pass); }
832
+ .step-status-code.status-error { background: var(--fail-dim); color: var(--fail); }
833
+ .step-name-dim { color: var(--text-dim); font-size: 0.7rem; margin-left: 0.5rem; }
834
+
835
+ /* ── Suite link (endpoints → suites navigation) ── */
836
+ .suite-link {
837
+ color: var(--accent);
838
+ text-decoration: none;
839
+ cursor: pointer;
840
+ }
841
+ .suite-link:hover { text-decoration: underline; }
842
+ .suite-highlight {
843
+ animation: suite-flash 2s ease-out;
844
+ }
845
+ @keyframes suite-flash {
846
+ 0% { background: rgba(61, 139, 253, 0.25); }
847
+ 100% { background: transparent; }
848
+ }
849
+
850
+ /* ═══════════════════════════════════════════════════
851
+ Explorer Tab
852
+ ═══════════════════════════════════════════════════ */
853
+
854
+ .explorer-base-url {
855
+ display: flex;
856
+ align-items: center;
857
+ gap: 0.5rem;
858
+ padding: 0.75rem 1rem;
859
+ background: var(--bg-secondary);
860
+ border: 1px solid var(--border);
861
+ border-radius: var(--radius);
862
+ margin-bottom: 1rem;
863
+ }
864
+ .explorer-base-url .explorer-label {
865
+ font-size: 0.8rem;
866
+ font-weight: 600;
867
+ color: var(--text-dim);
868
+ white-space: nowrap;
869
+ }
870
+ .explorer-input {
871
+ background: var(--bg-inset);
872
+ border: 1px solid var(--border);
873
+ border-radius: var(--radius-sm);
874
+ color: var(--text);
875
+ font-family: var(--font-mono);
876
+ font-size: 0.85rem;
877
+ padding: 0.4rem 0.6rem;
878
+ flex: 1;
879
+ min-width: 0;
880
+ }
881
+ .explorer-input:focus {
882
+ outline: none;
883
+ border-color: var(--accent);
884
+ }
885
+ .explorer-input-sm { flex: unset; width: auto; }
886
+
887
+ /* Groups */
888
+ .explorer-list { display: flex; flex-direction: column; gap: 0.5rem; }
889
+ .explorer-group {
890
+ border: 1px solid var(--border);
891
+ border-radius: var(--radius);
892
+ overflow: hidden;
893
+ }
894
+ .explorer-group-title {
895
+ font-size: 0.85rem;
896
+ font-weight: 600;
897
+ padding: 0.6rem 1rem;
898
+ background: var(--bg-secondary);
899
+ cursor: pointer;
900
+ display: flex;
901
+ align-items: center;
902
+ gap: 0.5rem;
903
+ }
904
+ .explorer-group-title .tab-count {
905
+ font-size: 0.75rem;
906
+ background: var(--bg-hover);
907
+ padding: 0.1rem 0.5rem;
908
+ border-radius: var(--radius-pill);
909
+ color: var(--text-dim);
910
+ }
911
+
912
+ /* Endpoint row */
913
+ .explorer-endpoint {
914
+ display: flex;
915
+ align-items: center;
916
+ gap: 0.5rem;
917
+ padding: 0.5rem 1rem;
918
+ cursor: pointer;
919
+ border-top: 1px solid var(--border-subtle);
920
+ transition: background 0.15s;
921
+ }
922
+ .explorer-endpoint:hover { background: var(--bg-hover); }
923
+ .explorer-endpoint-path {
924
+ font-family: var(--font-mono);
925
+ font-size: 0.85rem;
926
+ font-weight: 500;
927
+ }
928
+ .explorer-endpoint-summary {
929
+ color: var(--text-dim);
930
+ font-size: 0.8rem;
931
+ margin-left: auto;
932
+ white-space: nowrap;
933
+ overflow: hidden;
934
+ text-overflow: ellipsis;
935
+ }
936
+ .explorer-auth-hint {
937
+ font-size: 0.65rem;
938
+ font-weight: 600;
939
+ padding: 0.1rem 0.35rem;
940
+ border-radius: var(--radius-sm);
941
+ background: var(--warn-dim);
942
+ color: var(--warn);
943
+ }
944
+
945
+ /* Detail / form */
946
+ .explorer-detail {
947
+ padding: 1rem;
948
+ background: var(--bg-raised);
949
+ border-top: 1px solid var(--border);
950
+ }
951
+ .explorer-section {
952
+ margin-bottom: 1rem;
953
+ }
954
+ .explorer-section-title {
955
+ font-size: 0.8rem;
956
+ font-weight: 600;
957
+ color: var(--text-dim);
958
+ margin-bottom: 0.5rem;
959
+ display: flex;
960
+ align-items: center;
961
+ gap: 0.5rem;
962
+ }
963
+
964
+ /* Parameters */
965
+ .explorer-param-row {
966
+ display: grid;
967
+ grid-template-columns: 140px 50px 90px 1fr;
968
+ gap: 0.5rem;
969
+ align-items: center;
970
+ margin-bottom: 0.35rem;
971
+ font-size: 0.85rem;
972
+ }
973
+ .explorer-param-name {
974
+ font-family: var(--font-mono);
975
+ font-weight: 500;
976
+ font-size: 0.8rem;
977
+ }
978
+ .explorer-param-location {
979
+ font-size: 0.7rem;
980
+ color: var(--text-muted);
981
+ background: var(--bg-inset);
982
+ padding: 0.1rem 0.3rem;
983
+ border-radius: var(--radius-sm);
984
+ text-align: center;
985
+ }
986
+ .explorer-param-type {
987
+ font-size: 0.75rem;
988
+ color: var(--text-dim);
989
+ font-family: var(--font-mono);
990
+ }
991
+ .explorer-required {
992
+ color: var(--fail);
993
+ font-weight: 700;
994
+ margin-left: 0.15rem;
995
+ }
996
+
997
+ /* Body editor */
998
+ .explorer-body-editor {
999
+ width: 100%;
1000
+ min-height: 120px;
1001
+ background: var(--bg-inset);
1002
+ border: 1px solid var(--border);
1003
+ border-radius: var(--radius-sm);
1004
+ color: var(--text);
1005
+ font-family: var(--font-mono);
1006
+ font-size: 0.85rem;
1007
+ padding: 0.5rem;
1008
+ resize: vertical;
1009
+ tab-size: 2;
1010
+ }
1011
+ .explorer-body-editor:focus { outline: none; border-color: var(--accent); }
1012
+ .explorer-content-type {
1013
+ font-size: 0.75rem;
1014
+ padding: 0.15rem 0.35rem;
1015
+ }
1016
+
1017
+ /* Custom headers */
1018
+ .explorer-headers-list {
1019
+ display: flex;
1020
+ flex-direction: column;
1021
+ gap: 0.35rem;
1022
+ }
1023
+ .explorer-header-pair {
1024
+ display: flex;
1025
+ gap: 0.35rem;
1026
+ align-items: center;
1027
+ }
1028
+ .explorer-header-pair input { flex: 1; }
1029
+ .explorer-remove-btn {
1030
+ background: none;
1031
+ border: 1px solid var(--border);
1032
+ border-radius: var(--radius-sm);
1033
+ color: var(--text-dim);
1034
+ cursor: pointer;
1035
+ font-size: 0.75rem;
1036
+ padding: 0.25rem 0.5rem;
1037
+ line-height: 1;
1038
+ }
1039
+ .explorer-remove-btn:hover { color: var(--fail); border-color: var(--fail); }
1040
+ .explorer-add-header-btn {
1041
+ background: none;
1042
+ border: none;
1043
+ color: var(--accent);
1044
+ cursor: pointer;
1045
+ font-size: 0.8rem;
1046
+ padding: 0.25rem 0;
1047
+ margin-top: 0.25rem;
1048
+ }
1049
+ .explorer-add-header-btn:hover { text-decoration: underline; }
1050
+
1051
+ /* Actions */
1052
+ .explorer-actions {
1053
+ display: flex;
1054
+ align-items: center;
1055
+ gap: 0.75rem;
1056
+ margin-top: 0.5rem;
1057
+ }
1058
+ .explorer-send-btn {
1059
+ background: var(--accent);
1060
+ color: #fff;
1061
+ border: none;
1062
+ border-radius: var(--radius);
1063
+ padding: 0.5rem 1.5rem;
1064
+ font-weight: 600;
1065
+ font-size: 0.85rem;
1066
+ cursor: pointer;
1067
+ transition: background 0.15s;
1068
+ }
1069
+ .explorer-send-btn:hover { background: var(--accent-hover); }
1070
+ .explorer-send-btn:disabled { opacity: 0.5; cursor: not-allowed; }
1071
+ .explorer-spinner { color: var(--text-dim); font-size: 0.85rem; }
1072
+
1073
+ /* Response */
1074
+ .explorer-response-container { margin-top: 1rem; }
1075
+ .explorer-response {
1076
+ border: 1px solid var(--border);
1077
+ border-radius: var(--radius);
1078
+ overflow: hidden;
1079
+ }
1080
+ .explorer-response-error { border-color: var(--fail); }
1081
+ .response-meta {
1082
+ display: flex;
1083
+ align-items: center;
1084
+ gap: 1rem;
1085
+ padding: 0.5rem 0.75rem;
1086
+ background: var(--bg-secondary);
1087
+ border-bottom: 1px solid var(--border);
1088
+ font-size: 0.85rem;
1089
+ }
1090
+ .response-status {
1091
+ font-weight: 700;
1092
+ font-family: var(--font-mono);
1093
+ }
1094
+ .response-status.status-2xx { color: var(--pass); }
1095
+ .response-status.status-3xx { color: var(--info); }
1096
+ .response-status.status-4xx { color: var(--warn); }
1097
+ .response-status.status-5xx { color: var(--fail); }
1098
+ .response-time { color: var(--text-dim); font-size: 0.8rem; }
1099
+ .response-size { color: var(--text-muted); font-size: 0.8rem; }
1100
+ .response-headers { padding: 0.5rem 0.75rem; }
1101
+ .response-headers summary {
1102
+ font-size: 0.8rem;
1103
+ color: var(--text-dim);
1104
+ cursor: pointer;
1105
+ }
1106
+ .response-headers-pre {
1107
+ font-size: 0.8rem;
1108
+ margin-top: 0.25rem;
1109
+ white-space: pre-wrap;
1110
+ word-break: break-all;
1111
+ }
1112
+ .response-body {
1113
+ padding: 0.75rem;
1114
+ background: var(--bg-inset);
1115
+ }
1116
+ .response-body pre {
1117
+ font-family: var(--font-mono);
1118
+ font-size: 0.8rem;
1119
+ white-space: pre-wrap;
1120
+ word-break: break-all;
1121
+ max-height: 500px;
1122
+ overflow-y: auto;
1123
+ margin: 0;
1124
+ }
1125
+ .response-error-msg {
1126
+ padding: 0.75rem;
1127
+ color: var(--fail);
1128
+ font-size: 0.85rem;
1129
+ }
1130
+
1131
+ /* JSON syntax highlighting */
1132
+ .json-key { color: var(--accent); }
1133
+ .json-string { color: var(--pass); }
1134
+ .json-number { color: var(--warn); }
1135
+ .json-boolean { color: var(--method-patch); }
1136
+ .json-null { color: var(--text-dim); font-style: italic; }
1137
+
819
1138
  /* ── Responsive ── */
820
1139
  @media (max-width: 768px) {
821
1140
  .health-strip { grid-template-columns: 1fr; gap: 1rem; }
@@ -824,4 +1143,6 @@ h3 { font-size: 1.05rem; margin: 1rem 0 0.25rem; }
824
1143
  .run-row { grid-template-columns: 48px 1fr 60px; }
825
1144
  .run-time, .run-duration { display: none; }
826
1145
  .runs-header { display: none; }
1146
+ .explorer-param-row { grid-template-columns: 1fr; }
1147
+ .explorer-endpoint-summary { display: none; }
827
1148
  }
@@ -93,7 +93,7 @@ function renderWarningBadges(warnings: string[]): string {
93
93
  if (w === "deprecated") return '<span class="warning-badge warning-deprecated">DEPRECATED</span>';
94
94
  if (w === "no_response_schema") return '<span class="warning-badge warning-schema">NO SCHEMA</span>';
95
95
  if (w === "no_responses_defined") return '<span class="warning-badge warning-schema">NO RESPONSES</span>';
96
- if (w.startsWith("required_params_no_examples")) return '<span class="warning-badge warning-params">MISSING EXAMPLES</span>';
96
+ if (w.startsWith("required_params_no_examples")) return "";
97
97
  return `<span class="warning-badge">${escapeHtml(w)}</span>`;
98
98
  }).join(" ");
99
99
  }
@@ -140,7 +140,8 @@ function renderEndpointDetail(ep: EndpointViewState): string {
140
140
 
141
141
  return `<div class="covering-suite">
142
142
  ${icon}
143
- <span class="suite-ref">${escapeHtml(step.file)}</span>
143
+ <a class="suite-ref suite-link" href="#" data-suite="${escapeHtml(step.suiteName)}"
144
+ onclick="event.stopPropagation();switchToSuite(this.dataset.suite)">${escapeHtml(step.file)}</a>
144
145
  <span class="dim" style="font-size:0.75rem;">&rarr; "${escapeHtml(step.stepName)}"</span>
145
146
  <span style="margin-left:auto;display:flex;align-items:center;gap:0.5rem;">${statusBadge}${duration}</span>
146
147
  </div>${assertionsHtml}${hintHtml}`;
@@ -149,13 +150,16 @@ function renderEndpointDetail(ep: EndpointViewState): string {
149
150
  }
150
151
 
151
152
  // Fallback: just file names
152
- const files = ep.coveringFiles.map(f =>
153
- `<div class="covering-suite">
153
+ const files = ep.coveringFiles.map(f => {
154
+ const fileName = basename(f);
155
+ const suiteName = fileName.replace(/\.(ya?ml)$/i, "");
156
+ return `<div class="covering-suite">
154
157
  <span class="step-icon" style="color:var(--text-dim);">&#9675;</span>
155
- <span class="suite-ref">${escapeHtml(basename(f))}</span>
158
+ <a class="suite-ref suite-link" href="#" data-suite="${escapeHtml(suiteName)}"
159
+ onclick="event.stopPropagation();switchToSuite(this.dataset.suite)">${escapeHtml(fileName)}</a>
156
160
  <span class="dim" style="font-size:0.75rem;">not run</span>
157
- </div>`
158
- ).join("");
161
+ </div>`;
162
+ }).join("");
159
163
  return files;
160
164
  }
161
165