# frozen_string_literal: true RSpec.describe DiscourseAi::Utils::DiffUtils do describe ".apply_hunk" do subject(:apply_hunk) { described_class.apply_hunk(original_text, diff) } context "with HTML content" do let(:original_text) { <<~HTML }
Some content here
Some content here
DIFF it "inserts the new content" do expected = <<~HTMLSome content here
Some content here
Some content here
DIFF it "replaces the content correctly" do expected = <<~HTMLSome content here
DIFF it "raises an AmbiguousMatchError" do expect { apply_hunk }.to raise_error( DiscourseAi::Utils::DiffUtils::AmbiguousMatchError, ) do |error| expect(error.to_llm_message).to include("Found multiple possible locations") end end end context "with no matching context" do let(:diff) { <<~DIFF }
DIFF it "raises a NoMatchingContextError" do expect { apply_hunk }.to raise_error( DiscourseAi::Utils::DiffUtils::NoMatchingContextError, ) do |error| expect(error.to_llm_message).to include("Could not find the context lines") end end end context "with malformed diffs" do context "when empty" do let(:diff) { "" } it "raises a MalformedDiffError" do expect { apply_hunk }.to raise_error( DiscourseAi::Utils::DiffUtils::MalformedDiffError, ) do |error| expect(error.context["Issue"]).to eq("Diff is empty") end end end end end context "without markers" do let(:original_text) { "hello" } let(:diff) { "world" } it "will append to the end" do expect(apply_hunk).to eq("hello\nworld") end end context "when appending text to the end of a document" do let(:original_text) { "hello\nworld" } let(:diff) { <<~DIFF } world +123 DIFF it "can append to end" do expect(apply_hunk).to eq("hello\nworld\n123") end end context "when applying multiple hunks to a file" do let(:original_text) { <<~TEXT } 1 2 3 4 5 6 7 8 TEXT let(:diff) { <<~DIFF } @@ -1,4 +1,4 @@ 2 - 3 @@ -6,4 +6,4 @@ - 7 DIFF it "can apply multiple hunks" do expected = <<~TEXT 1 2 4 5 6 8 TEXT expect(apply_hunk).to eq(expected.strip) end end context "with line ending variations" do let(:original_text) { "line1\r\nline2\nline3\r\n" } let(:diff) { <<~DIFF } line1 +new line line2 DIFF it "handles mixed line endings" do expect(apply_hunk).to include("new line") expect(apply_hunk.lines.count).to eq(4) end end context "with whitespace sensitivity" do let(:original_text) { <<~TEXT } def method puts "hello" end TEXT context "when indentation matters" do let(:diff) { <<~DIFF } def method - puts "hello" + puts "world" end DIFF it "preserves exact indentation" do result = apply_hunk expect(result).to match(/^ puts "world"$/) end end context "when trailing whitespace exists" do let(:original_text) { "line1 \nline2\n" } let(:diff) { <<~DIFF } line1 +new line line2 DIFF it "preserves significant whitespace" do expect(apply_hunk).to include("line1 \n") end end end end end