trying to figure out jest issue.
This commit is contained in:
@ -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;
|
40
components/ConversationThread.tsx
Normal file
40
components/ConversationThread.tsx
Normal 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;
|
@ -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}>
|
||||
|
64
components/ui/MessageBubble.tsx
Normal file
64
components/ui/MessageBubble.tsx
Normal 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;
|
51
components/ui/__tests__/Message.spec.tsx
Normal file
51
components/ui/__tests__/Message.spec.tsx
Normal 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();
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user