Skip to content

Instantly share code, notes, and snippets.

@dorianmariecom
Created March 12, 2022 10:16
Show Gist options
  • Save dorianmariecom/d92fdd27eb9a8e120c327eb560d68947 to your computer and use it in GitHub Desktop.
Save dorianmariecom/d92fdd27eb9a8e120c327eb560d68947 to your computer and use it in GitHub Desktop.
require 'spec_helper'
require 'json'
require 'active_support/all'
require_relative '../../app/models/search_parser'
RSpec.describe SearchParser do
let!(:string) { '' }
subject do
described_class.new.parse(string)
rescue Parslet::ParseFailed => e
puts e.parse_failure_cause.ascii_tree
raise e
end
it { expect(subject).to eq(value: "") }
context 'strings' do
context 'with a plain text search' do
let!(:string) { 'ruby' }
it { expect(subject).to eq(value: 'ruby') }
end
context 'with a plain text search with multiple terms' do
let!(:string) { 'ruby rails' }
it { expect(subject).to eq(and: { left: { value: 'ruby' }, right: { value: 'rails' } }) }
end
context 'with a quoted string' do
let(:string) { '"ruby on rails"' }
it { expect(subject).to eq(value: '"ruby on rails"') }
end
context 'with a quote inside an unquoted string' do
let(:string) { '\"hello\"' }
it { expect(subject).to eq({ value: '\"hello\"' }) }
end
context 'with a quote inside an quoted string' do
let(:string) { '"hello \"world\""' }
it { expect(subject).to eq(value: '"hello \"world\""') }
end
context 'with an escaped space' do
let(:string) { 'hello\ world' }
it { expect(subject).to eq(value: 'hello\ world') }
end
end
context 'rules' do
context 'with a simple rule' do
let!(:string) { 'user:pg' }
it do
expect(subject).to eq(
rule: { key: 'user', operator: ':', value: 'pg' }
)
end
end
context "with all kinds of operators" do
let!(:string) { "created_at>2023 content~=ruby user=dorianmariefr" }
it do
expect(subject).to eq(
and: {
left: {
rule: {
key: "created_at", operator: ">", value:"2023"
}
},
right: {
and: {
left: { rule: { key: "content", operator: "~=", value: "ruby" } },
right: { rule: { key: "user", operator: "=", value: "dorianmariefr" } }
}
}
}
)
end
end
context "with key separators" do
let!(:string) { "item.extras.user=dorianmariefr" }
it do
expect(subject).to eq(
rule: { key: 'item.extras.user', operator: '=', value: 'dorianmariefr' },
)
end
end
end
context "operators" do
context "with an OR query" do
let!(:string) { "ruby OR rails" }
it do
expect(subject).to eq(
or: { left: { value: "ruby" }, right: { value: "rails" } },
)
end
end
context "with an AND query" do
let!(:string) { "ruby AND rails" }
it do
expect(subject).to eq(
and: { left: { value: "ruby" }, right: { value: "rails" } },
)
end
end
context "with a NOT query" do
let!(:string) { "NOT node" }
it do
expect(subject).to eq(
not: { value: "node" },
)
end
end
end
describe "groups" do
context "with two groups with operators" do
let!(:string) { "(ruby or Ruby) and (rails or Rails)" }
it do
expect(subject).to eq(
and: {
left: {
or: {
left: {
value: "ruby"
},
right: {
value: "Ruby"
}
}
},
right: {
or: {
left: {
value: "rails"
},
right: {
value: "Rails"
}
}
},
}
)
end
end
context "optional and" do
let!(:string) { "(ruby or Ruby) (rails or Rails)" }
it do
expect(subject).to eq(
and: {
left: {
or: {
left: {
value: "ruby"
},
right: {
value: "Ruby"
}
}
},
right: {
or: {
left: {
value: "rails"
},
right: {
value: "Rails"
}
}
},
}
)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment