issues_finder_spec.rb 24.7 KB
Newer Older
D
Dmitriy Zaporozhets 已提交
1 2
require 'spec_helper'

3
describe IssuesFinder do
4
  include_context 'IssuesFinder context'
D
Dmitriy Zaporozhets 已提交
5

S
Sean McGivern 已提交
6
  describe '#execute' do
7
    include_context 'IssuesFinder#execute context'
8

D
Dmitriy Zaporozhets 已提交
9
    context 'scope: all' do
S
Sean McGivern 已提交
10
      let(:scope) { 'all' }
D
Dmitriy Zaporozhets 已提交
11

S
Sean McGivern 已提交
12
      it 'returns all issues' do
13
        expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
D
Dmitriy Zaporozhets 已提交
14
      end
D
Dmitriy Zaporozhets 已提交
15

16 17
      context 'assignee filtering' do
        let(:issuables) { issues }
S
Sean McGivern 已提交
18

19 20 21
        it_behaves_like 'assignee ID filter' do
          let(:params) { { assignee_id: user.id } }
          let(:expected_issuables) { [issue1, issue2] }
S
Sean McGivern 已提交
22
        end
23

24 25 26 27 28
        it_behaves_like 'assignee username filter' do
          before do
            project2.add_developer(user3)
            issue3.assignees = [user2, user3]
          end
29

30 31 32
          set(:user3) { create(:user) }
          let(:params) { { assignee_username: [user2.username, user3.username] } }
          let(:expected_issuables) { [issue3] }
33 34
        end

35 36 37
        it_behaves_like 'no assignee filter' do
          set(:user3) { create(:user) }
          let(:expected_issuables) { [issue4] }
H
Heinrich Lee Yu 已提交
38
        end
39

40 41
        it_behaves_like 'any assignee filter' do
          let(:expected_issuables) { [issue1, issue2, issue3] }
H
Heinrich Lee Yu 已提交
42
        end
43 44
      end

45 46 47 48 49 50 51 52 53
      context 'filtering by group_id' do
        let(:params) { { group_id: group.id } }

        context 'when include_subgroup param not set' do
          it 'returns all group issues' do
            expect(issues).to contain_exactly(issue1)
          end
        end

54
        context 'when include_subgroup param is true' do
55 56 57 58 59 60 61 62 63 64
          before do
            params[:include_subgroups] = true
          end

          it 'returns all group and subgroup issues' do
            expect(issues).to contain_exactly(issue1, issue4)
          end
        end
      end

S
Sean McGivern 已提交
65 66 67 68 69 70
      context 'filtering by author ID' do
        let(:params) { { author_id: user2.id } }

        it 'returns issues created by that user' do
          expect(issues).to contain_exactly(issue3)
        end
D
Dmitriy Zaporozhets 已提交
71 72
      end

S
Sean McGivern 已提交
73 74 75 76 77 78
      context 'filtering by milestone' do
        let(:params) { { milestone_title: milestone.title } }

        it 'returns issues assigned to that milestone' do
          expect(issues).to contain_exactly(issue1)
        end
79 80
      end

F
Felipe Artur 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
      context 'filtering by group milestone' do
        let!(:group) { create(:group, :public) }
        let(:group_milestone) { create(:milestone, group: group) }
        let!(:group_member) { create(:group_member, group: group, user: user) }
        let(:params) { { milestone_title: group_milestone.title } }

        before do
          project2.update(namespace: group)
          issue2.update(milestone: group_milestone)
          issue3.update(milestone: group_milestone)
        end

        it 'returns issues assigned to that group milestone' do
          expect(issues).to contain_exactly(issue2, issue3)
        end
      end

S
Sean McGivern 已提交
98
      context 'filtering by no milestone' do
99
        let(:params) { { milestone_title: 'None' } }
S
Sean McGivern 已提交
100 101

        it 'returns issues with no milestone' do
102
          expect(issues).to contain_exactly(issue2, issue3, issue4)
S
Sean McGivern 已提交
103
        end
104 105 106 107 108 109

        it 'returns issues with no milestone (deprecated)' do
          params[:milestone_title] = Milestone::None.title

          expect(issues).to contain_exactly(issue2, issue3, issue4)
        end
110 111
      end

112
      context 'filtering by any milestone' do
113
        let(:params) { { milestone_title: 'Any' } }
