201 lines
8.9 KiB
Ruby
201 lines
8.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe "AI image caption", type: :system, js: true do
|
|
fab!(:user) { Fabricate(:admin, refresh_auto_groups: true) }
|
|
fab!(:non_member_group) { Fabricate(:group) }
|
|
let(:user_preferences_ai_page) { PageObjects::Pages::UserPreferencesAi.new }
|
|
let(:topic_page) { PageObjects::Pages::Topic.new }
|
|
fab!(:topic)
|
|
fab!(:post) { Fabricate(:post, topic: topic) }
|
|
let(:composer) { PageObjects::Components::Composer.new }
|
|
let(:popup) { PageObjects::Components::AiCaptionPopup.new }
|
|
let(:dialog) { PageObjects::Components::Dialog.new }
|
|
let(:file_path) { file_from_fixtures("logo.jpg", "images").path }
|
|
let(:caption) do
|
|
"The image shows a stylized speech bubble icon with a multicolored border on a black background."
|
|
end
|
|
let(:caption_with_attrs) do
|
|
"#{caption} (#{I18n.t("discourse_ai.ai_helper.image_caption.attribution")})"
|
|
end
|
|
|
|
before do
|
|
Group.find_by(id: Group::AUTO_GROUPS[:admins]).add(user)
|
|
assign_fake_provider_to(:ai_helper_model)
|
|
assign_fake_provider_to(:ai_helper_image_caption_model)
|
|
SiteSetting.ai_helper_enabled = true
|
|
SiteSetting.ai_helper_enabled_features = "image_caption"
|
|
sign_in(user)
|
|
end
|
|
|
|
shared_examples "shows no image caption button" do
|
|
it "should not show an image caption button" do
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([file_path]) { composer.click_toolbar_button("upload") }
|
|
wait_for { composer.has_no_in_progress_uploads? }
|
|
expect(popup).to have_no_generate_caption_button
|
|
end
|
|
end
|
|
|
|
context "when not a member of ai helper group" do
|
|
before { SiteSetting.composer_ai_helper_allowed_groups = non_member_group.id.to_s }
|
|
include_examples "shows no image caption button"
|
|
end
|
|
|
|
context "when image caption feature is disabled" do
|
|
before { SiteSetting.ai_helper_enabled_features = "" }
|
|
include_examples "shows no image caption button"
|
|
end
|
|
|
|
context "when triggering caption with AI on desktop" do
|
|
it "should show an image caption in an input field" do
|
|
DiscourseAi::Completions::Llm.with_prepared_responses([caption]) do
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([file_path]) { composer.click_toolbar_button("upload") }
|
|
popup.click_generate_caption
|
|
expect(popup.has_caption_popup_value?(caption_with_attrs)).to eq(true)
|
|
popup.save_caption
|
|
wait_for { page.find(".image-wrapper img")["alt"] == caption_with_attrs }
|
|
expect(page.find(".image-wrapper img")["alt"]).to eq(caption_with_attrs)
|
|
end
|
|
end
|
|
|
|
it "should allow you to cancel a caption request" do
|
|
DiscourseAi::Completions::Llm.with_prepared_responses([caption]) do
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([file_path]) { composer.click_toolbar_button("upload") }
|
|
popup.click_generate_caption
|
|
popup.cancel_caption
|
|
expect(popup).to have_no_disabled_generate_button
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when triggering caption with AI on mobile", mobile: true do
|
|
it "should show update the image alt text with the caption" do
|
|
DiscourseAi::Completions::Llm.with_prepared_responses([caption]) do
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([file_path]) { page.find(".mobile-file-upload").click }
|
|
page.find(".mobile-preview").click
|
|
popup.click_generate_caption
|
|
wait_for { page.find(".image-wrapper img")["alt"] == caption_with_attrs }
|
|
expect(page.find(".image-wrapper img")["alt"]).to eq(caption_with_attrs)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "automatic image captioning" do
|
|
context "when ai helper is disabled" do
|
|
before { SiteSetting.ai_helper_enabled = false }
|
|
|
|
it "should not have the setting present in the user preferences page" do
|
|
user_preferences_ai_page.visit(user)
|
|
expect(user_preferences_ai_page).to have_no_ai_preference("pref-auto-image-caption")
|
|
end
|
|
end
|
|
|
|
context "when toggling the setting from the user preferences page" do
|
|
before { user.user_option.update!(auto_image_caption: false) }
|
|
|
|
it "should update the preference to enabled" do
|
|
user_preferences_ai_page.visit(user)
|
|
user_preferences_ai_page.toggle_setting("pref-auto-image-caption")
|
|
user_preferences_ai_page.save_changes
|
|
wait_for(timeout: 5) { user.reload.user_option.auto_image_caption }
|
|
expect(user.reload.user_option.auto_image_caption).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when the user preference is disabled" do
|
|
before { user.user_option.update!(auto_image_caption: false) }
|
|
|
|
it "should show a prompt when submitting a post with captionable images uploaded" do
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([file_path]) { composer.click_toolbar_button("upload") }
|
|
wait_for { composer.has_no_in_progress_uploads? }
|
|
composer.fill_title("I love using Discourse! It is my favorite forum software")
|
|
composer.create
|
|
expect(dialog).to be_open
|
|
end
|
|
|
|
it "should not show a prompt when submitting a post with no captionable images uploaded" do
|
|
original_file_path = Rails.root.join("spec/fixtures/images/logo.jpg")
|
|
temp_file_path = Rails.root.join("spec/fixtures/images/An image of Discourse logo.jpg")
|
|
FileUtils.cp(original_file_path, temp_file_path)
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([temp_file_path]) { composer.click_toolbar_button("upload") }
|
|
wait_for { composer.has_no_in_progress_uploads? }
|
|
composer.fill_title("I love using Discourse! It is my favorite forum software")
|
|
composer.create
|
|
expect(dialog).to be_closed
|
|
end
|
|
|
|
it "should auto caption the existing images and update the preference when dialog is accepted" do
|
|
DiscourseAi::Completions::Llm.with_prepared_responses([caption]) do
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([file_path]) { composer.click_toolbar_button("upload") }
|
|
wait_for { composer.has_no_in_progress_uploads? }
|
|
composer.fill_title("I love using Discourse! It is my favorite forum software")
|
|
composer.create
|
|
dialog.click_yes
|
|
wait_for(timeout: 100) { page.find("#post_1 .cooked img")["alt"] == caption_with_attrs }
|
|
expect(page.find("#post_1 .cooked img")["alt"]).to eq(caption_with_attrs)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the user preference is enabled" do
|
|
before { user.user_option.update!(auto_image_caption: true) }
|
|
|
|
skip "TODO: Fix auto_image_caption user option not present in testing environment?" do
|
|
it "should auto caption the image after uploading" do
|
|
DiscourseAi::Completions::Llm.with_prepared_responses([caption]) do
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
attach_file([Rails.root.join("spec/fixtures/images/logo.jpg")]) do
|
|
composer.click_toolbar_button("upload")
|
|
end
|
|
wait_for { composer.has_no_in_progress_uploads? }
|
|
wait_for { page.find(".image-wrapper img")["alt"] == caption_with_attrs }
|
|
expect(page.find(".image-wrapper img")["alt"]).to eq(caption_with_attrs)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when a post has no uploads" do
|
|
before { user.user_option.update!(auto_image_caption: true) }
|
|
|
|
it "should create the topic without triggering auto caption" do
|
|
title = "I love using Discourse! It is my favorite forum software"
|
|
visit("/latest")
|
|
page.find("#create-topic").click
|
|
composer.fill_title(title)
|
|
composer.fill_content(
|
|
"Culpa labore velit cupidatat commodo magna esse et minim consequat veniam dolore eiusmod. Labore eu elit in nulla ipsum elit consectetur sunt consectetur enim. Cillum ex ex velit eiusmod labore ullamco ut ad. Dolore dolor commodo nisi fugiat esse quis anim officia quis. Pariatur cillum pariatur irure cupidatat nostrud ullamco labore id aliqua ut nostrud. Eu adipisicing ut laboris.",
|
|
)
|
|
composer.create
|
|
expect(dialog).to be_closed
|
|
expect(topic_page).to have_topic_title(title)
|
|
end
|
|
|
|
it "should create a reply to a post without triggering auto caption" do
|
|
visit("/t/-/#{topic.id}")
|
|
topic_page.click_footer_reply
|
|
composer.fill_content(
|
|
"Culpa labore velit cupidatat commodo magna esse et minim consequat veniam dolore eiusmod. Labore eu elit in nulla ipsum elit consectetur sunt consectetur enim. Cillum ex ex velit eiusmod labore ullamco ut ad. Dolore dolor commodo nisi fugiat esse quis anim officia quis. Pariatur cillum pariatur irure cupidatat nostrud ullamco labore id aliqua ut nostrud. Eu adipisicing ut laboris.",
|
|
)
|
|
composer.create
|
|
expect(dialog).to be_closed
|
|
expect(topic_page).to have_post_number(post.post_number)
|
|
end
|
|
end
|
|
end
|
|
end
|