Hi! I’m trying to test my chat agent with KaribuTest. I don’t think I’m clicking the Send button correctly in my test in MessageSubmit.
I tried to get access to the Send button with id and text, but that didn’t work. Now I’m trying javascript. I’m not sure if it’s working or how to tell what’s happening.
Here’s the test:
class ChatAgentCreatesProjectTest extends KaribuTest {
@Autowired
ProjectRepository projectRepository;
@Test
void chatAgentCreatesProject() throws Exception {
assertThat(projectRepository.count()).isEqualTo(0);
loginAndNavigate(ProjectsView.class);
MessageInput messageInput = _get(MessageInput.class, spec -> spec.withId("message-input"));
messageInput.getElement().setText("please create a new project called Vroomba");
messageInput.getElement().executeJs("this.shadowRoot.querySelector('textarea').dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter'}));");
Thread.sleep(2000);
MessageList messageList = _get(MessageList.class, spec -> spec.withId("message-list"));
assertThat(messageList.getItems()).hasSize(2); // This is where the test fails.
assertThat(messageList.getItems().get(0).getText()).isEqualTo("please create a new project called Vroomba");
assertThat(messageList.getItems().get(1).getText()).isEqualTo("Success! I have created a new project called Vroomba");
}
}
Here’s where I’m using the MessageList:
public class RightDrawer extends VerticalLayout {
private final List<ChatMessage> messages;
private final List<MessageListItem> items;
private final MessageList messageList;
private final AiGateway aiGateway;
private final AuthenticatedUser authenticatedUser;
public RightDrawer(AiGateway aiGateway, AuthenticatedUser authenticatedUser) {
this.aiGateway = aiGateway;
this.authenticatedUser = authenticatedUser;
this.messages = new ArrayList<>();
this.items = new ArrayList<>();
this.messageList = new MessageList(items);
this.messageList.setId("message-list");
createDrawer();
}
private void createDrawer() {
setId("right-drawer-layout");
setHeight("100%");
setWidth("500px");
addClassNames(LumoUtility.Background.CONTRAST_10);
Scroller messageScroller = createMessageScroller();
MessageInput messageInput = createMessageInput(messageScroller);
add(messageScroller, messageInput);
}
private Scroller createMessageScroller() {
Scroller scroller = new Scroller(messageList);
scroller.setSizeFull();
return scroller;
}
private MessageInput createMessageInput(Scroller messageScroller) {
MessageInput messageInput = new MessageInput();
messageInput.setId("message-input");
messageInput.setWidthFull();
ComponentUtil.addListener(messageInput, TimestampedSubmitEvent.class,
event -> handleMessageSubmit(event, messageScroller));
return messageInput;
}
private void handleMessageSubmit(TimestampedSubmitEvent event, Scroller messageScroller) {
String userMessageText = event.getValue();
LocalDateTime creationTime = event.getLocalDateTime();
String timestamp = event.getTimestamp();
String timezone = event.getTimezone();
Instant timestampInstant = timestamp != null ? Instant.parse(timestamp) : Instant.now();
try {
Account account = authenticatedUser.getCurrentAccount();
String userName = account.person().name();
String userEmail = account.username();
String userAvatar = account.getProfilePictureUri();
AccountId chatId = account.id();
MessageListItem userMessage = new MessageListItem(userMessageText, timestampInstant, userName, userAvatar);
UserMessageDto userMessageDto = new UserMessageDto(timestampInstant, creationTime, userName,
userMessageText, chatId, timezone, userEmail);
appendMessageAndReply(userMessage, messageScroller, userMessageDto);
} catch (UserNotAuthenticatedException ex) {
UI.getCurrent().navigate(LoginView.class);
}
}
private void appendMessageAndReply(MessageListItem userMessage, Scroller messageScroller, UserMessageDto userMessageDto) {
getUI().ifPresent(ui -> ui.access(() -> {
addMessagesToUI(userMessage);
MessageListItem reply = new MessageListItem("", Instant.now(), "Assistant");
appendReplyMessages(reply, messageScroller, userMessageDto);
}));
}
private void addMessagesToUI(MessageListItem userMessage) {
items.add(userMessage);
messageList.setItems(items);
messages.add(new UserMessage(userMessage.getText()));
}
private void appendReplyMessages(MessageListItem reply, Scroller messageScroller, UserMessageDto userMessageDto) {
items.add(reply);
messageList.setItems(items);
Flux<String> contentStream = aiGateway.sendMessageAndReceiveReplies(userMessageDto);
// Display error message to the user if needed
contentStream.subscribe(
content -> updateReplyContent(reply, content),
Throwable::printStackTrace,
() -> finalizeReply(reply)
);
scrollToBottom(messageScroller);
}
private void updateReplyContent(MessageListItem reply, String content) {
getUI().ifPresent(ui -> ui.access(() -> {
reply.setText(reply.getText() + content);
messageList.setItems(items);
}));
}
private void finalizeReply(MessageListItem reply) {
getUI().ifPresent(ui -> ui.access(() -> {
messages.add(new AiMessage(reply.getText()));
messageList.setItems(items);
}));
}
private void scrollToBottom(Scroller scroller) {
scroller.getElement().executeJs("this.scrollTo(0, this.scrollHeight);");
}
}