114 115 116 117

        it 'returns issues with any assigned milestone' do
          expect(issues).to contain_exactly(issue1)
        end
118 119 120 121 122 123

        it 'returns issues with any assigned milestone (deprecated)' do
          params[:milestone_title] = Milestone::Any.title

          expect(issues).to contain_exactly(issue1)
        end
124 125
      end

126 127 128
      context 'filtering by upcoming milestone' do
        let(:params) { { milestone_title: Milestone::Upcoming.name } }

129 130 131
        let!(:group) { create(:group, :public) }
        let!(:group_member) { create(:group_member, group: group, user: user) }

132 133 134
        let(:project_no_upcoming_milestones) { create(:project, :public) }
        let(:project_next_1_1) { create(:project, :public) }
        let(:project_next_8_8) { create(:project, :public) }
135
        let(:project_in_group) { create(:project, :public, namespace: group) }
136 137 138 139 140 141 142 143 144 145

        let(:yesterday) { Date.today - 1.day }
        let(:tomorrow) { Date.today + 1.day }
        let(:two_days_from_now) { Date.today + 2.days }
        let(:ten_days_from_now) { Date.today + 10.days }

        let(:milestones) do
          [
            create(:milestone, :closed, project: project_no_upcoming_milestones),
            create(:milestone, project: project_next_1_1, title: '1.1', due_date: two_days_from_now),
146 147 148 149
            create(:milestone, project: project_next_1_1, title: '8.9', due_date: ten_days_from_now),
            create(:milestone, project: project_next_8_8, title: '1.2', due_date: yesterday),
            create(:milestone, project: project_next_8_8, title: '8.8', due_date: tomorrow),
            create(:milestone, group: group, title: '9.9', due_date: tomorrow)
150 151 152 153 154
          ]
        end

        before do
          milestones.each do |milestone|
155
            create(:issue, project: milestone.project || project_in_group, milestone: milestone, author: user, assignees: [user])
156 157 158
          end
        end

159 160 161
        it 'returns issues in the upcoming milestone for each project or group' do
          expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.1', '8.8', '9.9')
          expect(issues.map { |issue| issue.milestone.due_date }).to contain_exactly(tomorrow, two_days_from_now, tomorrow)
162 163 164
        end
      end

165 166 167
      context 'filtering by started milestone' do
        let(:params) { { milestone_title: Milestone::Started.name } }

168 169 170
        let(:project_no_started_milestones) { create(:project, :public) }
        let(:project_started_1_and_2) { create(:project, :public) }
        let(:project_started_8) { create(:project, :public) }
171 172 173 174

        let(:yesterday) { Date.today - 1.day }
        let(:tomorrow) { Date.today + 1.day }
        let(:two_days_ago) { Date.today - 2.days }
175
        let(:three_days_ago) { Date.today - 3.days }
176 177 178 179 180 181 182

        let(:milestones) do
          [
            create(:milestone, project: project_no_started_milestones, start_date: tomorrow),
            create(:milestone, project: project_started_1_and_2, title: '1.0', start_date: two_days_ago),
            create(:milestone, project: project_started_1_and_2, title: '2.0', start_date: yesterday),
            create(:milestone, project: project_started_1_and_2, title: '3.0', start_date: tomorrow),
183 184
            create(:milestone, :closed, project: project_started_1_and_2, title: '4.0', start_date: three_days_ago),
            create(:milestone, :closed, project: project_started_8, title: '6.0', start_date: three_days_ago),
185 186 187 188 189 190 191 192
            create(:milestone, project: project_started_8, title: '7.0'),
            create(:milestone, project: project_started_8, title: '8.0', start_date: yesterday),
            create(:milestone, project: project_started_8, title: '9.0', start_date: tomorrow)
          ]
        end

        before do
          milestones.each do |milestone|
193
            create(:issue, project: milestone.project, milestone: milestone, author: user, assignees: [user])
194 195 196 197 198 199 200 201 202
          end
        end

        it 'returns issues in the started milestones for each project' do
          expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.0', '2.0', '8.0')
          expect(issues.map { |issue| issue.milestone.start_date }).to contain_exactly(two_days_ago, yesterday, yesterday)
        end
      end

S
Sean McGivern 已提交
203 204
      context 'filtering by label' do
        let(:params) { { label_name: label.title } }
