204 lines
4.8 KiB
Ruby
204 lines
4.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe DiscourseAi::Utils::DiffUtils::SimpleDiff do
|
|
subject { described_class }
|
|
|
|
describe ".apply" do
|
|
it "raises error for nil inputs" do
|
|
expect { subject.apply(nil, "search", "replace") }.to raise_error(ArgumentError)
|
|
expect { subject.apply("content", nil, "replace") }.to raise_error(ArgumentError)
|
|
expect { subject.apply("content", "search", nil) }.to raise_error(ArgumentError)
|
|
end
|
|
|
|
it "prioritizes exact matches over all fuzzy matches" do
|
|
content = <<~TEXT
|
|
line 1
|
|
line 1
|
|
lin 1
|
|
TEXT
|
|
|
|
search = " line 1"
|
|
replace = " new_line"
|
|
expected = <<~TEXT
|
|
line 1
|
|
new_line
|
|
lin 1
|
|
TEXT
|
|
|
|
expect(subject.apply(content, search, replace).strip).to eq(expected.strip)
|
|
end
|
|
|
|
it "raises error when no match is found" do
|
|
content = "line1\ncompletely_different\nline3"
|
|
search = "nothing_like_this"
|
|
replace = "new_line"
|
|
expect { subject.apply(content, search, replace) }.to raise_error(
|
|
DiscourseAi::Utils::DiffUtils::SimpleDiff::NoMatchError,
|
|
)
|
|
end
|
|
|
|
it "replaces all matching occurrences" do
|
|
content = "line1\nline2\nmiddle\nline2\nend"
|
|
search = "line2"
|
|
replace = "new_line2"
|
|
expect(subject.apply(content, search, replace)).to eq(
|
|
"line1\nnew_line2\nmiddle\nnew_line2\nend",
|
|
)
|
|
end
|
|
|
|
it "replaces exact matches" do
|
|
content = "line1\nline2\nline3"
|
|
search = "line2"
|
|
replace = "new_line2"
|
|
expect(subject.apply(content, search, replace)).to eq("line1\nnew_line2\nline3")
|
|
end
|
|
|
|
it "handles multi-line replacements" do
|
|
content = "start\nline1\nline2\nend"
|
|
search = "line1\nline2"
|
|
replace = "new_line"
|
|
expect(subject.apply(content, search, replace)).to eq("start\nnew_line\nend")
|
|
end
|
|
|
|
it "is forgiving of whitespace differences" do
|
|
content = "line1\n line2\nline3"
|
|
search = "line2"
|
|
replace = "new_line2"
|
|
expect(subject.apply(content, search, replace).strip).to eq("line1\n new_line2\nline3")
|
|
end
|
|
|
|
it "is forgiving of small character differences" do
|
|
content = "line one one one\nlin2\nline three three" # Notice 'lin2' instead of 'line2'
|
|
search = "line2"
|
|
replace = "new_line2"
|
|
expect(subject.apply(content, search, replace)).to eq(
|
|
"line one one one\nnew_line2\nline three three",
|
|
)
|
|
end
|
|
|
|
it "is forgiving in multi-line blocks with indentation differences" do
|
|
content = "def method\n line1\n line2\nend"
|
|
search = "line1\nline2"
|
|
replace = "new_content"
|
|
expect(subject.apply(content, search, replace)).to eq("def method\nnew_content\nend")
|
|
end
|
|
|
|
it "handles CSS blocks in different orders" do
|
|
content = <<~CSS
|
|
.first {
|
|
color: red;
|
|
padding: 10px;
|
|
}
|
|
.second {
|
|
color: blue;
|
|
margin: 20px;
|
|
}
|
|
CSS
|
|
|
|
search = <<~CSS
|
|
.second {
|
|
color: blue;
|
|
margin: 20px;
|
|
}
|
|
.first {
|
|
color: red;
|
|
padding: 10px;
|
|
}
|
|
CSS
|
|
|
|
replace = <<~CSS
|
|
.new-block {
|
|
color: green;
|
|
}
|
|
CSS
|
|
|
|
expected = <<~CSS
|
|
.new-block {
|
|
color: green;
|
|
}
|
|
CSS
|
|
|
|
expect(subject.apply(content, search, replace)).to eq(expected.strip)
|
|
end
|
|
|
|
it "handles partial line matches" do
|
|
content = "abc hello efg\nabc hello efg"
|
|
search = "hello"
|
|
replace = "bob"
|
|
expect(subject.apply(content, search, replace)).to eq("abc bob efg\nabc bob efg")
|
|
end
|
|
|
|
it "handles JavaScript blocks in different orders" do
|
|
content = <<~JS
|
|
function first() {
|
|
const x = 1;
|
|
return x + 2;
|
|
}
|
|
|
|
function second() {
|
|
if (true) {
|
|
return 42;
|
|
}
|
|
return 0;
|
|
}
|
|
JS
|
|
|
|
search = <<~JS
|
|
function second() {
|
|
if (true) {
|
|
return 42;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function first() {
|
|
const x = 1;
|
|
return x + 2;
|
|
}
|
|
JS
|
|
|
|
replace = <<~JS
|
|
function replacement() {
|
|
return 'new';
|
|
}
|
|
JS
|
|
|
|
expected = <<~JS
|
|
function replacement() {
|
|
return 'new';
|
|
}
|
|
JS
|
|
|
|
expect(subject.apply(content, search, replace).strip).to eq(expected.strip)
|
|
end
|
|
|
|
it "handles missing lines in search" do
|
|
original = <<~TEXT
|
|
line1
|
|
line2
|
|
line3
|
|
line4
|
|
line5
|
|
line1
|
|
line2
|
|
TEXT
|
|
|
|
search = <<~TEXT
|
|
line1
|
|
...
|
|
line3
|
|
...
|
|
line1
|
|
TEXT
|
|
|
|
replace = ""
|
|
|
|
expected = <<~TEXT
|
|
line2
|
|
TEXT
|
|
|
|
expect(subject.apply(original, search, replace).strip).to eq(expected.strip)
|
|
end
|
|
end
|
|
end
|