trying to figure out jest issue.

This commit is contained in:
Jordan Hewitt
2025-01-29 17:17:59 -08:00
parent 0876db2dea
commit 889d898062
18 changed files with 7410 additions and 4790 deletions

View File

@ -1,107 +0,0 @@
interface ConversationPlayProps {
translator: Translator;
}
function ConversationPlay (props : ConversationPlayProps) {
const [language, setLanguage] = useState<string>(languages[0].code);
const [message, setMessage] = useState<string>('');
const [conversation, setConversation] = useState<Conversation | null>(null);
const startConversation = () => {
const speaker: Speaker = { id: "user", language };
const newConversation = new Conversation(translator, speaker);
setConversation(newConversation);
};
const addMessage = async () => {
if (conversation) {
conversation.addMessage({ id: "user", language }, message);
await conversation.translateLast();
setMessage('');
}
};
return (
<View>
<Text>Select Language:</Text>
{languages.map(lang => (
<Button key={lang.code} title={lang.name} onPress={() => setLanguage(lang.code)} />
))}
<Button title="Start Conversation" onPress={startConversation} />
{conversation && (
<>
<TextInput
placeholder="Type a message"
value={message}
onChangeText={setMessage}
/>
<Button title="Send Message" onPress={addMessage} />
{conversation.messages.map((msg, index) => (
<View key={index}>
<Text>{msg.text}</Text>
{msg.translation && <Text>Translation: {msg.translation}</Text>}
</View>
))}
</>
)}
</View>
);
};
export default ConversationPlay;import React, { useState } from 'react';
import { View, Text, TextInput, Button } from 'react-native';
import { Conversation, Speaker, Translator } from './index';
import {LANG_FLAGS} from "@/app/i18n/lang"
interface ConversationPlayProps {
translator: Translator;
}
const ConversationPlay: React.FC<ConversationPlayProps> = ({ translator }) => {
const [language, setLanguage] = useState<string>(languages[0].code);
const [message, setMessage] = useState<string>('');
const [conversation, setConversation] = useState<Conversation | null>(null);
const startConversation = () => {
const speaker: Speaker = { id: "user", language };
const newConversation = new Conversation(translator, speaker);
setConversation(newConversation);
};
const addMessage = async () => {
if (conversation) {
conversation.addMessage({ id: "user", language }, message);
await conversation.translateLast();
setMessage('');
}
};
return (
<View>
<Text>Select Language:</Text>
{languages.map(lang => (
<Button key={lang.code} title={lang.name} onPress={() => setLanguage(lang.code)} />
))}
<Button title="Start Conversation" onPress={startConversation} />
{conversation && (
<>
<TextInput
placeholder="Type a message"
value={message}
onChangeText={setMessage}
/>
<Button title="Send Message" onPress={addMessage} />
{conversation.messages.map((msg, index) => (
<View key={index}>
<Text>{msg.text}</Text>
{msg.translation && <Text>Translation: {msg.translation}</Text>}
</View>
))}
</>
)}
</View>
);
};
export default ConversationPlay;

View File

@ -0,0 +1,40 @@
import React, { useState, useEffect } from 'react';
import { View } from 'react-native';
import { Conversation } from '@/app/lib/conversation';
import MessageBubble from '@/components/ui/MessageBubble';
interface ConversationThreadProps {
conversation: Conversation;
}
const ConversationThread: React.FC<ConversationThreadProps> = ({ conversation }) => {
const [messages, setMessages] = useState<Message[]>(conversation.messages);
useEffect(() => {
const updateMessages = () => {
setMessages([...conversation.messages]);
};
conversation.on('messageAdded', updateMessages);
conversation.on('messageUpdated', updateMessages);
return () => {
conversation.off('messageAdded', updateMessages);
conversation.off('messageUpdated', updateMessages);
};
}, [conversation]);
const renderMessages = () => (
messages.map((message, index) => (
<MessageBubble key={index} message={message} />
))
);
return (
<View style={{ flex: 1 }}>
{renderMessages()}
</View>
);
};
export default ConversationThread;

View File