205

S
Sean McGivern 已提交
206 207 208 209
        it 'returns issues with that label' do
          expect(issues).to contain_exactly(issue2)
        end
      end
210

S
Sean McGivern 已提交
211 212 213
      context 'filtering by multiple labels' do
        let(:params) { { label_name: [label.title, label2.title].join(',') } }
        let(:label2) { create(:label, project: project2) }
214

215 216 217
        before do
          create(:label_link, label: label2, target: issue2)
        end
218

219 220 221 222 223 224 225 226 227 228 229 230 231
        it 'returns the unique issues with all those labels' do
          expect(issues).to contain_exactly(issue2)
        end
      end

      context 'filtering by a label that includes any or none in the title' do
        let(:params) { { label_name: [label.title, label2.title].join(',') } }
        let(:label) { create(:label, title: 'any foo', project: project2) }
        let(:label2) { create(:label, title: 'bar none', project: project2) }

        it 'returns the unique issues with all those labels' do
          create(:label_link, label: label2, target: issue2)

S
Sean McGivern 已提交
232 233
          expect(issues).to contain_exactly(issue2)
        end
234 235
      end

S
Sean McGivern 已提交
236
      context 'filtering by no label' do
237
        let(:params) { { label_name: described_class::FILTER_NONE } }
S
Sean McGivern 已提交
238 239

        it 'returns issues with no labels' do
240
          expect(issues).to contain_exactly(issue1, issue3, issue4)
S
Sean McGivern 已提交
241
        end
242 243
      end

244 245 246 247 248 249 250 251 252 253 254 255
      context 'filtering by any label' do
        let(:params) { { label_name: described_class::FILTER_ANY } }

        it 'returns issues that have one or more label' do
          2.times do
            create(:label_link, label: create(:label, project: project2), target: issue3)
          end

          expect(issues).to contain_exactly(issue2, issue3)
        end
      end

B
barthc 已提交
256 257 258 259 260 261 262 263
      context 'filtering by issue term' do
        let(:params) { { search: 'git' } }

        it 'returns issues with title and description match for search term' do
          expect(issues).to contain_exactly(issue1, issue2)
        end
      end

264 265 266 267 268 269 270 271
      context 'filtering by issue term in title' do
        let(:params) { { search: 'git', in: 'title' } }

        it 'returns issues with title match for search term' do
          expect(issues).to contain_exactly(issue1)
        end
      end

M
mhasbini 已提交
272 273
      context 'filtering by issues iids' do
        let(:params) { { iids: issue3.iid } }
B
barthc 已提交
274

M
mhasbini 已提交
275
        it 'returns issues with iids match' do
B
barthc 已提交
276 277 278 279
          expect(issues).to contain_exactly(issue3)
        end
      end

280 281 282 283 284
      context 'filtering by state' do
        context 'with opened' do
          let(:params) { { state: 'opened' } }

          it 'returns only opened issues' do
285
            expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
          end
        end

        context 'with closed' do
          let(:params) { { state: 'closed' } }

          it 'returns only closed issues' do
            expect(issues).to contain_exactly(closed_issue)
          end
        end

        context 'with all' do
          let(:params) { { state: 'all' } }

          it 'returns all issues' do
301
            expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4)
302 303 304 305 306 307 308
          end
        end

        context 'with invalid state' do
          let(:params) { { state: 'invalid_state' } }

          it 'returns all issues' do
309
            expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4)
310 311 312 313
          end
        end
      end

314 315 316 317 318 319 320 321 322 323
      context 'filtering by created_at' do
        context 'through created_after' do
          let(:params) { { created_after: issue3.created_at } }

          it 'returns issues created on or after the given date' do
            expect(issues).to contain_exactly(issue3)
          end
        end

        context 'through created_before' do
324
          let(:params) { { created_before: issue1.created_at } }
