Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/tz-testrun-tags-and-links.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,8 @@ Implemented in `testit-java-commons` (all Java adapters share this):
- Config: `testRunTags` / `TMS_TEST_RUN_TAGS` / `tmsTestRunTags`, `testRunLinks` / `TMS_TEST_RUN_LINKS` / `tmsTestRunLinks`
- Create path: tags/links on `createTestRun`
- Existing run: early merge in `AdapterStartupHelper` at startup
- **TODO — TEMPORARY WORKAROUND (remove after TMS fix):**
`GET /adapters/testRuns/{id}` returns empty `links`/`attachments`.
`TmsApiClient.getTestRun` falls back to `GET /api/v2/testRuns/{id}` for merge-on-update
(adapters `PUT` replaces those collections; tags are merged server-side).
Switch back to adapters GET once it returns links/attachments.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version=4.2.1
version=4.2.2

org.gradle.daemon=true
org.gradle.parallel=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,9 @@ public static List<UpdateLinkApiModel> convertTestRunUpdateLinks(List<LinkItem>
}

public static List<AssignAttachmentApiModel> buildAssignAttachmentApiModels(List<AttachmentApiResult> attachments) {
if (attachments == null || attachments.isEmpty()) {
return Collections.emptyList();
}
return attachments.stream().map(
attachment -> {
AssignAttachmentApiModel model = new AssignAttachmentApiModel();
Expand All @@ -549,6 +552,9 @@ public static List<AssignAttachmentApiModel> buildAssignAttachmentApiModels(List
}

public static List<UpdateLinkApiModel> buildUpdateLinkApiModels(List<LinkApiResult> links) {
if (links == null || links.isEmpty()) {
return Collections.emptyList();
}
return links.stream().map(
link -> {
UpdateLinkApiModel model = new UpdateLinkApiModel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.core.GenericType;
import ru.testit.adaptersapi.api.*;
import ru.testit.adaptersapi.invoker.ApiClient;
import ru.testit.adaptersapi.invoker.ApiException;
Expand All @@ -25,6 +26,7 @@ public class TmsApiClient implements ITmsApiClient {
private static final int TESTS_LIMIT = 100;
private static final UUID EMPTY_TEST_POINT_ID = UUID.fromString("00000000-0000-0000-0000-000000000000");

private final ApiClient apiClient;
private final TestRunsApi testRunsApi;
private final AutoTestsApi autoTestsApi;
private final AttachmentsApi attachmentsApi;
Expand All @@ -41,6 +43,7 @@ public TmsApiClient(ClientConfiguration config) {
apiClient.setApiKey(config.getPrivateToken());

clientConfiguration = config;
this.apiClient = apiClient;
testRunsApi = new TestRunsApi(apiClient);
autoTestsApi = new AutoTestsApi(apiClient);
attachmentsApi = new AttachmentsApi(apiClient);
Expand Down Expand Up @@ -83,7 +86,38 @@ public TestRunApiResult createTestRun() throws ApiException {

@Override
public TestRunApiResult getTestRun(String uuid) throws ApiException {
return testRunsApi.adaptersTestRunsIdGet(UUID.fromString(uuid));
// TODO(TEMPORARY WORKAROUND): remove getTestRunViaPublicApi once
// GET /adapters/testRuns/{id} returns links and attachments.
// Adapters GET currently stubs them as empty; UpdateEmptyTestRun then
// replaces those collections and wipes existing data on merge.
return getTestRunViaPublicApi(UUID.fromString(uuid));
}

/**
* FIXME: temporary workaround — delete this method when adapters GET is fixed.
* Until then, public API is the only source of real links/attachments for merge.
*/
private TestRunApiResult getTestRunViaPublicApi(UUID id) throws ApiException {
String path = "/api/v2/testRuns/" + apiClient.escapeString(id.toString());
String accept = apiClient.selectHeaderAccept("application/json");
String contentType = apiClient.selectHeaderContentType();
String[] authNames = new String[]{"PrivateToken", "Identity.Application"};
GenericType<TestRunApiResult> returnType = new GenericType<TestRunApiResult>() {};
return apiClient.invokeAPI(
"TmsApiClient.getTestRunViaPublicApi",
path,
"GET",
new ArrayList<>(),
null,
new LinkedHashMap<>(),
new LinkedHashMap<>(),
new LinkedHashMap<>(),
accept,
contentType,
authNames,
returnType,
false
).getData();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ private void updateTestRunMetadata() throws ApiException {
}

TestRunApiResult testRun = this.client.getTestRun(this.clientConfiguration.getTestRunId());
// getTestRun uses a temporary v2 fallback (see TmsApiClient) until adapters GET
// returns links/attachments; without that, merge would wipe them on PUT.
UpdateEmptyTestRunApiModel model = Converter.buildUpdateEmptyTestRunApiModel(testRun);
boolean changed = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;
import ru.testit.adaptersapi.model.AttachmentApiResult;
import ru.testit.adaptersapi.model.LinkApiResult;
import ru.testit.adaptersapi.model.LinkType;
import ru.testit.adaptersapi.model.TestRunApiResult;
Expand Down Expand Up @@ -54,23 +55,68 @@ void startTests_mergesTagsAndLinksEarly() throws Exception {
existing.setName("Old");
existing.setTags(Collections.singletonList("smoke"));
LinkApiResult oldLink = new LinkApiResult();
oldLink.setId(UUID.fromString("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"));
oldLink.setUrl("https://existing.example");
oldLink.setType(LinkType.RELATED);
existing.setLinks(Collections.singletonList(oldLink));
AttachmentApiResult oldAttachment = new AttachmentApiResult();
oldAttachment.setId(UUID.fromString("11111111-2222-3333-4444-555555555555"));
oldAttachment.setFileId("file-1");
oldAttachment.setType("text/plain");
oldAttachment.setSize(1f);
oldAttachment.setName("note.txt");
existing.setAttachments(Collections.singletonList(oldAttachment));
when(client.getTestRun(RUN_ID)).thenReturn(existing);

AdapterStartupHelper helper = new AdapterStartupHelper(
adapterConfig, config, client, LoggerFactory.getLogger(getClass()));
helper.startTests();

verify(client).updateTestRun(any(UpdateEmptyTestRunApiModel.class));
org.mockito.ArgumentCaptor<UpdateEmptyTestRunApiModel> captor =
org.mockito.ArgumentCaptor.forClass(UpdateEmptyTestRunApiModel.class);
verify(client).updateTestRun(captor.capture());
UpdateEmptyTestRunApiModel model = captor.getValue();
assertTrue(model.getTags().contains("smoke"));
assertTrue(model.getTags().contains("nightly"));
assertEquals(2, model.getLinks().size());
assertEquals(1, model.getAttachments().size());
assertEquals(oldAttachment.getId(), model.getAttachments().get(0).getId());
assertEquals(oldLink.getId(), model.getLinks().get(0).getId());
}

@Test
void startTests_tagsOnly_keepsExistingLinksAndAttachments() throws Exception {
ClientConfiguration config = configWith(RUN_ID, null, "nightly", null);

TestRunApiResult existing = new TestRunApiResult();
existing.setId(UUID.fromString(RUN_ID));
existing.setName("Old");
existing.setTags(Collections.singletonList("smoke"));
LinkApiResult oldLink = new LinkApiResult();
oldLink.setId(UUID.fromString("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"));
oldLink.setUrl("https://existing.example");
oldLink.setType(LinkType.RELATED);
existing.setLinks(Collections.singletonList(oldLink));
AttachmentApiResult oldAttachment = new AttachmentApiResult();
oldAttachment.setId(UUID.fromString("11111111-2222-3333-4444-555555555555"));
oldAttachment.setFileId("file-1");
oldAttachment.setType("text/plain");
oldAttachment.setSize(1f);
oldAttachment.setName("note.txt");
existing.setAttachments(Collections.singletonList(oldAttachment));
when(client.getTestRun(RUN_ID)).thenReturn(existing);

AdapterStartupHelper helper = new AdapterStartupHelper(
adapterConfig, config, client, LoggerFactory.getLogger(getClass()));
helper.startTests();

org.mockito.ArgumentCaptor<UpdateEmptyTestRunApiModel> captor =
org.mockito.ArgumentCaptor.forClass(UpdateEmptyTestRunApiModel.class);
verify(client).updateTestRun(captor.capture());
UpdateEmptyTestRunApiModel model = captor.getValue();
assertEquals(1, model.getLinks().size());
assertEquals(1, model.getAttachments().size());
assertEquals("https://existing.example", model.getLinks().get(0).getUrl());
}

@Test
Expand Down
Loading