diff --git a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/index.ts b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/index.ts index 2a3026e7cc..91fe97bf92 100644 --- a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/index.ts +++ b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/index.ts @@ -22,4 +22,5 @@ export { default as ScheduleRow } from "./schedule-row/ScheduleRow.svelte"; export { default as TestflowNavigator } from "./testflow-navigator/TestflowNavigator.svelte"; export { default as TestDataRow } from "./test-data-row/TestDataRow.svelte"; export { default as RequestAssertionsTestFlow } from "./request-tests/RequestAssertionsTestFlow.svelte"; +export { default as RequestTestsTestFlow } from "./request-tests/RequestTestsTestFlow.svelte"; export { default as ResponseTestResults } from "./test-results-panel/ResponseTestResults.svelte"; diff --git a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-navigator/RequestNavigatorTestFlow.svelte b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-navigator/RequestNavigatorTestFlow.svelte index 2c13895b52..e18d1e1e50 100644 --- a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-navigator/RequestNavigatorTestFlow.svelte +++ b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-navigator/RequestNavigatorTestFlow.svelte @@ -55,6 +55,11 @@ id: RequestSectionEnum.AUTHORIZATION, count: 0, }, + { + name: "Scripts", + id: RequestSectionEnum.TESTS, + count: 0, + }, { name: "Assertions", id: RequestSectionEnum.ASSERTIONS, diff --git a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/RequestTestsTestFlow.svelte b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/RequestTestsTestFlow.svelte new file mode 100644 index 0000000000..92a543ee0e --- /dev/null +++ b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/RequestTestsTestFlow.svelte @@ -0,0 +1,133 @@ + + +
+
+
+
+
+ { + onTestsChange({ + ...tests, + testCaseMode: TestCaseModeEnum.NO_CODE, + }); + }} + > + Pre-Request Script + + + { + onTestsChange({ + ...tests, + testCaseMode: TestCaseModeEnum.SCRIPT, + }); + }} + id="request-tab-test-script" + class="rounded px-2 text-fs-12 py-1 btn-formatter" + style="position: relative; z-index: 2; background-color: {tests?.testCaseMode === + TestCaseModeEnum.SCRIPT + ? 'var(--bg-ds-surface-400)' + : 'transparent'}" + > + Post-Request Script + +
+
+
+
+ +
+ {#if tests?.testCaseMode === TestCaseModeEnum.SCRIPT} +
+

JavaScript Code

+
+ {:else if tests?.testCaseMode === TestCaseModeEnum.NO_CODE} +
+

JavaScript Code

+
+ {/if} +
+ +
+ {#if tests?.testCaseMode === TestCaseModeEnum.SCRIPT} + + +
+
+ +
+ +
+ + +
+ +
+
+ + +
+ {#if errorMessage} +
{errorMessage}
+ {/if} +
+
+ { + isError = false; + errorMessage = ""; + }} + /> +
+
+
+
+
+
+
+
+ + diff --git a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/pre-script/utils/common-snippets.ts b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/pre-script/utils/common-snippets.ts new file mode 100644 index 0000000000..6d1760abd3 --- /dev/null +++ b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/pre-script/utils/common-snippets.ts @@ -0,0 +1,22 @@ +export const predefinedTestSnippets = [ + { + title: "Get Environment Variables", + function: `sp.global.get("url");`, + }, + { + title: "Set Environment Variables", + function: `sp.global.set("url", "https://jsonplaceholder.typicode.com/todos");`, + }, + { + title: "Get Local Variables", + function: `sp.environment.get("url");`, + }, + { + title: "Set Local Variables", + function: `sp.environment.set("url", "https://jsonplaceholder.typicode.com/todos");`, + }, + { + title: "Set Timestamp Variables", + function: `sp.environment.set("timestamp", new Date());`, + }, +]; diff --git a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/script/Script.svelte b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/script/Script.svelte new file mode 100644 index 0000000000..af47d1e93c --- /dev/null +++ b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/script/Script.svelte @@ -0,0 +1,374 @@ + + +
+
+ +
+ +
+ + +
+ +
+
+ + +
+ {#if errorMessage} +
{errorMessage}
+ {/if} +
+
+ { + isError = false; + errorMessage = ""; + }} + /> +
+
+
+
+
+
+
+
+ + diff --git a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/script/utils/common-snippets.ts b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/script/utils/common-snippets.ts new file mode 100644 index 0000000000..9c048f1a65 --- /dev/null +++ b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/request-tests/sub-components/script/utils/common-snippets.ts @@ -0,0 +1,136 @@ +export const predefinedTestSnippets = [ + { + title: "Status Code is 200", + function: `sp.test("Status code is 200", function () { + sp.expect(sp.response.statusCode).to.equal(200); +});`, + }, + { + title: "Response time is less than 500ms", + function: `sp.test("Response time is less than 500ms", function () { + sp.expect(sp.response.time).to.be.lessThan(500); +});`, + }, + { + title: "Response body is not empty", + function: `sp.test("Response body is not empty", function () { + sp.expect(sp.response.body.text()).to.be.notEmpty(); +});`, + }, + { + title: "Content-Type is application/json", + function: `sp.test("Content-Type is application/json", function () { + sp.expect(sp.response.headers["Content-Type"]).to.contain("application/json"); +});`, + }, + { + title: "Response has id field", + function: `sp.test("Response has id field", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData).to.have.all.keys("id", "userId", "title", "completed"); +});`, + }, + { + title: "Response has success = true", + function: `sp.test("Response has success = true", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData.success).to.equal(true); +});`, + }, + { + title: "User object contains name and email", + function: `sp.test("User object contains name and email", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData.user).to.have.all.keys("name", "email"); +});`, + }, + { + title: "Array response contains at least one item", + function: `sp.test("Array response contains at least one item", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData.length).to.be.greaterThan(0); +});`, + }, + { + title: "Unauthorized request returns 401", + function: `sp.test("Unauthorized request returns 401", function () { + sp.expect(sp.response.statusCode).to.equal(401); + let jsonData = sp.response.body.json(); + sp.expect(jsonData.message).to.equal("Unauthorized"); +});`, + }, + { + title: "Response contains expected schema keys", + function: `sp.test("Response contains expected schema keys", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData).to.have.all.keys("id", "name", "email"); +});`, + }, + { + title: "Response contains token field", + function: `sp.test("Response contains token field", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData).to.exist("token"); +});`, + }, + { + title: "Token is a non-empty string", + function: `sp.test("Token is a non-empty string", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData.token).to.be.a("string"); + sp.expect(jsonData.token).to.be.notEmpty(); +});`, + }, + { + title: "Created resource returns 201", + function: `sp.test("Created resource returns 201", function () { + sp.expect(sp.response.statusCode).to.equal(201); +});`, + }, + { + title: "Response array contains specific field", + function: `sp.test("Response array contains specific field in objects", function () { + let jsonData = sp.response.body.json(); + jsonData.forEach(item => { + sp.expect(item).to.exist("id"); + }); +});`, + }, + { + title: "Response has error field when status 400", + function: `sp.test("Response has error field when status 400", function () { + if (sp.response.statusCode === 400) { + let jsonData = sp.response.body.json(); + sp.expect(jsonData).to.exist("error"); + } +});`, + }, + { + title: "Response contains pagination fields", + function: `sp.test("Response contains pagination fields", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData).to.include.keys("page", "limit", "total"); +});`, + }, + { + title: "Date field is valid ISO string", + function: `sp.test("Date field is valid ISO string", function () { + let jsonData = sp.response.body.json(); + let date = new Date(jsonData.createdAt); + sp.expect(isNaN(date.getTime())).to.equal(false); +});`, + }, + { + title: "Response includes expected message text", + function: `sp.test("Response includes expected message text", function () { + let jsonData = sp.response.body.json(); + sp.expect(jsonData.message).to.contain("success"); +});`, + }, + { + title: "Response has Content-Length header", + function: `sp.test("Response has Content-Length header", function () { + sp.expect(sp.response.headers).to.exist("Content-Length"); +});`, + }, +]; diff --git a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/test-flow-bottom-panel/TestFlowBottomPanel.svelte b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/test-flow-bottom-panel/TestFlowBottomPanel.svelte index 1280ad10f0..f7bd89bd93 100644 --- a/packages/@sparrow-workspaces/src/features/testflow-explorer/components/test-flow-bottom-panel/TestFlowBottomPanel.svelte +++ b/packages/@sparrow-workspaces/src/features/testflow-explorer/components/test-flow-bottom-panel/TestFlowBottomPanel.svelte @@ -18,6 +18,7 @@ RequestParameterTestFlow, RequestAuthorizationTestFlow, RequestAssertionsTestFlow, + RequestTestsTestFlow, ResponseErrorScreen, ResponseHeaders, ResponseNavigator, @@ -81,6 +82,8 @@ requestNavigation = "Headers"; } else if (tab === "Authorization") { requestNavigation = "Authorization"; + } else if (tab === "Scripts" || tab === RequestSectionEnum.TESTS) { + requestNavigation = RequestSectionEnum.TESTS; } else if (tab === "Assertions") { requestNavigation = "Assertions"; } else { @@ -390,6 +393,24 @@ responseHeader={selectedNodeResponse?.response?.headers ?? []} /> {/key} + {:else if requestNavigation === RequestSectionEnum.TESTS} + {#key selectedBlock?.id} + { + handleUpdateRequestData("tests", updatedTests); + }} + tabSplitDirection="horizontal" + onGenerateTestCases={undefined} + onGeneratePreScript={undefined} + isTestCasesGenerating={false} + isPreScriptGenerating={false} + /> + {/key} {/if}