325 326 327 328 329

          it 'returns issues created on or before the given date' do
            expect(issues).to contain_exactly(issue1)
          end
        end
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

        context 'through created_after and created_before' do
          let(:params) { { created_after: issue2.created_at, created_before: issue3.created_at } }

          it 'returns issues created between the given dates' do
            expect(issues).to contain_exactly(issue2, issue3)
          end
        end
      end

      context 'filtering by updated_at' do
        context 'through updated_after' do
          let(:params) { { updated_after: issue3.updated_at } }

          it 'returns issues updated on or after the given date' do
            expect(issues).to contain_exactly(issue3)
          end
        end

        context 'through updated_before' do
          let(:params) { { updated_before: issue1.updated_at } }

          it 'returns issues updated on or before the given date' do
            expect(issues).to contain_exactly(issue1)
          end
        end

        context 'through updated_after and updated_before' do
          let(:params) { { updated_after: issue2.updated_at, updated_before: issue3.updated_at } }

          it 'returns issues updated between the given dates' do
            expect(issues).to contain_exactly(issue2, issue3)
          end
        end
364 365
      end

366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
      context 'filtering by closed_at' do
        let!(:closed_issue1) { create(:issue, project: project1, state: :closed, closed_at: 1.week.ago) }
        let!(:closed_issue2) { create(:issue, project: project2, state: :closed, closed_at: 1.week.from_now) }
        let!(:closed_issue3) { create(:issue, project: project2, state: :closed, closed_at: 2.weeks.from_now) }

        context 'through closed_after' do
          let(:params) { { state: :closed, closed_after: closed_issue3.closed_at } }

          it 'returns issues closed on or after the given date' do
            expect(issues).to contain_exactly(closed_issue3)
          end
        end

        context 'through closed_before' do
          let(:params) { { state: :closed, closed_before: closed_issue1.closed_at } }

          it 'returns issues closed on or before the given date' do
            expect(issues).to contain_exactly(closed_issue1)
          end
        end

        context 'through closed_after and closed_before' do
          let(:params) { { state: :closed, closed_after: closed_issue2.closed_at, closed_before: closed_issue3.closed_at } }

          it 'returns issues closed between the given dates' do
            expect(issues).to contain_exactly(closed_issue2, closed_issue3)
          end
        end
      end

H
Hiroyuki Sato 已提交
396
      context 'filtering by reaction name' do
H
Heinrich Lee Yu 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
        context 'user searches by no reaction' do
          let(:params) { { my_reaction_emoji: 'None' } }

          it 'returns issues that the user did not react to' do
            expect(issues).to contain_exactly(issue2, issue4)
          end
        end

        context 'user searches by any reaction' do
          let(:params) { { my_reaction_emoji: 'Any' } }

          it 'returns issues that the user reacted to' do
            expect(issues).to contain_exactly(issue1, issue3)
          end
        end

H
Hiroyuki Sato 已提交
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
        context 'user searches by "thumbsup" reaction' do
          let(:params) { { my_reaction_emoji: 'thumbsup' } }

          it 'returns issues that the user thumbsup to' do
            expect(issues).to contain_exactly(issue1)
          end
        end

        context 'user2 searches by "thumbsup" reaction' do
          let(:search_user) { user2 }

          let(:params) { { my_reaction_emoji: 'thumbsup' } }

          it 'returns issues that the user2 thumbsup to' do
            expect(issues).to contain_exactly(issue2)
          end
        end

        context 'user searches by "thumbsdown" reaction' do
          let(:params) { { my_reaction_emoji: 'thumbsdown' } }

          it 'returns issues that the user thumbsdown to' do
            expect(issues).to contain_exactly(issue3)
          end
        end
      end

440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
      context 'filtering by confidential' do
        set(:confidential_issue) { create(:issue, project: project1, confidential: true) }

        context 'no filtering' do
          it 'returns all issues' do
            expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, confidential_issue)
          end
        end

        context 'user filters confidential issues' do
          let(:params) { { confidential: true } }

          it 'returns only confdential issues' do
            expect(issues).to contain_exactly(confidential_issue)
          end
        end

        context 'user filters only public issues' do
          let(:params) { { confidential: false } }

          it 'returns only confdential issues' do
            expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
          end
        end
      end

S
Sean McGivern 已提交
466 467 468 469 470 471
      context 'when the user is unauthorized' do
        let(:search_user) { nil }

        it 'returns no results' do
          expect(issues).to be_empty
        end
D
Dmitriy Zaporozhets 已提交
472 473
      end

S
Sean McGivern 已提交
474 475 476 477 478 479
      context 'when the user can see some, but not all, issues' do
        let(:search_user) { user2 }

        it 'returns only issues they can see' do
          expect(issues).to contain_exactly(issue2, issue3)
        end
