diff --git a/README.md b/README.md
index 464c518..43c5afe 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,9 @@ The main dashboard now exposes a test-selection panel before execution:
- `Select All` enables the full suite.
- `Clear All` disables every test.
- `Expand All` and `Collapse All` control the selection tree.
+- Search filters APIs, base URLs, endpoints, methods, and test names in the selection tree.
+- The results view also has live search for APIs, endpoints, tests, assertions, and error text.
+- Matching text is highlighted in both selection and result sections to make hits easier to spot.
- Environment, endpoint, and individual test checkboxes let you run only the subset you care about.
- Each page load starts with all tests selected by default.
- The dashboard and cURL import pages use local AdminLTE assets, so the UI does not rely on external CDNs at runtime.
diff --git a/src/ApiTestRunner.App/wwwroot/app.js b/src/ApiTestRunner.App/wwwroot/app.js
index 99a2cb7..5d800d8 100644
--- a/src/ApiTestRunner.App/wwwroot/app.js
+++ b/src/ApiTestRunner.App/wwwroot/app.js
@@ -6,6 +6,8 @@ const expandSelectionButton = document.getElementById("expandSelectionButton");
const collapseSelectionButton = document.getElementById("collapseSelectionButton");
const expandResultsButton = document.getElementById("expandResultsButton");
const collapseResultsButton = document.getElementById("collapseResultsButton");
+const selectionSearchInput = document.getElementById("selectionSearchInput");
+const resultsSearchInput = document.getElementById("resultsSearchInput");
const selectionContainer = document.getElementById("selectionContainer");
const selectionSummary = document.getElementById("selectionSummary");
const resultsSummary = document.getElementById("resultsSummary");
@@ -17,6 +19,8 @@ const testTemplate = document.getElementById("testTemplate");
let suiteManifest = null;
let selectedTestIds = new Set();
let lastRunState = null;
+let selectionSearchTerm = "";
+let resultsSearchTerm = "";
const selectionExpansionState = {
environments: new Map(),
@@ -116,6 +120,7 @@ function hydrateSelection(manifest) {
function renderSelection(manifest) {
selectionContainer.innerHTML = "";
+ const searchDisplayTerm = selectionSearchInput.value.trim();
if (!manifest || !manifest.environments || manifest.environments.length === 0) {
selectionSummary.textContent = "No tests were found in the configured YAML files.";
@@ -125,60 +130,74 @@ function renderSelection(manifest) {
}
const totalTestCount = manifest.totalTests;
- selectionSummary.textContent = `${selectedTestIds.size} of ${totalTestCount} tests selected`;
+ const filteredEnvironments = filterManifestEnvironments(manifest, selectionSearchTerm);
+ const visibleEndpointCount = filteredEnvironments.reduce((count, environmentEntry) => count + environmentEntry.endpoints.length, 0);
+ const visibleTestCount = filteredEnvironments.reduce(
+ (count, environmentEntry) => count + environmentEntry.endpoints.reduce((endpointCount, endpointEntry) => endpointCount + endpointEntry.tests.length, 0),
+ 0
+ );
+
+ selectionSummary.textContent = selectionSearchTerm
+ ? `${selectedTestIds.size} of ${totalTestCount} tests selected | ${visibleEndpointCount} endpoints and ${visibleTestCount} tests shown for "${searchDisplayTerm}"`
+ : `${selectedTestIds.size} of ${totalTestCount} tests selected`;
updateSelectionButtons(true);
- for (const environment of manifest.environments) {
- const environmentIds = environment.endpoints.flatMap((endpoint) => endpoint.tests.map((test) => test.id));
+ if (filteredEnvironments.length === 0) {
+ selectionContainer.innerHTML = `
No APIs or endpoints match "${escapeHtml(searchDisplayTerm)}".
`;
+ return;
+ }
+
+ for (const environmentEntry of filteredEnvironments) {
+ const { environment, environmentMatches, endpoints } = environmentEntry;
+ const visibleEnvironmentTestIds = endpoints.flatMap((endpointEntry) => endpointEntry.tests.map((test) => test.id));
+
const environmentNode = document.createElement("details");
environmentNode.className = "selection-group";
- environmentNode.open = selectionExpansionState.environments.get(environment.id) ?? true;
+ environmentNode.open = selectionSearchTerm ? true : selectionExpansionState.environments.get(environment.id) ?? true;
environmentNode.addEventListener("toggle", () => {
selectionExpansionState.environments.set(environment.id, environmentNode.open);
});
const environmentSummary = document.createElement("summary");
environmentSummary.className = "selection-summary-row";
-
- const environmentHeader = createSelectionHeader(
- environment.name,
- `${environment.baseUrl} - ${environment.totalTests} tests`,
- environmentIds,
+ environmentSummary.appendChild(createSelectionHeader(
+ highlightMatch(environment.name, selectionSearchTerm),
+ environmentMatches || !selectionSearchTerm
+ ? `${highlightMatch(environment.baseUrl, selectionSearchTerm)} - ${environment.totalTests} tests`
+ : `${highlightMatch(environment.baseUrl, selectionSearchTerm)} - ${visibleEnvironmentTestIds.length} matching tests`,
+ visibleEnvironmentTestIds,
toggleGroupSelection
- );
-
- environmentSummary.appendChild(environmentHeader);
- environmentNode.appendChild(environmentSummary);
+ ));
const environmentBody = document.createElement("div");
environmentBody.className = "selection-group-body";
- for (const endpoint of environment.endpoints) {
- const endpointIds = endpoint.tests.map((test) => test.id);
+ for (const endpointEntry of endpoints) {
+ const { endpoint, endpointMatches, tests } = endpointEntry;
+ const endpointIds = tests.map((test) => test.id);
+
const endpointNode = document.createElement("details");
endpointNode.className = "selection-subgroup";
- endpointNode.open = selectionExpansionState.endpoints.get(endpoint.id) ?? false;
+ endpointNode.open = selectionSearchTerm ? true : selectionExpansionState.endpoints.get(endpoint.id) ?? false;
endpointNode.addEventListener("toggle", () => {
selectionExpansionState.endpoints.set(endpoint.id, endpointNode.open);
});
const endpointSummary = document.createElement("summary");
endpointSummary.className = "selection-summary-row";
-
- const endpointHeader = createSelectionHeader(
- endpoint.name,
- `${endpoint.method} ${endpoint.path} - ${endpoint.tests.length} tests`,
+ endpointSummary.appendChild(createSelectionHeader(
+ highlightMatch(endpoint.name, selectionSearchTerm),
+ endpointMatches || !selectionSearchTerm
+ ? `${highlightMatch(endpoint.method, selectionSearchTerm)} ${highlightMatch(endpoint.path, selectionSearchTerm)} - ${tests.length} tests`
+ : `${highlightMatch(endpoint.method, selectionSearchTerm)} ${highlightMatch(endpoint.path, selectionSearchTerm)} - ${tests.length} matching tests`,
endpointIds,
toggleGroupSelection
- );
-
- endpointSummary.appendChild(endpointHeader);
- endpointNode.appendChild(endpointSummary);
+ ));
const testList = document.createElement("div");
testList.className = "selection-test-list";
- for (const test of endpoint.tests) {
+ for (const test of tests) {
const testRow = document.createElement("label");
testRow.className = "selection-test";
@@ -189,29 +208,31 @@ function renderSelection(manifest) {
const details = document.createElement("span");
details.className = "selection-label-stack";
- details.innerHTML = `${escapeHtml(test.name)}Expected HTTP ${test.expectedStatus}`;
+ details.innerHTML = `${highlightMatch(test.name, selectionSearchTerm)}Expected HTTP ${test.expectedStatus}`;
testRow.appendChild(checkbox);
testRow.appendChild(details);
testList.appendChild(testRow);
}
+ endpointNode.appendChild(endpointSummary);
endpointNode.appendChild(testList);
environmentBody.appendChild(endpointNode);
}
+ environmentNode.appendChild(environmentSummary);
environmentNode.appendChild(environmentBody);
selectionContainer.appendChild(environmentNode);
}
}
-function createSelectionHeader(title, detail, childTestIds, onToggle) {
+function createSelectionHeader(titleHtml, detailHtml, childTestIds, onToggle) {
const header = document.createElement("div");
header.className = "selection-header-row";
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
- checkbox.checked = childTestIds.every((testId) => selectedTestIds.has(testId));
+ checkbox.checked = childTestIds.length > 0 && childTestIds.every((testId) => selectedTestIds.has(testId));
checkbox.indeterminate = !checkbox.checked && childTestIds.some((testId) => selectedTestIds.has(testId));
checkbox.addEventListener("click", (event) => {
event.stopPropagation();
@@ -220,7 +241,7 @@ function createSelectionHeader(title, detail, childTestIds, onToggle) {
const labelStack = document.createElement("span");
labelStack.className = "selection-label-stack";
- labelStack.innerHTML = `${escapeHtml(title)}${escapeHtml(detail)}`;
+ labelStack.innerHTML = `${titleHtml}${detailHtml}`;
header.appendChild(checkbox);
header.appendChild(labelStack);
@@ -255,9 +276,67 @@ function getAllTestIds(manifest) {
);
}
+function filterManifestEnvironments(manifest, searchTerm) {
+ if (!searchTerm) {
+ return manifest.environments.map((environment) => ({
+ environment,
+ environmentMatches: false,
+ endpoints: environment.endpoints.map((endpoint) => ({
+ endpoint,
+ endpointMatches: false,
+ tests: endpoint.tests
+ }))
+ }));
+ }
+
+ return manifest.environments
+ .map((environment) => {
+ const environmentMatches =
+ matchesSearch(environment.name, searchTerm) ||
+ matchesSearch(environment.baseUrl, searchTerm);
+
+ const endpoints = environment.endpoints
+ .map((endpoint) => {
+ const endpointMatches = environmentMatches || endpointMatchesSelectionSearch(endpoint, searchTerm);
+ return {
+ endpoint,
+ endpointMatches,
+ tests: endpointMatches
+ ? endpoint.tests
+ : endpoint.tests.filter((test) => testMatchesSelectionSearch(test, searchTerm))
+ };
+ })
+ .filter((endpointEntry) => endpointEntry.endpointMatches || endpointEntry.tests.length > 0);
+
+ if (!environmentMatches && endpoints.length === 0) {
+ return null;
+ }
+
+ return {
+ environment,
+ environmentMatches,
+ endpoints
+ };
+ })
+ .filter((entry) => entry !== null);
+}
+
+function endpointMatchesSelectionSearch(endpoint, searchTerm) {
+ return (
+ matchesSearch(endpoint.name, searchTerm) ||
+ matchesSearch(endpoint.method, searchTerm) ||
+ matchesSearch(endpoint.path, searchTerm)
+ );
+}
+
+function testMatchesSelectionSearch(test, searchTerm) {
+ return matchesSearch(test.name, searchTerm);
+}
+
function renderState(state) {
lastRunState = state;
const run = state.lastRun;
+ const searchDisplayTerm = resultsSearchInput.value.trim();
setStatusError(Boolean(state.lastError));
document.getElementById("runStatus").textContent = buildStatusText(state);
@@ -282,59 +361,83 @@ function renderState(state) {
return;
}
- resultsSummary.textContent = `${run.passedTests} passed, ${run.failedTests} failed across ${run.environments.length} environments.`;
+ const filteredEnvironments = filterRunEnvironments(run, resultsSearchTerm);
+ const visibleEndpointCount = filteredEnvironments.reduce((count, environmentEntry) => count + environmentEntry.endpoints.length, 0);
+ const visibleTestCount = filteredEnvironments.reduce(
+ (count, environmentEntry) => count + environmentEntry.endpoints.reduce((endpointCount, endpointEntry) => endpointCount + endpointEntry.tests.length, 0),
+ 0
+ );
+
+ resultsSummary.textContent = resultsSearchTerm
+ ? `${run.passedTests} passed, ${run.failedTests} failed overall | ${visibleEndpointCount} endpoints and ${visibleTestCount} tests shown for "${searchDisplayTerm}"`
+ : `${run.passedTests} passed, ${run.failedTests} failed across ${run.environments.length} environments.`;
updateResultButtons(true);
synchronizeResultExpansionState(run);
- for (const environment of run.environments) {
+ if (filteredEnvironments.length === 0) {
+ environmentContainer.innerHTML = `No matching results
No APIs, endpoints, tests, assertions, or errors match "${escapeHtml(searchDisplayTerm)}".
`;
+ return;
+ }
+
+ for (const environmentEntry of filteredEnvironments) {
+ const { environment, environmentMatches, endpoints } = environmentEntry;
const environmentKey = getResultEnvironmentKey(environment);
+ const visibleTests = endpoints.flatMap((endpointEntry) => endpointEntry.tests);
+ const visiblePassedTests = visibleTests.filter((test) => test.isSuccess).length;
+ const visibleFailedTests = visibleTests.length - visiblePassedTests;
+
const environmentNode = environmentTemplate.content.firstElementChild.cloneNode(true);
- environmentNode.open = resultExpansionState.environments.get(environmentKey) ?? environment.failedTests > 0;
+ environmentNode.open = resultsSearchTerm ? true : resultExpansionState.environments.get(environmentKey) ?? environment.failedTests > 0;
environmentNode.addEventListener("toggle", () => {
resultExpansionState.environments.set(environmentKey, environmentNode.open);
});
- environmentNode.querySelector(".environment-name").textContent = environment.name;
- environmentNode.querySelector(".environment-url").textContent = environment.baseUrl;
- environmentNode.querySelector(".environment-stats").textContent =
- `${environment.passedTests} passed, ${environment.failedTests} failed, ${environment.totalTests} total`;
+ environmentNode.querySelector(".environment-name").innerHTML = highlightMatch(environment.name, resultsSearchTerm);
+ environmentNode.querySelector(".environment-url").innerHTML = highlightMatch(environment.baseUrl, resultsSearchTerm);
+ environmentNode.querySelector(".environment-stats").textContent = resultsSearchTerm && !environmentMatches
+ ? `${visiblePassedTests} passed, ${visibleFailedTests} failed, ${visibleTests.length} matching tests`
+ : `${environment.passedTests} passed, ${environment.failedTests} failed, ${environment.totalTests} total`;
const environmentBadge = environmentNode.querySelector(".environment-badge");
- environmentBadge.textContent = environment.failedTests === 0 ? "Passing" : "Issues";
- environmentBadge.className = `environment-badge ${environment.failedTests === 0 ? "passing" : "failing"}`;
+ const environmentIsPassing = resultsSearchTerm ? visibleFailedTests === 0 : environment.failedTests === 0;
+ environmentBadge.textContent = environmentIsPassing ? "Passing" : "Issues";
+ environmentBadge.className = `environment-badge ${environmentIsPassing ? "passing" : "failing"}`;
const endpointList = environmentNode.querySelector(".endpoint-list");
- for (const endpoint of environment.endpoints) {
+ for (const endpointEntry of endpoints) {
+ const { endpoint, endpointMatches, tests } = endpointEntry;
const endpointKey = getResultEndpointKey(environment, endpoint);
const endpointNode = endpointTemplate.content.firstElementChild.cloneNode(true);
- endpointNode.open = resultExpansionState.endpoints.get(endpointKey) ?? !endpoint.isSuccess;
+ endpointNode.open = resultsSearchTerm ? true : resultExpansionState.endpoints.get(endpointKey) ?? !endpoint.isSuccess;
endpointNode.addEventListener("toggle", () => {
resultExpansionState.endpoints.set(endpointKey, endpointNode.open);
});
- endpointNode.querySelector(".endpoint-name").textContent = endpoint.name;
- endpointNode.querySelector(".endpoint-meta").textContent =
- `${endpoint.method} ${endpoint.requestUrl} - ${Math.round(endpoint.durationMs)} ms`;
+ endpointNode.querySelector(".endpoint-name").innerHTML = highlightMatch(endpoint.name, resultsSearchTerm);
+ endpointNode.querySelector(".endpoint-meta").innerHTML =
+ `${highlightMatch(endpoint.method, resultsSearchTerm)} ${highlightMatch(endpoint.requestUrl, resultsSearchTerm)} - ${Math.round(endpoint.durationMs)} ms`;
const endpointBadge = endpointNode.querySelector(".endpoint-badge");
- endpointBadge.textContent = endpoint.isSuccess ? "Pass" : "Fail";
- endpointBadge.className = `endpoint-badge ${endpoint.isSuccess ? "passing" : "failing"}`;
+ const endpointVisibleFailedTests = tests.filter((test) => !test.isSuccess).length;
+ const endpointIsPassing = resultsSearchTerm ? endpointVisibleFailedTests === 0 : endpoint.isSuccess;
+ endpointBadge.textContent = endpointIsPassing ? "Pass" : "Fail";
+ endpointBadge.className = `endpoint-badge ${endpointIsPassing ? "passing" : "failing"}`;
endpointNode.querySelector(".response-body").textContent =
endpoint.responseBody || endpoint.errorMessage || "(empty response)";
const testList = endpointNode.querySelector(".test-list");
- endpoint.tests.forEach((test, testIndex) => {
+ tests.forEach((test, testIndex) => {
const testKey = getResultTestKey(environment, endpoint, test, testIndex);
const testNode = testTemplate.content.firstElementChild.cloneNode(true);
- testNode.open = resultExpansionState.tests.get(testKey) ?? !test.isSuccess;
+ testNode.open = resultsSearchTerm ? true : resultExpansionState.tests.get(testKey) ?? !test.isSuccess;
testNode.addEventListener("toggle", () => {
resultExpansionState.tests.set(testKey, testNode.open);
});
- testNode.querySelector(".test-name").textContent = test.name;
+ testNode.querySelector(".test-name").innerHTML = highlightMatch(test.name, resultsSearchTerm);
const testBadge = testNode.querySelector(".test-badge");
testBadge.textContent = test.isSuccess ? "Pass" : "Fail";
@@ -342,7 +445,7 @@ function renderState(state) {
const expectedText = `Expected ${test.expectedStatus}, actual ${test.actualStatus ?? "n/a"}`;
const errorSuffix = test.errorMessage ? ` - ${test.errorMessage}` : "";
- testNode.querySelector(".test-status-line").textContent = `${expectedText}${errorSuffix}`;
+ testNode.querySelector(".test-status-line").innerHTML = highlightMatch(`${expectedText}${errorSuffix}`, resultsSearchTerm);
const assertionList = testNode.querySelector(".assertion-list");
if (test.assertions.length === 0) {
@@ -351,7 +454,7 @@ function renderState(state) {
for (const assertion of test.assertions) {
const listItem = document.createElement("li");
listItem.className = assertion.isSuccess ? "assertion-pass" : "assertion-fail";
- listItem.textContent = `${assertion.rule} on ${assertion.field}: ${assertion.message}`;
+ listItem.innerHTML = `${highlightMatch(assertion.rule, resultsSearchTerm)} on ${highlightMatch(assertion.field, resultsSearchTerm)}: ${highlightMatch(assertion.message, resultsSearchTerm)}`;
assertionList.appendChild(listItem);
}
}
@@ -366,6 +469,76 @@ function renderState(state) {
}
}
+function filterRunEnvironments(run, searchTerm) {
+ if (!searchTerm) {
+ return run.environments.map((environment) => ({
+ environment,
+ environmentMatches: false,
+ endpoints: environment.endpoints.map((endpoint) => ({
+ endpoint,
+ endpointMatches: false,
+ tests: endpoint.tests
+ }))
+ }));
+ }
+
+ return run.environments
+ .map((environment) => {
+ const environmentMatches =
+ matchesSearch(environment.name, searchTerm) ||
+ matchesSearch(environment.baseUrl, searchTerm);
+
+ const endpoints = environment.endpoints
+ .map((endpoint) => {
+ const endpointMatches = environmentMatches || endpointMatchesRunSearch(endpoint, searchTerm);
+ return {
+ endpoint,
+ endpointMatches,
+ tests: endpointMatches
+ ? endpoint.tests
+ : endpoint.tests.filter((test) => testMatchesRunSearch(test, searchTerm))
+ };
+ })
+ .filter((endpointEntry) => endpointEntry.endpointMatches || endpointEntry.tests.length > 0);
+
+ if (!environmentMatches && endpoints.length === 0) {
+ return null;
+ }
+
+ return {
+ environment,
+ environmentMatches,
+ endpoints
+ };
+ })
+ .filter((entry) => entry !== null);
+}
+
+function endpointMatchesRunSearch(endpoint, searchTerm) {
+ return (
+ matchesSearch(endpoint.name, searchTerm) ||
+ matchesSearch(endpoint.method, searchTerm) ||
+ matchesSearch(endpoint.requestUrl, searchTerm) ||
+ matchesSearch(endpoint.errorMessage, searchTerm)
+ );
+}
+
+function testMatchesRunSearch(test, searchTerm) {
+ return (
+ matchesSearch(test.name, searchTerm) ||
+ matchesSearch(test.errorMessage, searchTerm) ||
+ test.assertions.some((assertion) => assertionMatchesSearch(assertion, searchTerm))
+ );
+}
+
+function assertionMatchesSearch(assertion, searchTerm) {
+ return (
+ matchesSearch(assertion.field, searchTerm) ||
+ matchesSearch(assertion.rule, searchTerm) ||
+ matchesSearch(assertion.message, searchTerm)
+ );
+}
+
function synchronizeResultExpansionState(run) {
const environmentKeys = new Set();
const endpointKeys = new Set();
@@ -534,8 +707,26 @@ function setResultExpansion(isOpen) {
renderState(lastRunState);
}
+function matchesSearch(value, searchTerm) {
+ return typeof value === "string" && value.toLowerCase().includes(searchTerm);
+}
+
+function highlightMatch(value, searchTerm) {
+ const safeValue = escapeHtml(value);
+ if (!searchTerm || typeof value !== "string") {
+ return safeValue;
+ }
+
+ const pattern = new RegExp(`(${escapeRegExp(searchTerm)})`, "ig");
+ return safeValue.replace(pattern, "$1");
+}
+
+function escapeRegExp(value) {
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+}
+
function escapeHtml(value) {
- return value
+ return String(value ?? "")
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">");
@@ -568,5 +759,19 @@ expandSelectionButton.addEventListener("click", () => setSelectionExpansion(true
collapseSelectionButton.addEventListener("click", () => setSelectionExpansion(false));
expandResultsButton.addEventListener("click", () => setResultExpansion(true));
collapseResultsButton.addEventListener("click", () => setResultExpansion(false));
+selectionSearchInput.addEventListener("input", () => {
+ selectionSearchTerm = selectionSearchInput.value.trim().toLowerCase();
+
+ if (suiteManifest) {
+ renderSelection(suiteManifest);
+ }
+});
+resultsSearchInput.addEventListener("input", () => {
+ resultsSearchTerm = resultsSearchInput.value.trim().toLowerCase();
+
+ if (lastRunState) {
+ renderState(lastRunState);
+ }
+});
initializeDashboard();
diff --git a/src/ApiTestRunner.App/wwwroot/index.html b/src/ApiTestRunner.App/wwwroot/index.html
index 4c34dc5..88414ed 100644
--- a/src/ApiTestRunner.App/wwwroot/index.html
+++ b/src/ApiTestRunner.App/wwwroot/index.html
@@ -164,6 +164,12 @@ T
@@ -183,6 +189,14 @@
+
diff --git a/src/ApiTestRunner.App/wwwroot/styles.css b/src/ApiTestRunner.App/wwwroot/styles.css
index 6b4fe0a..594b6f1 100644
--- a/src/ApiTestRunner.App/wwwroot/styles.css
+++ b/src/ApiTestRunner.App/wwwroot/styles.css
@@ -228,6 +228,45 @@ body.app-shell {
align-items: center;
}
+.selection-search-row {
+ margin-bottom: 0.9rem;
+}
+
+.selection-search-input {
+ display: flex;
+ align-items: center;
+ gap: 0.7rem;
+ width: 100%;
+ padding: 0.75rem 0.9rem;
+ border-radius: 0.9rem;
+ border: 1px solid rgba(15, 23, 42, 0.1);
+ background: rgba(255, 255, 255, 0.82);
+ color: #64748b;
+}
+
+.selection-search-input i {
+ color: #64748b;
+}
+
+.selection-search-input input {
+ width: 100%;
+ border: 0;
+ background: transparent;
+ color: #0f172a;
+ outline: none;
+}
+
+.selection-search-input input::placeholder {
+ color: #94a3b8;
+}
+
+.search-highlight {
+ padding: 0 0.14rem;
+ border-radius: 0.3rem;
+ background: rgba(255, 193, 7, 0.38);
+ color: inherit;
+}
+
.primary-button,
.ghost-button {
display: inline-flex;
diff --git a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.dll b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.dll
index 198cdac..18ecb7a 100644
Binary files a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.dll and b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.dll differ
diff --git a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.pdb b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.pdb
index 3682e98..30080e0 100644
Binary files a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.pdb and b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.Tests.pdb differ
diff --git a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.dll b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.dll
index a7f3535..04b3a01 100644
Binary files a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.dll and b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.dll differ
diff --git a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.pdb b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.pdb
index 55bea81..a297b37 100644
Binary files a/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.pdb and b/tests/ApiTestRunner.Core.Tests/bin/Release/net8.0/ApiTestRunner.Core.pdb differ
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfo.cs b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfo.cs
index 6a8fda2..619a1ea 100644
--- a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfo.cs
+++ b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfo.cs
@@ -13,7 +13,7 @@
[assembly: System.Reflection.AssemblyCompanyAttribute("ApiTestRunner.Core.Tests")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
-[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+65ac9495de0178332192ab628fca8ab9544113cb")]
+[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b6531e3d6db2e3250c965f806f08cd3f385db4fb")]
[assembly: System.Reflection.AssemblyProductAttribute("ApiTestRunner.Core.Tests")]
[assembly: System.Reflection.AssemblyTitleAttribute("ApiTestRunner.Core.Tests")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfoInputs.cache b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfoInputs.cache
index 3ed580d..53d95c4 100644
--- a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfoInputs.cache
+++ b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.AssemblyInfoInputs.cache
@@ -1 +1 @@
-97c02c74a7fbd12e17e64b87f8cfa9ae138c3c19a7df23cb9ddfd960b4de5054
+6bf5c1731d5b5f4edbe1a68420688a78362680f6b716751ae68a391bafad5036
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.csproj.AssemblyReference.cache b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.csproj.AssemblyReference.cache
index ab809de..0c21c4f 100644
Binary files a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.csproj.AssemblyReference.cache and b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.csproj.AssemblyReference.cache differ
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.dll b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.dll
index 198cdac..18ecb7a 100644
Binary files a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.dll and b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.dll differ
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.pdb b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.pdb
index 3682e98..30080e0 100644
Binary files a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.pdb and b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.pdb differ
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.sourcelink.json b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.sourcelink.json
index df0b08a..c835c59 100644
--- a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.sourcelink.json
+++ b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ApiTestRunner.Core.Tests.sourcelink.json
@@ -1 +1 @@
-{"documents":{"D:\\Projects\\Research\\EndpointTestRunner\\*":"https://raw.githubusercontent.com/javaChip56/EndpointTestRunner/65ac9495de0178332192ab628fca8ab9544113cb/*"}}
\ No newline at end of file
+{"documents":{"D:\\Projects\\Research\\EndpointTestRunner\\*":"https://raw.githubusercontent.com/javaChip56/EndpointTestRunner/b6531e3d6db2e3250c965f806f08cd3f385db4fb/*"}}
\ No newline at end of file
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ref/ApiTestRunner.Core.Tests.dll b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ref/ApiTestRunner.Core.Tests.dll
index a86bde4..38449a9 100644
Binary files a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ref/ApiTestRunner.Core.Tests.dll and b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/ref/ApiTestRunner.Core.Tests.dll differ
diff --git a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/refint/ApiTestRunner.Core.Tests.dll b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/refint/ApiTestRunner.Core.Tests.dll
index a86bde4..38449a9 100644
Binary files a/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/refint/ApiTestRunner.Core.Tests.dll and b/tests/ApiTestRunner.Core.Tests/obj/Release/net8.0/refint/ApiTestRunner.Core.Tests.dll differ