Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

package com.microsoft.copilot.eclipse.ui.chat.services;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -25,6 +26,8 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import org.eclipse.swt.widgets.Display;

import com.microsoft.copilot.eclipse.core.lsp.CopilotLanguageServerConnection;
import com.microsoft.copilot.eclipse.core.lsp.protocol.byok.ByokApiKey;
import com.microsoft.copilot.eclipse.core.lsp.protocol.byok.ByokListApiKeyResponse;
Expand Down Expand Up @@ -55,7 +58,6 @@ class ByokServiceTests {
void setUp() {
byokService = new ByokService(lsConnection);
byokService.bindByokPreferencePage(preferencePage);
clearInvocations(preferencePage);
}

@AfterEach
Expand All @@ -71,8 +73,7 @@ void testConfigureOllama_discoveryFailureKeepsSavedEndpointVisible() {

assertThrows(CompletionException.class, () -> byokService.configureOllama(OLLAMA_ENDPOINT).join());

verify(preferencePage).updateProviderUrlsDisplay(argThat(
providerUrls -> OLLAMA_ENDPOINT.equals(providerUrls.get(OLLAMA_PROVIDER))));
assertEquals(OLLAMA_ENDPOINT, awaitProviderUrlsDisplay().get(OLLAMA_PROVIDER));
}

@Test
Expand All @@ -86,7 +87,7 @@ void testLoadProviderUrls_ignoresBlankUrlsAndKeepsFirstDuplicate() {

byokService.loadProviderUrls().join();

verify(preferencePage).updateProviderUrlsDisplay(Map.of(OLLAMA_PROVIDER, OLLAMA_ENDPOINT));
assertEquals(Map.of(OLLAMA_PROVIDER, OLLAMA_ENDPOINT), awaitProviderUrlsDisplay());
}

@Test
Expand Down Expand Up @@ -118,15 +119,23 @@ void testConfigureOllama_discoveredModelsAreRegistered() {
}

@Test
void testDeleteOllamaConfig_removesEndpointBeforeRefresh() {
void testDeleteOllamaConfig_removesEndpoint() {
ByokListModelResponse emptyModels = new ByokListModelResponse();
emptyModels.setModels(List.of());
when(lsConnection.deleteByokProviderConfig(any())).thenReturn(completedStatus());
configureRefreshResponses(List.of());
when(lsConnection.listByokModels(any())).thenReturn(CompletableFuture.completedFuture(emptyModels));
when(lsConnection.listByokApiKeys(any(ByokApiKey.class)))
.thenReturn(CompletableFuture.completedFuture(new ByokListApiKeyResponse(List.of())));
when(lsConnection.listByokProviderConfigs(any(ByokListProviderConfigParams.class))).thenReturn(
CompletableFuture.completedFuture(new ByokListProviderConfigResponse(
List.of(new ByokProviderConfig(OLLAMA_PROVIDER, OLLAMA_ENDPOINT)))),
CompletableFuture.completedFuture(new ByokListProviderConfigResponse(List.of())));

byokService.loadProviderUrls().join();
clearInvocations(preferencePage);

byokService.deleteOllamaConfig().join();

verify(preferencePage).updateProviderUrlsDisplay(argThat(Map::isEmpty));
assertTrue(awaitProviderUrlsDisplay().isEmpty());
}

private void configureRefreshResponses(List<ByokModel> discoveredModels) {
Expand All @@ -147,4 +156,21 @@ private CompletableFuture<ByokStatusResponse> completedStatus() {
response.setSuccess(true);
return CompletableFuture.completedFuture(response);
}

// Drains pending UI Realm callbacks so the ISideEffect has pushed the latest value, then returns it.
@SuppressWarnings("unchecked")
private Map<String, String> awaitProviderUrlsDisplay() {
Display display = Display.getDefault();
if (display.getThread() == Thread.currentThread()) {
while (display.readAndDispatch()) {
// drain queued asyncExec callbacks while on the UI thread
}
} else {
display.syncExec(() -> { });
}
ArgumentCaptor<Map<String, String>> providerUrls = ArgumentCaptor.forClass(Map.class);
verify(preferencePage, atLeastOnce()).updateProviderUrlsDisplay(providerUrls.capture());
return providerUrls.getValue();
}

}
Loading