D
Dmitriy Zaporozhets 已提交
480
      end
481 482 483

      it 'finds issues user can access due to group' do
        group = create(:group)
484
        project = create(:project, group: group)
485 486 487 488 489
        issue = create(:issue, project: project)
        group.add_user(user, :owner)

        expect(issues).to include(issue)
      end
490 491
    end

D
Dmitriy Zaporozhets 已提交
492
    context 'personal scope' do
493
      let(:scope) { 'assigned_to_me' }
S
Sean McGivern 已提交
494 495 496

      it 'returns issue assigned to the user' do
        expect(issues).to contain_exactly(issue1, issue2)
D
Dmitriy Zaporozhets 已提交
497 498
      end

S
Sean McGivern 已提交
499 500 501 502 503 504
      context 'filtering by project' do
        let(:params) { { project_id: project1.id } }

        it 'returns issues assigned to the user in that project' do
          expect(issues).to contain_exactly(issue1)
        end
D
Dmitriy Zaporozhets 已提交
505
      end
506
    end
507 508 509 510 511

    context 'when project restricts issues' do
      let(:scope) { nil }

      it "doesn't return team-only issues to non team members" do
512
        project = create(:project, :public, :issues_private)
513 514 515 516 517 518
        issue = create(:issue, project: project)

        expect(issues).not_to include(issue)
      end

      it "doesn't return issues if feature disabled" do
519
        [project1, project2, project3].each do |project|
520 521 522 523 524 525
          project.project_feature.update!(issues_access_level: ProjectFeature::DISABLED)
        end

        expect(issues.count).to eq 0
      end
    end
526 527 528 529 530 531 532

    context 'external authorization' do
      it_behaves_like 'a finder with external authorization service' do
        let!(:subject) { create(:issue, project: project) }
        let(:project_params) { { project_id: project.id } }
      end
    end
533 534
  end

535 536 537 538
  describe '#row_count', :request_store do
    it 'returns the number of rows for the default state' do
      finder = described_class.new(user)

539
      expect(finder.row_count).to eq(5)
540 541 542 543 544 545 546 547 548
    end

    it 'returns the number of rows for a given state' do
      finder = described_class.new(user, state: 'closed')

      expect(finder.row_count).to be_zero
    end
  end

549
  describe '#with_confidentiality_access_check' do
550 551
    let(:guest) { create(:user) }
    set(:authorized_user) { create(:user) }
552
    set(:project) { create(:project, namespace: authorized_user.namespace) }
553 554 555 556 557 558 559
    set(:public_issue) { create(:issue, project: project) }
    set(:confidential_issue) { create(:issue, project: project, confidential: true) }

    context 'when no project filter is given' do
      let(:params) { {} }

      context 'for an anonymous user' do
560
        subject { described_class.new(nil, params).with_confidentiality_access_check }
561 562 563 564 565 566 567 568

        it 'returns only public issues' do
          expect(subject).to include(public_issue)
          expect(subject).not_to include(confidential_issue)
        end
      end

      context 'for a user without project membership' do
569
        subject { described_class.new(user, params).with_confidentiality_access_check }
570 571 572 573 574 575 576 577

        it 'returns only public issues' do
          expect(subject).to include(public_issue)
          expect(subject).not_to include(confidential_issue)
        end
      end

      context 'for a guest user' do
578
        subject { described_class.new(guest, params).with_confidentiality_access_check }
579 580 581 582 583 584 585 586 587 588 589 590

        before do
          project.add_guest(guest)
        end

        it 'returns only public issues' do
          expect(subject).to include(public_issue)
          expect(subject).not_to include(confidential_issue)
        end
      end

      context 'for a project member with access to view confidential issues' do
591
        subject { described_class.new(authorized_user, params).with_confidentiality_access_check }
592

593 594 595 596
        it 'returns all issues' do
          expect(subject).to include(public_issue, confidential_issue)
        end
      end
597 598 599 600 601 602 603 604 605 606

      context 'for an admin' do
        let(:admin_user) { create(:user, :admin) }

        subject { described_class.new(admin_user, params).with_confidentiality_access_check }

        it 'returns all issues' do
          expect(subject).to include(public_issue, confidential_issue)
        end
      end
607 608
    end

609 610 611 612
    context 'when searching within a specific project' do
      let(:params) { { project_id: project.id } }

      context 'for an anonymous user' do