@ -36,30 +36,6 @@ const intelligence: Record<string, string> = {
H: "High",
};
// This is the configuration schema
const settings: SettingsElement[] = [
{
label: "Host Language",
type: "enum",
// You can override the way the value is displayed
values: ["en", "es", "fr"],
display: (v) => {
return longLang(v);
},
get: confGet.bind(null, "@hostLanguage", ""),
set: confSet.bind(null, "@hostLanguage"),
},
// Choose from a list, uses the standard phone navigation screens
{
label: "Intelligence",
title: "Select Intelligence",
type: "enum",
values: Object.keys(intelligence),
display: (v: string) => intelligence[v],
get: confGet.bind(null, "@int", "M"),
set: confSet.bind(null, "@int"),
},
];
export default function Settings() {
// Simply pass the schema here
@ -68,6 +44,32 @@ export default function Settings() {
const [languages, setLanguages] = useState<language_matrix | undefined>();
const [languagesLoaded, setLanguagesLoaded] = useState<boolean>(false);
// This is the configuration schema
const settings: SettingsElement[] = [
{
label: "Host Language",
type: "enum",
// You can override the way the value is displayed
values: ["en", "es", "fr"],
display: (v) => {
return longLang(v);
},
get: confGet.bind(null, "@hostLanguage", ""),
set: confSet.bind(null, "@hostLanguage"),
},
// Choose from a list, uses the standard phone navigation screens
{
label: "Intelligence",
title: "Select Intelligence",
type: "enum",
values: Object.keys(intelligence),
display: (v: string) => intelligence[v],
get: confGet.bind(null, "@int", "M"),
set: confSet.bind(null, "@int"),
},
];
useEffect(() => {
const fetchData = async () => {
try {
@ -80,7 +82,7 @@ export default function Settings() {
}
};
});
return (
<NavigationContainer>
<View style={styles.container}>

View File

@ -0,0 +1,64 @@
import { Translator } from "@/app/i18n/api";
import { Message, Speaker } from "@/app/lib/conversation";
import { useState } from "react";
import { StyleSheet, Text } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
type MessageProps = {
message: Message;
translator: Translator;
}
const MessageBubble = (props: MessageProps) => {
const [text, setText] = useState(props.message.text);
const [translatedText, setTranslatedText] = useState(props.message.text);
const [isTranslating, setIsTranslating] = useState<boolean>(false);
props.message.onTextUpdate = (message: Message) => {
setText(message.text);
}
props.message.onTextDone = async (message: Message) => {
setIsTranslating(true);
await props.message.translate(props.translator)
}
props.message.onTranslationDone = (message: Message) => {
if (!message.translation) throw new Error("Missing translation");
setTranslatedText(message.translation);
setIsTranslating(false);
}
const spId = props.message.speaker.id
return (
<SafeAreaView>
{text && (
<Text>{text}</Text>
)}
{translatedText &&
<Text>{translatedText}</Text>
}
</SafeAreaView>
)
}
// const bubbleStyle = StyleSheet.create({
// host: {
// },
// guest: {
// },
// })
// const textStyles = StyleSheet.create({
// native: {
// },
// translation: {
// },
// });
export default MessageBubble;

View File

@ -0,0 +1,51 @@
import React, { act } from 'react';
import { render, screen } from '@testing-library/react-native'
import MessageBubble from '@/components/ui/MessageBubble';
import { Conversation, Speaker } from '@/app/lib/conversation';
import {Translator} from '@/app/i18n/api';
import { View } from 'react-native';
describe('Message Component', () => {
const translator = new Translator('en', 'es');
const host : Speaker = {id : "host", language : "en"}
const guest : Speaker = {id : "guest", language: "es"}
let conversation : Conversation;
beforeEach(() => {
jest.clearAllMocks();
conversation = new Conversation(translator, host, guest);
});
it('renders the message text correctly', async () => {
conversation.addMessage(host, "Hello, World!");
const message = conversation[0];
render(<View></View>);
// render(<MessageBubble message={message} />);
expect(await screen.findByText(message.text as string)).toBeOnTheScreen();
});
it('translates the message when target language is provided', async () => {
const translatedText = 'Hola, ¿cómo estás?';
conversation.addMessage(host, "Hello, how are you?");
await conversation.translateLast();
render(<MessageBubble message={conversation[0]} translator={translator} />);
expect(await screen.findByText(translatedText)).toBeOnTheScreen();
});
it('widget still renders pre-translation', async () => {
const text = "Hello, how are you?"
const translatedText = 'Hola, ¿cómo estás?';
conversation.addMessage(host, text);
render(<MessageBubble message={conversation[0]} translator={translator} />);
expect(await screen.findByText(text)).toBeOnTheScreen();
expect(await screen.findByText(translatedText)).not.toBeOnTheScreen();
await act(async () => {
await conversation.translateLast();
});
expect(await screen.findByText(text)).toBeOnTheScreen();
expect(await screen.findByText(translatedText)).toBeOnTheScreen();
});
});