Skip to content

Commit

Permalink
Merge branch 'PSL-8488-UT-ANSWERS' of https://github.com/Azure-Sample…
Browse files Browse the repository at this point in the history
  • Loading branch information
Somesh-Microsoft committed Oct 25, 2024
2 parents ed1a8b7 + fec575d commit 77c00d8
Show file tree
Hide file tree
Showing 21 changed files with 1,640 additions and 987 deletions.
62 changes: 62 additions & 0 deletions code/frontend/__mocks__/SampleData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,65 @@ export const citationObj = {

export const AIResponseContent =
"Microsoft AI refers to the artificial intelligence capabilities and offerings provided by Microsoft. It encompasses a range of technologies and solutions that leverage AI to empower individuals and organizations to achieve more. Microsoft's AI platform, Azure AI, enables organizations to transform their operations by bringing intelligence and insights to employees and customers. It offers AI-optimized infrastructure, advanced models, and AI services designed for developers and data scientists is an ";
export const chatHistoryListData = [
{
id: "conv_id_1",
title: "mocked conversation title 1",
date: "2024-10-16T07:02:16.238267",
updatedAt: "2024-10-16T07:02:18.470231",
messages: [
{
id: "785e393a-defc-4ef4-8c0a-27ad41631c76",
role: "user",
date: "2024-10-16T07:02:16.798628",
content: "Hi",
feedback: "",
},
{
id: "dfc65527-5bb5-48a8-aaa4-5fba74b67a85",
role: "tool",
date: "2024-10-16T07:02:17.609894",
content: '{"citations": [], "intent": "Hi"}',
feedback: "",
},
{
id: "18fd8f70-ec1c-42bc-93d2-765d52c184eb",
role: "assistant",
date: "2024-10-16T07:02:18.470231",
content: "Hello! How can I assist you today?",
feedback: "",
},
],
},
{
id: "conv_id_2",
title: "mocked conversation title 2",
date: "2024-10-16T07:02:16.238267",
updatedAt: "2024-10-16T07:02:18.470231",
messages: [],
},
];

export const historyReadAPIResponse = [
{
content: "Hi",
createdAt: "2024-10-16T07:02:16.798628",
feedback: "",
id: "785e393a-defc-4ef4-8c0a-27ad41631c76",
role: "user",
},
{
content: '{"citations": [], "intent": "Hi"}',
createdAt: "2024-10-16T07:02:17.609894",
feedback: "",
id: "dfc65527-5bb5-48a8-aaa4-5fba74b67a85",
role: "tool",
},
{
content: "Hello! How can I assist you today?",
createdAt: "2024-10-16T07:02:18.470231",
feedback: "",
id: "18fd8f70-ec1c-42bc-93d2-765d52c184eb",
role: "assistant",
},
];
3 changes: 2 additions & 1 deletion code/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"dev": "tsc && vite",
"build": "tsc && vite build",
"watch": "tsc && vite build --watch",
"test": "jest --coverage --verbose"
"test": "jest --coverage --verbose",
"test:watch": "jest --coverage --verbose --watchAll"
},
"dependencies": {
"@babel/traverse": "^7.25.7",
Expand Down
2 changes: 1 addition & 1 deletion code/frontend/src/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type Citation = {
title: string | null;
filepath: string | null;
url: string | null;
metadata: string | null;
metadata: string | null | Record<string, string| number>;
chunk_id: string | null | number;
reindex_id?: string | null;
}
Expand Down
132 changes: 132 additions & 0 deletions code/frontend/src/components/Answer/Answer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -463,4 +463,136 @@ describe("Answer.tsx", () => {
fireEvent.copy(messageBox);
expect(window.alert).toHaveBeenCalledWith("Please consider where you paste this content.");
});
test("renders correctly without citations", async () => {
(global.fetch as jest.Mock).mockResolvedValue(
createFetchResponse(true, speechMockData)
);

await act(async () => {
render(
<Answer
answer={{ answer: "User Question without citations.", citations: [] }}
onCitationClicked={mockCitationClick}
onSpeak={mockOnSpeak}
isActive={true}
index={1}
/>
);
});

// Check if the answer text is rendered correctly
const answerTextElement = screen.getByText(/User Question without citations/i);
expect(answerTextElement).toBeInTheDocument();

// Verify that the citations container is not rendered
const citationsContainer = screen.queryByTestId("citations-container");
expect(citationsContainer).not.toBeInTheDocument();

// Verify that no references element is displayed
const referencesElement = screen.queryByTestId("no-of-references");
expect(referencesElement).not.toBeInTheDocument();
});
test("should stop audio playback when isActive is false", async () => {
(global.fetch as jest.Mock).mockResolvedValue(
createFetchResponse(true, speechMockData)
);

await act(async () => {
const { rerender } = render(
<Answer
answer={{
answer: componentPropsWithCitations.answer.answer,
citations: componentPropsWithCitations.answer.citations,
}}
isActive={true}
index={2}
onCitationClicked={mockCitationClick}
onSpeak={mockOnSpeak}
/>
);
});

const playBtn = screen.getByTestId("play-button");
expect(playBtn).toBeInTheDocument();

await act(async () => {
fireEvent.click(playBtn);
});

const pauseBtn = screen.getByTestId("pause-button");
expect(pauseBtn).toBeInTheDocument();

// Rerender with isActive set to false
await act(async () => {
render(
<Answer
answer={{
answer: componentPropsWithCitations.answer.answer,
citations: componentPropsWithCitations.answer.citations,
}}
isActive={false}
index={2}
onCitationClicked={mockCitationClick}
onSpeak={mockOnSpeak}
/>
);
});

expect(playBtn).toBeInTheDocument(); // Ensure the play button is back
screen.debug()
//expect(pauseBtn).not.toBeInTheDocument(); // Ensure pause button is not there
});
test("should initialize new synthesizer on index prop update", async () => {
(global.fetch as jest.Mock).mockResolvedValue(
createFetchResponse(true, speechMockData)
);

let rerender;
await act(async () => {
const { rerender: rerenderFunc } = render(
<Answer
answer={{
answer: componentPropsWithCitations.answer.answer,
citations: componentPropsWithCitations.answer.citations,
}}
isActive={true}
index={2}
onCitationClicked={mockCitationClick}
onSpeak={mockOnSpeak}
/>
);
rerender = rerenderFunc;
});

const playBtn = screen.getByTestId("play-button");
await act(async () => {
fireEvent.click(playBtn);
});

const pauseBtn = screen.getByTestId("pause-button");
expect(pauseBtn).toBeInTheDocument();

// Rerender with a different index
await act(async () => {
render(
<Answer
answer={{
answer: componentPropsWithCitations.answer.answer,
citations: componentPropsWithCitations.answer.citations,
}}
isActive={true}
index={3} // Change index
onCitationClicked={mockCitationClick}
onSpeak={mockOnSpeak}
/>
);
});

// Check if a new synthesizer has been initialized
const newPlayBtn = screen.getByTestId("play-button");
expect(newPlayBtn).toBeInTheDocument();
//screen.debug()
//expect(pauseBtn).not.toBeInTheDocument(); // Ensure previous pause button is gone
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.chatEmptyState {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.chatIcon {
height: 62px;
width: 62px;
}

.chatEmptyStateTitle {
font-family: "Segoe UI";
font-style: normal;
font-weight: 700;
font-size: 36px;
display: flex;
align-items: flex-end;
text-align: center;
margin-top: 24px;
margin-bottom: 0px;
}

.chatEmptyStateSubtitle {
margin-top: 16px;
font-family: "Segoe UI";
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 150%;
display: flex;
align-items: flex-end;
text-align: center;
letter-spacing: -0.01em;
color: #616161;
}

.dataText {
background: linear-gradient(90deg, #464FEB 10.42%, #8330E9 100%);
color: transparent;
background-clip: text;
}

.loadingContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh; /* Full viewport height */
}

.loadingIcon {
border: 8px solid #f3f3f3; /* Light grey */
border-top: 8px solid #3498db; /* Blue */
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from "react";
import { Stack } from "@fluentui/react";
import Azure from "../../assets/Azure.svg";
import Cards from "../../pages/chat/Cards_contract/Cards";
import styles from "./AssistantTypeSection.module.css";

type AssistantTypeSectionProps = {
assistantType: string;
isAssistantAPILoading: boolean;
};

enum assistantTypes {
default = "default",
contractAssistant = "contract assistant",
}

export const AssistantTypeSection: React.FC<AssistantTypeSectionProps> = ({
assistantType,
isAssistantAPILoading,
}) => {
return (
<Stack className={styles.chatEmptyState}>
<img
src={Azure}
className={styles.chatIcon}
aria-hidden="true"
alt="Chat with your data"
/>
{assistantType === assistantTypes.contractAssistant ? (
<>
<h1 className={styles.chatEmptyStateTitle}>Contract Summarizer</h1>
<h2 className={styles.chatEmptyStateSubtitle}>
AI-Powered assistant for simplified summarization
</h2>
<Cards />
</>
) : assistantType === assistantTypes.default ? (
<>
<h1 className={styles.chatEmptyStateTitle}>
Chat with your
<span className={styles.dataText}>&nbsp;Data</span>
</h1>
<h2 className={styles.chatEmptyStateSubtitle}>
This chatbot is configured to answer your questions
</h2>
</>
) : null}
{isAssistantAPILoading && (
<div className={styles.loadingContainer}>
<div className={styles.loadingIcon}></div>
<p>Loading...</p>
</div>
)}
</Stack>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
width: 300px;
}

.listContainer {
height: 100%;
overflow: hidden auto;
max-height: 80vh;
}

.itemCell {
min-height: 32px;
cursor: pointer;
Expand Down Expand Up @@ -42,30 +36,6 @@
background-color: #e6e6e6;
}

.chatGroup {
margin: auto 5px;
width: 100%;
}

.spinnerContainer {
display: flex;
justify-content: center;
align-items: center;
height: 22px;
margin-top: -8px;
}

.chatList {
width: 100%;
}

.chatMonth {
font-size: 14px;
font-weight: 600;
margin-bottom: 5px;
padding-left: 15px;
}

.chatTitle {
width: 80%;
overflow: hidden;
Expand Down
Loading

0 comments on commit 77c00d8

Please sign in to comment.