613
        subject { described_class.new(nil, params).with_confidentiality_access_check }
614 615 616 617 618 619 620 621 622 623 624 625 626 627

        it 'returns only public issues' do
          expect(subject).to include(public_issue)
          expect(subject).not_to include(confidential_issue)
        end

        it 'does not filter by confidentiality' do
          expect(Issue).not_to receive(:where).with(a_string_matching('confidential'), anything)

          subject
        end
      end

      context 'for a user without project membership' do
628
        subject { described_class.new(user, params).with_confidentiality_access_check }
629 630 631 632 633 634 635

        it 'returns only public issues' do
          expect(subject).to include(public_issue)
          expect(subject).not_to include(confidential_issue)
        end

        it 'filters by confidentiality' do
636
          expect(subject.to_sql).to match("issues.confidential")
637 638 639 640
        end
      end

      context 'for a guest user' do
641
        subject { described_class.new(guest, params).with_confidentiality_access_check }
642 643 644 645 646 647 648 649 650 651 652

        before do
          project.add_guest(guest)
        end

        it 'returns only public issues' do
          expect(subject).to include(public_issue)
          expect(subject).not_to include(confidential_issue)
        end

        it 'filters by confidentiality' do
653
          expect(subject.to_sql).to match("issues.confidential")
654 655 656 657
        end
      end

      context 'for a project member with access to view confidential issues' do
658
        subject { described_class.new(authorized_user, params).with_confidentiality_access_check }
659 660 661 662 663 664 665 666 667 668 669

        it 'returns all issues' do
          expect(subject).to include(public_issue, confidential_issue)
        end

        it 'does not filter by confidentiality' do
          expect(Issue).not_to receive(:where).with(a_string_matching('confidential'), anything)

          subject
        end
      end
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685

      context 'for an admin' do
        let(:admin_user) { create(:user, :admin) }

        subject { described_class.new(admin_user, params).with_confidentiality_access_check }

        it 'returns all issues' do
          expect(subject).to include(public_issue, confidential_issue)
        end

        it 'does not filter by confidentiality' do
          expect(Issue).not_to receive(:where).with(a_string_matching('confidential'), anything)

          subject
        end
      end
686
    end
D
Dmitriy Zaporozhets 已提交
687
  end
688

689
  describe '#use_cte_for_search?' do
690 691 692
    let(:finder) { described_class.new(nil, params) }

    before do
693
      stub_feature_flags(attempt_group_search_optimizations: true)
694 695 696 697 698 699
    end

    context 'when there is no search param' do
      let(:params) { { attempt_group_search_optimizations: true } }

      it 'returns false' do
700
        expect(finder.use_cte_for_search?).to be_falsey
701 702 703
      end
    end

704
    context 'when the force_cte param is falsey' do
705 706 707
      let(:params) { { search: 'foo' } }

      it 'returns false' do
708
        expect(finder.use_cte_for_search?).to be_falsey
709 710 711
      end
    end

712
    context 'when the attempt_group_search_optimizations flag is disabled' do
713 714 715
      let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }

      before do
716
        stub_feature_flags(attempt_group_search_optimizations: false)
717 718 719
      end

      it 'returns false' do
720
        expect(finder.use_cte_for_search?).to be_falsey
721 722 723
      end
    end

724 725
    context 'when attempt_group_search_optimizations is unset and attempt_project_search_optimizations is set' do
      let(:params) { { search: 'foo', attempt_project_search_optimizations: true } }
726

727 728 729 730
      context 'and the corresponding feature flag is disabled' do
        before do
          stub_feature_flags(attempt_project_search_optimizations: false)
        end
731

732 733 734
        it 'returns false' do
          expect(finder.use_cte_for_search?).to be_falsey
        end
735 736
      end

737 738 739 740
      context 'and the corresponding feature flag is enabled' do
        before do
          stub_feature_flags(attempt_project_search_optimizations: true)
        end
741

742 743 744
        it 'returns true' do
          expect(finder.use_cte_for_search?).to be_truthy
        end
745 746 747 748
      end
    end

    context 'when all conditions are met' do
749
      let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
750 751

      it 'returns true' do
752
        expect(finder.use_cte_for_search?).to be_truthy
753 754 755
      end
    end
  end
D
Dmitriy Zaporozhets 已提交
756
end