|
| 1 | +import { JSDOM } from "jsdom"; |
| 2 | + |
| 3 | +let initializeChatbot; |
| 4 | + |
| 5 | +beforeEach(async () => { |
| 6 | + const { window } = new JSDOM(`<!DOCTYPE html><body> |
| 7 | + <h1 id="chatbot-name"> </h1> |
| 8 | + <main> |
| 9 | + <div id="chat" class="chat-container" role="region" aria-label="Zone de conversation"> |
| 10 | + <!-- La conversation sera affichée ici --> |
| 11 | + </div> |
| 12 | + <div id="controls"> |
| 13 | + <div id="input-container"> |
| 14 | + <label id="user-input-label" class="sr-only" for="user-input">Écrivez votre message</label> |
| 15 | + <div id="user-input" contenteditable="true" placeholder="Écrivez votre message" tabindex="0" role="textbox" aria-labelledby="user-input-label" title="Écrivez votre message"></div> |
| 16 | + </div> |
| 17 | + <button id="send-button" type="button">Envoyer</button> |
| 18 | + </div> |
| 19 | + </main> |
| 20 | + <footer id="footer"> |
| 21 | + ChatMD – Outil libre & gratuit créé par <a href="http://eyssette.forge.apps.education.fr/">Cédric Eyssette</a> |
| 22 | + </footer> |
| 23 | + <script src="script.min.js"></script> |
| 24 | +</body>`); |
| 25 | + |
| 26 | + global.window = window; |
| 27 | + global.document = window.document; |
| 28 | + |
| 29 | + const mod = await import("../../../../app/js/core/chatbot/initialize.mjs"); |
| 30 | + |
| 31 | + initializeChatbot = mod.initializeChatbot; |
| 32 | +}); |
| 33 | + |
| 34 | +describe("initializeChatbot", () => { |
| 35 | + it("initializes a basic chatbot with no responses, no specific YAML and no params", async () => { |
| 36 | + const chatbotData = { |
| 37 | + title: "Test Chatbot", |
| 38 | + initialMessage: { |
| 39 | + content: ["Welcome to the test chatbot!"], |
| 40 | + choiceOptions: [], |
| 41 | + }, |
| 42 | + responses: [], |
| 43 | + }; |
| 44 | + const yaml = { |
| 45 | + searchInContent: false, |
| 46 | + useLLM: {}, |
| 47 | + responseTitles: ["## "], |
| 48 | + dynamicContent: false, |
| 49 | + typeWriter: false, |
| 50 | + }; |
| 51 | + const params = null; |
| 52 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 53 | + |
| 54 | + expect(chatbot.dynamicVariables).toEqual({}); |
| 55 | + expect(chatbot.responses).toEqual([]); |
| 56 | + expect(chatbot.initialMessage).toEqual( |
| 57 | + 'Welcome to the test chatbot!\n<ul class="messageOptions"></ul>', |
| 58 | + ); |
| 59 | + expect(document.getElementById("chatbot-name").innerHTML).toBe( |
| 60 | + "Test Chatbot", |
| 61 | + ); |
| 62 | + expect(document.title).toBe("Test Chatbot"); |
| 63 | + }); |
| 64 | + |
| 65 | + it("initializes a chatbot with choices dynamic variables from params", async () => { |
| 66 | + const chatbotData = { |
| 67 | + title: "Test Chatbot", |
| 68 | + initialMessage: { |
| 69 | + content: ["Welcome to the test chatbot!"], |
| 70 | + choiceOptions: [{ text: "Option 1", link: "option1" }], |
| 71 | + }, |
| 72 | + responses: [], |
| 73 | + }; |
| 74 | + const yaml = { |
| 75 | + searchInContent: false, |
| 76 | + useLLM: {}, |
| 77 | + responseTitles: ["## "], |
| 78 | + dynamicContent: true, |
| 79 | + typeWriter: false, |
| 80 | + }; |
| 81 | + const params = { |
| 82 | + name: "John", |
| 83 | + age: "30", |
| 84 | + actions: "e:who are you?|c:option 1", |
| 85 | + }; |
| 86 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 87 | + |
| 88 | + expect(chatbot.dynamicVariables).toEqual({ |
| 89 | + GETname: "John", |
| 90 | + GETage: "30", |
| 91 | + }); |
| 92 | + expect(chatbot.responses).toEqual([]); |
| 93 | + expect(chatbot.initialMessage).toEqual( |
| 94 | + 'Welcome to the test chatbot!\n<ul class="messageOptions"><li><a href="#option1">Option 1</a></li>\n</ul>', |
| 95 | + ); |
| 96 | + expect(document.getElementById("chatbot-name").innerHTML).toBe( |
| 97 | + "Test Chatbot", |
| 98 | + ); |
| 99 | + expect(document.title).toBe("Test Chatbot"); |
| 100 | + expect(chatbot.actions).toEqual(["e:who are you?", "c:option 1"]); |
| 101 | + }); |
| 102 | + |
| 103 | + it("initializes a chatbot with a title containing Markdown tags", async () => { |
| 104 | + const chatbotData = { |
| 105 | + title: "**Bold** and _Italic_ Chatbot", |
| 106 | + initialMessage: { |
| 107 | + content: ["Welcome to the test chatbot!"], |
| 108 | + choiceOptions: [], |
| 109 | + }, |
| 110 | + responses: [], |
| 111 | + }; |
| 112 | + const yaml = { |
| 113 | + searchInContent: false, |
| 114 | + useLLM: {}, |
| 115 | + responseTitles: ["## "], |
| 116 | + dynamicContent: false, |
| 117 | + typeWriter: false, |
| 118 | + }; |
| 119 | + const params = null; |
| 120 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 121 | + |
| 122 | + expect(document.getElementById("chatbot-name").innerHTML).toBe( |
| 123 | + "<strong>Bold</strong> and <em>Italic</em> Chatbot", |
| 124 | + ); |
| 125 | + expect(document.title).toBe("Bold and Italic Chatbot"); |
| 126 | + }); |
| 127 | + |
| 128 | + it("precalculate vector chatbot responses when searchInContent is true", async () => { |
| 129 | + const chatbotData = { |
| 130 | + title: "Test Chatbot", |
| 131 | + initialMessage: { |
| 132 | + content: ["Welcome to the test chatbot!"], |
| 133 | + choiceOptions: [], |
| 134 | + }, |
| 135 | + responses: [ |
| 136 | + { title: "Response 1", content: "This is the first response." }, |
| 137 | + { title: "Response 2", content: "This is the second response." }, |
| 138 | + ], |
| 139 | + }; |
| 140 | + const yaml = { |
| 141 | + searchInContent: true, |
| 142 | + useLLM: {}, |
| 143 | + responseTitles: ["## "], |
| 144 | + dynamicContent: false, |
| 145 | + typeWriter: false, |
| 146 | + }; |
| 147 | + const params = null; |
| 148 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 149 | + |
| 150 | + expect(chatbot.vectorChatBotResponses.length).toBe(2); |
| 151 | + expect(chatbot.vectorChatBotResponses[0]).toEqual({ |
| 152 | + response: 32.4, |
| 153 | + respo: 24.53333333333333, |
| 154 | + espon: 24.133333333333333, |
| 155 | + spons: 24.133333333333333, |
| 156 | + ponse: 24.133333333333333, |
| 157 | + respon: 26.6, |
| 158 | + espons: 26.2, |
| 159 | + sponse: 26.2, |
| 160 | + respons: 32, |
| 161 | + esponse: 31.6, |
| 162 | + first: 11.2, |
| 163 | + }); |
| 164 | + expect(chatbot.vectorChatBotResponses[1]).toEqual({ |
| 165 | + response: 32.4, |
| 166 | + respo: 24.53333333333333, |
| 167 | + espon: 24.133333333333333, |
| 168 | + spons: 24.133333333333333, |
| 169 | + ponse: 24.133333333333333, |
| 170 | + respon: 26.6, |
| 171 | + espons: 26.2, |
| 172 | + sponse: 26.2, |
| 173 | + respons: 32, |
| 174 | + esponse: 31.6, |
| 175 | + second: 11.6, |
| 176 | + secon: 5.6, |
| 177 | + econd: 5.4, |
| 178 | + }); |
| 179 | + }); |
| 180 | + |
| 181 | + it("sets up RAG content when specified as a string in YAML", async () => { |
| 182 | + const chatbotData = { |
| 183 | + title: "Test Chatbot", |
| 184 | + initialMessage: { |
| 185 | + content: ["Welcome to the test chatbot!"], |
| 186 | + choiceOptions: [], |
| 187 | + }, |
| 188 | + responses: [], |
| 189 | + }; |
| 190 | + const yaml = { |
| 191 | + searchInContent: false, |
| 192 | + useLLM: { |
| 193 | + RAGinformations: "This is the first response.", |
| 194 | + }, |
| 195 | + responseTitles: ["## "], |
| 196 | + dynamicContent: false, |
| 197 | + typeWriter: false, |
| 198 | + }; |
| 199 | + const params = null; |
| 200 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 201 | + |
| 202 | + expect(chatbot.RAG).toBeDefined(); |
| 203 | + |
| 204 | + expect(chatbot.RAG.content).toEqual(["This is the first response."]); |
| 205 | + expect(chatbot.RAG.vector).toEqual([ |
| 206 | + { |
| 207 | + first: 11.2, |
| 208 | + response: 6.2, |
| 209 | + respo: 2.2666666666666666, |
| 210 | + espon: 2.066666666666667, |
| 211 | + spons: 2.066666666666667, |
| 212 | + ponse: 2.066666666666667, |
| 213 | + respon: 3.3, |
| 214 | + espons: 3.1, |
| 215 | + sponse: 3.1, |
| 216 | + respons: 6, |
| 217 | + esponse: 5.8, |
| 218 | + }, |
| 219 | + ]); |
| 220 | + }); |
| 221 | + |
| 222 | + it("sets up RAG content when specified as an array in YAML", async () => { |
| 223 | + const chatbotData = { |
| 224 | + title: "Test Chatbot", |
| 225 | + initialMessage: { |
| 226 | + content: ["Welcome to the test chatbot!"], |
| 227 | + choiceOptions: [], |
| 228 | + }, |
| 229 | + responses: [], |
| 230 | + }; |
| 231 | + const yaml = { |
| 232 | + searchInContent: false, |
| 233 | + useLLM: { |
| 234 | + RAGinformations: [ |
| 235 | + "https://codimd.apps.education.fr/DeuOq2i2TCmibyyRSXlWhQ/download", |
| 236 | + ], |
| 237 | + }, |
| 238 | + responseTitles: ["## "], |
| 239 | + dynamicContent: false, |
| 240 | + typeWriter: false, |
| 241 | + }; |
| 242 | + const params = null; |
| 243 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 244 | + |
| 245 | + expect(chatbot.RAG.content).toEqual(["# Testons un fichier RAG simple"]); |
| 246 | + expect(chatbot.RAG.vector[0]).toEqual({ |
| 247 | + testons: 12, |
| 248 | + testo: 3.1, |
| 249 | + eston: 2.9, |
| 250 | + stons: 2.9, |
| 251 | + teston: 5.8, |
| 252 | + estons: 5.6, |
| 253 | + fichier: 12, |
| 254 | + fichi: 3.1, |
| 255 | + ichie: 2.9, |
| 256 | + chier: 2.9, |
| 257 | + fichie: 5.8, |
| 258 | + ichier: 5.6, |
| 259 | + simple: 11.6, |
| 260 | + simpl: 5.6, |
| 261 | + imple: 5.4, |
| 262 | + }); |
| 263 | + }); |
| 264 | + |
| 265 | + it("initializes a chatbot with default values for nextMessage and choiceOptionsLastResponse", async () => { |
| 266 | + const chatbotData = { |
| 267 | + title: "Test Chatbot", |
| 268 | + initialMessage: { |
| 269 | + content: ["Welcome to the test chatbot!"], |
| 270 | + choiceOptions: [], |
| 271 | + }, |
| 272 | + responses: [], |
| 273 | + }; |
| 274 | + const yaml = { |
| 275 | + searchInContent: false, |
| 276 | + useLLM: {}, |
| 277 | + responseTitles: ["## "], |
| 278 | + dynamicContent: false, |
| 279 | + typeWriter: false, |
| 280 | + }; |
| 281 | + const params = null; |
| 282 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 283 | + |
| 284 | + expect(chatbot.nextMessage).toEqual({ |
| 285 | + goto: "", |
| 286 | + lastMessageFromBot: "", |
| 287 | + selected: undefined, |
| 288 | + onlyIfKeywords: false, |
| 289 | + errorsCounter: 0, |
| 290 | + maxErrors: 3, |
| 291 | + messageIfKeywordsNotFound: "", |
| 292 | + }); |
| 293 | + expect(chatbot.choiceOptionsLastResponse).toEqual([]); |
| 294 | + }); |
| 295 | + |
| 296 | + it("handles an initial message with a unique section", async () => { |
| 297 | + const chatbotData = { |
| 298 | + title: "Test Chatbot", |
| 299 | + initialMessage: { |
| 300 | + content: [ |
| 301 | + '<section class="unique">This is a unique section message.</section>', |
| 302 | + "This is a normal message.", |
| 303 | + ], |
| 304 | + choiceOptions: [], |
| 305 | + }, |
| 306 | + responses: [], |
| 307 | + }; |
| 308 | + const yaml = { |
| 309 | + searchInContent: false, |
| 310 | + useLLM: {}, |
| 311 | + responseTitles: ["## "], |
| 312 | + dynamicContent: false, |
| 313 | + typeWriter: false, |
| 314 | + }; |
| 315 | + const params = null; |
| 316 | + const chatbot = await initializeChatbot(chatbotData, yaml, params); |
| 317 | + |
| 318 | + expect(chatbot.initialMessage).toEqual( |
| 319 | + '\n\nThis is a normal message.\n<ul class="messageOptions"></ul>', |
| 320 | + ); |
| 321 | + }); |
| 322 | +}); |
0 commit comments