test: polish soap wizard test run flow
This commit is contained in:
@@ -1553,6 +1553,9 @@ function currentUpstream() {
|
||||
|
||||
var customName = textValue('new-upstream-name');
|
||||
var customUrl = textValue('new-upstream-url');
|
||||
if (!customUrl && wizardProtocol === 'soap') {
|
||||
customUrl = textValue('soap-endpoint-override');
|
||||
}
|
||||
if (!customUrl) return null;
|
||||
|
||||
var authMode = textValue('new-upstream-auth-mode') || 'none';
|
||||
|
||||
@@ -103,6 +103,59 @@ const server = http.createServer((request, response) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.pathname === '/soap/leads' && request.method === 'POST') {
|
||||
let buffer = '';
|
||||
request.setEncoding('utf8');
|
||||
request.on('data', (chunk) => {
|
||||
buffer += chunk;
|
||||
});
|
||||
request.on('end', () => {
|
||||
const hasEmail = buffer.includes('<email>user@example.com</email>')
|
||||
|| buffer.includes('<m:email>user@example.com</m:email>');
|
||||
|
||||
if (!hasEmail) {
|
||||
response.writeHead(400, {
|
||||
'Content-Type': 'text/xml; charset=utf-8',
|
||||
'Cache-Control': 'no-store',
|
||||
});
|
||||
response.end([
|
||||
'<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">',
|
||||
'<soap:Body>',
|
||||
'<soap:Fault>',
|
||||
'<faultcode>Client</faultcode>',
|
||||
'<faultstring>missing email</faultstring>',
|
||||
'</soap:Fault>',
|
||||
'</soap:Body>',
|
||||
'</soap:Envelope>',
|
||||
].join(''));
|
||||
return;
|
||||
}
|
||||
|
||||
response.writeHead(200, {
|
||||
'Content-Type': 'text/xml; charset=utf-8',
|
||||
'Cache-Control': 'no-store',
|
||||
});
|
||||
response.end([
|
||||
'<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">',
|
||||
'<soap:Body>',
|
||||
'<CreateLeadResponse>',
|
||||
'<id>lead_soap_123</id>',
|
||||
'<status>created</status>',
|
||||
'</CreateLeadResponse>',
|
||||
'</soap:Body>',
|
||||
'</soap:Envelope>',
|
||||
].join(''));
|
||||
});
|
||||
request.on('error', () => {
|
||||
response.writeHead(500, {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
'Cache-Control': 'no-store',
|
||||
});
|
||||
response.end('fixture_error');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
writeJson(response, 404, { error: 'not_found' });
|
||||
});
|
||||
|
||||
|
||||
@@ -213,6 +213,84 @@ function buildRestWindowOperationPayload(name) {
|
||||
};
|
||||
}
|
||||
|
||||
const SOAP_TEST_WSDL = `<?xml version="1.0"?>
|
||||
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
xmlns:tns="urn:crm"
|
||||
targetNamespace="urn:crm">
|
||||
<binding name="LeadBinding" type="tns:LeadPortType">
|
||||
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
|
||||
<operation name="CreateLead">
|
||||
<soap:operation soapAction="urn:createLead"/>
|
||||
</operation>
|
||||
</binding>
|
||||
<service name="LeadService">
|
||||
<port name="LeadPort" binding="tns:LeadBinding">
|
||||
<soap:address location="http://127.0.0.1:${STREAM_FIXTURE_PORT}/soap/leads"/>
|
||||
</port>
|
||||
</service>
|
||||
</definitions>`;
|
||||
|
||||
function buildSoapOperationPayload(name) {
|
||||
return {
|
||||
name,
|
||||
display_name: 'Playwright SOAP Lead',
|
||||
category: 'sales',
|
||||
protocol: 'soap',
|
||||
target: {
|
||||
kind: 'soap',
|
||||
wsdl_ref: 'sample_wsdl_pending',
|
||||
service_name: 'Service',
|
||||
port_name: 'Port',
|
||||
operation_name: 'Operation',
|
||||
endpoint_override: `http://127.0.0.1:${STREAM_FIXTURE_PORT}/soap/leads`,
|
||||
soap_version: 'soap_11',
|
||||
soap_action: 'urn:createLead',
|
||||
binding_style: 'document_literal',
|
||||
headers: [],
|
||||
metadata: {
|
||||
input_part_names: ['CreateLeadRequest'],
|
||||
output_part_names: ['CreateLeadResponse'],
|
||||
namespaces: ['urn:crm'],
|
||||
},
|
||||
},
|
||||
input_schema: schemaObject({
|
||||
email: schemaString(true),
|
||||
}),
|
||||
output_schema: schemaObject({
|
||||
id: schemaString(true),
|
||||
}),
|
||||
input_mapping: {
|
||||
rules: [
|
||||
{
|
||||
source: '$.mcp.email',
|
||||
target: '$.request.body.email',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
output_mapping: {
|
||||
rules: [
|
||||
{
|
||||
source: '$.response.body.id',
|
||||
target: '$.output.id',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
execution_config: {
|
||||
timeout_ms: 1000,
|
||||
headers: {},
|
||||
},
|
||||
tool_description: {
|
||||
title: 'Playwright SOAP Lead',
|
||||
description: 'Creates a lead through the local SOAP fixture.',
|
||||
tags: ['playwright', 'soap'],
|
||||
examples: [{ input: { email: 'user@example.com' } }],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function buildGrpcSessionOperationPayload(name) {
|
||||
return {
|
||||
name,
|
||||
@@ -474,10 +552,12 @@ async function mcpToolCall(session, toolName, argumentsValue) {
|
||||
module.exports = {
|
||||
ADMIN_EMAIL,
|
||||
ADMIN_PASSWORD,
|
||||
SOAP_TEST_WSDL,
|
||||
browserJson,
|
||||
buildGrpcSessionOperationPayload,
|
||||
buildRestAsyncJobOperationPayload,
|
||||
buildRestWindowOperationPayload,
|
||||
buildSoapOperationPayload,
|
||||
createAgent,
|
||||
createOperation,
|
||||
createPlatformApiKey,
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
const { test, expect } = require('@playwright/test');
|
||||
const { login, localized } = require('./helpers');
|
||||
const {
|
||||
SOAP_TEST_WSDL,
|
||||
buildSoapOperationPayload,
|
||||
createOperation,
|
||||
getCurrentWorkspace,
|
||||
login,
|
||||
localized,
|
||||
uniqueName,
|
||||
} = require('./helpers');
|
||||
|
||||
test('wizard loads and protocol selection updates flow', async ({ page }) => {
|
||||
await login(page);
|
||||
@@ -11,3 +19,77 @@ test('wizard loads and protocol selection updates flow', async ({ page }) => {
|
||||
await expect(page.locator('[data-step-counter]')).toContainText(/2/);
|
||||
await expect(page.locator('#step-panel-2 .step-panel-title')).toContainText(localized('Select upstream', 'Выберите upstream'));
|
||||
});
|
||||
|
||||
test('soap wizard uploads wsdl, applies discovered binding and runs test', async ({ page }) => {
|
||||
await login(page);
|
||||
const workspace = await getCurrentWorkspace(page);
|
||||
const operation = await createOperation(
|
||||
page,
|
||||
workspace.id,
|
||||
buildSoapOperationPayload(uniqueName('playwright_soap_wizard')),
|
||||
);
|
||||
|
||||
await page.goto(`/wizard/?mode=edit&operationId=${encodeURIComponent(operation.operation_id)}`);
|
||||
await page.locator('#btn-continue').click();
|
||||
await page.locator('#btn-continue').click();
|
||||
|
||||
await expect(page.locator('#step-panel-3-soap .step-panel-title')).toContainText(/WSDL/i);
|
||||
await page.evaluate((wsdl) => {
|
||||
const fileName = document.getElementById('wizard-soap-wsdl-name');
|
||||
if (fileName) fileName.textContent = 'lead.wsdl';
|
||||
}, SOAP_TEST_WSDL);
|
||||
await page.evaluate(async ({ workspaceId, operationId, wsdl }) => {
|
||||
const uploaded = await window.CrankApi.uploadWsdlFile(
|
||||
workspaceId,
|
||||
operationId,
|
||||
new TextEncoder().encode(wsdl),
|
||||
'lead.wsdl',
|
||||
);
|
||||
const services = await window.CrankApi.listSoapServices(
|
||||
workspaceId,
|
||||
operationId,
|
||||
null,
|
||||
);
|
||||
window.renderSoapServiceCatalog(services.services || []);
|
||||
return uploaded;
|
||||
}, {
|
||||
workspaceId: workspace.id,
|
||||
operationId: operation.operation_id,
|
||||
wsdl: SOAP_TEST_WSDL,
|
||||
});
|
||||
|
||||
await expect(page.locator('#wizard-soap-services-list button')).toContainText('CreateLead');
|
||||
await page.locator('#wizard-soap-services-list button').getByText('CreateLead').click();
|
||||
await expect(page.locator('#soap-service-name')).toHaveValue('LeadService');
|
||||
await expect(page.locator('#soap-port-name')).toHaveValue('LeadPort');
|
||||
await expect(page.locator('#soap-operation-name')).toHaveValue('CreateLead');
|
||||
|
||||
await page.locator('#btn-continue').click();
|
||||
await expect(page.locator('#step-panel-4 .step-panel-title')).toBeVisible();
|
||||
await page.locator('#tool-input-schema').fill(JSON.stringify({
|
||||
type: 'object',
|
||||
required: ['email'],
|
||||
properties: {
|
||||
email: { type: 'string' },
|
||||
},
|
||||
}, null, 2));
|
||||
await page.locator('#tool-output-schema').fill(JSON.stringify({
|
||||
type: 'object',
|
||||
required: ['id'],
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
},
|
||||
}, null, 2));
|
||||
await page.locator('#btn-continue').click();
|
||||
await expect(page.locator('[data-i18n="wizard.step5.test_title"]')).toContainText(localized('Test run', 'Тестовый запуск'));
|
||||
await page.locator('#tool-input-mapping').fill('email: "$.input.email"');
|
||||
await page.locator('#tool-output-mapping').fill('id: "$.response.body.id"');
|
||||
await page.locator('#tool-exec-config').fill('timeout_ms: 1000');
|
||||
|
||||
await page.locator('#wizard-test-input').fill(JSON.stringify({ email: 'user@example.com' }, null, 2));
|
||||
await page.locator('#wizard-run-test').click();
|
||||
|
||||
await expect(page.locator('#wizard-test-request-preview')).toHaveValue(/user@example.com/);
|
||||
await expect(page.locator('#wizard-test-response-preview')).toHaveValue(/lead_soap_123/);
|
||||
await expect(page.locator('#wizard-test-errors')).toHaveValue('[]');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user