# frozen_string_literal: true RSpec.describe DiscourseAi::Personas::Tools::ReadArtifact do fab!(:llm_model) let(:bot_user) { DiscourseAi::AiBot::EntryPoint.find_user_from_model(llm_model.name) } fab!(:post) fab!(:post2) { Fabricate(:post, user: post.user) } fab!(:artifact) do AiArtifact.create!( user: post.user, post: post, name: "Test Artifact", html: "
Test Content
", css: ".test { color: blue; }", js: "console.log('test');", ) end before { SiteSetting.ai_bot_enabled = true } describe "#invoke" do it "successfully reads a local artifact" do tool = described_class.new( { url: "#{Discourse.base_url}/discourse-ai/ai-bot/artifacts/#{artifact.id}" }, bot_user: bot_user, llm: llm_model.to_llm, context: DiscourseAi::Personas::BotContext.new(post: post), ) result = tool.invoke {} expect(result[:status]).to eq("success") new_artifact = AiArtifact.last expect(new_artifact.html).to eq(artifact.html) expect(new_artifact.css).to eq(artifact.css) expect(new_artifact.js).to eq(artifact.js) expect(new_artifact.metadata["cloned_from"]).to eq(artifact.id) end it "handles invalid URLs" do tool = described_class.new( { url: "invalid-url" }, bot_user: bot_user, llm: llm_model.to_llm, context: DiscourseAi::Personas::BotContext.new(post: post), ) result = tool.invoke {} expect(result[:status]).to eq("error") expect(result[:error]).to eq("Invalid URL") end it "handles non-existent artifacts" do tool = described_class.new( { url: "#{Discourse.base_url}/discourse-ai/ai-bot/artifacts/99999" }, bot_user: bot_user, llm: llm_model.to_llm, context: DiscourseAi::Personas::BotContext.new(post: post), ) result = tool.invoke {} expect(result[:status]).to eq("error") expect(result[:error]).to eq("Artifact not found") end it "handles external web pages" do stub_request(:get, "https://example.com").to_return(status: 200, body: <<~HTML)
External Content
HTML stub_request(:get, "https://example.com/style.css").to_return( status: 200, body: ".external { color: red; }", ) tool = described_class.new( { url: "https://example.com" }, bot_user: bot_user, llm: llm_model.to_llm, context: DiscourseAi::Personas::BotContext.new(post: post), ) result = tool.invoke {} expect(result[:status]).to eq("success") new_artifact = AiArtifact.last expect(new_artifact.html).to include("
External Content
") expect(new_artifact.css).to include(".external { color: red; }") expect(new_artifact.js).to include("console.log('test');") expect(new_artifact.metadata["imported_from"]).to eq("https://example.com") end it "respects MAX_HTML_SIZE limit" do large_content = "x" * (described_class::MAX_HTML_SIZE + 1000) stub_request(:get, "https://example.com").to_return(status: 200, body: <<~HTML)
#{large_content}
HTML tool = described_class.new( { url: "https://example.com" }, bot_user: bot_user, llm: llm_model.to_llm, context: DiscourseAi::Personas::BotContext.new(post: post), ) result = tool.invoke {} expect(result[:status]).to eq("success") new_artifact = AiArtifact.last expect(new_artifact.html.length).to be <= described_class::MAX_HTML_SIZE end end end