diff options
Diffstat (limited to 'spec/lib/gitlab/database/similarity_score_spec.rb')
-rw-r--r-- | spec/lib/gitlab/database/similarity_score_spec.rb | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/spec/lib/gitlab/database/similarity_score_spec.rb b/spec/lib/gitlab/database/similarity_score_spec.rb new file mode 100644 index 00000000000..e36a4f610e1 --- /dev/null +++ b/spec/lib/gitlab/database/similarity_score_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::SimilarityScore do + let(:search) { '' } + let(:query_result) { ActiveRecord::Base.connection.execute(query).to_a } + + let(:query) do + # In memory query, with the id as the tie breaker. + <<-SQL + SELECT *, #{order_expression} AS similarity + FROM ( + VALUES (1, 'Git', 'git', 'git source code mirror. this is a publish-only repository.'), + (2, 'GitLab Runner', 'gitlab-runner', 'official helm chart for the gitlab runner'), + (3, 'gitaly', 'gitaly', 'gitaly is a git rpc service for handling all the git calls made by gitlab'), + (4, 'GitLab', 'gitlab', 'gitlab is an open source end-to-end software development platform with built-in version control'), + (5, 'Gitlab Danger', 'gitlab-danger', 'this gem provides common dangerfile and plugins for gitlab projects'), + (6, 'different', 'same', 'same'), + (7, 'same', 'different', 'same'), + (8, 'gitlab-styles', 'gitlab-styles', 'gitlab style guides and shared style configs.'), + (9, '🔒 gitaly', 'gitaly-sec', 'security mirror for gitaly') + ) tbl (id, name, path, descrption) ORDER BY #{order_expression} DESC, id DESC; + SQL + end + + let(:order_expression) do + Gitlab::Database::SimilarityScore.build_expression(search: search, rules: [{ column: Arel.sql('path') }]).to_sql + end + + subject { query_result.take(3).map { |row| row['path'] } } + + context 'when passing empty values' do + context 'when search is nil' do + let(:search) { nil } + + it 'orders by a constant 0 value' do + expect(query).to include('ORDER BY CAST(0 AS integer) DESC') + end + end + + context 'when rules are empty' do + let(:search) { 'text' } + + let(:order_expression) do + Gitlab::Database::SimilarityScore.build_expression(search: search, rules: []).to_sql + end + + it 'orders by a constant 0 value' do + expect(query).to include('ORDER BY CAST(0 AS integer) DESC') + end + end + end + + context 'when similarity scoring based on the path' do + let(:search) { 'git' } + + context 'when searching for `git`' do + let(:search) { 'git' } + + it { expect(subject).to eq(%w[git gitlab gitaly]) } + end + + context 'when searching for `gitlab`' do + let(:search) { 'gitlab' } + + it { expect(subject).to eq(%w[gitlab gitlab-styles gitlab-danger]) } + end + + context 'when searching for something unrelated' do + let(:search) { 'xyz' } + + it 'results have 0 similarity score' do + expect(query_result.map { |row| row['similarity'] }).to all(eq(0)) + end + end + end + + describe 'score multiplier' do + let(:order_expression) do + Gitlab::Database::SimilarityScore.build_expression(search: search, rules: [ + { column: Arel.sql('path'), multiplier: 1 }, + { column: Arel.sql('name'), multiplier: 0.8 } + ]).to_sql + end + + let(:search) { 'different' } + + it 'ranks `path` matches higher' do + expect(subject).to eq(%w[different same gitlab-danger]) + end + end +end |