BigW Consortium Gitlab

issues_spec.rb 15.7 KB
Newer Older
gitlabhq committed
1 2
require 'spec_helper'

3
describe 'Issues', feature: true do
Dmitriy Zaporozhets committed
4 5
  include SortingHelper

6
  let(:project) { create(:project) }
gitlabhq committed
7

Nihad Abbasov committed
8
  before do
gitlabhq committed
9
    login_as :user
Riyad Preukschas committed
10
    user2 = create(:user)
gitlabhq committed
11

12
    project.team << [[@user, user2], :developer]
gitlabhq committed
13 14
  end

15
  describe 'Edit issue' do
Riyad Preukschas committed
16 17 18 19 20 21 22
    let!(:issue) do
      create(:issue,
             author: @user,
             assignee: @user,
             project: project)
    end

Nihad Abbasov committed
23
    before do
24
      visit edit_namespace_project_issue_path(project.namespace, project, issue)
Phil Hughes committed
25
      click_button "Go full screen"
gitlabhq committed
26 27
    end

28
    it 'should open new issue popup' do
29
      expect(page).to have_content("Issue ##{issue.iid}")
gitlabhq committed
30 31
    end

32
    describe 'fill in' do
gitlabhq committed
33
      before do
34 35
        fill_in 'issue_title', with: 'bug 345'
        fill_in 'issue_description', with: 'bug description'
gitlabhq committed
36 37
      end
    end
38 39
  end

40
  describe 'Editing issue assignee' do
41 42 43 44 45 46 47
    let!(:issue) do
      create(:issue,
             author: @user,
             assignee: @user,
             project: project)
    end

48
    it 'allows user to select unassigned', js: true do
Vinnie Okada committed
49
      visit edit_namespace_project_issue_path(project.namespace, project, issue)
50

51
      expect(page).to have_content "Assignee #{@user.name}"
52

53
      first('#s2id_issue_assignee_id').click
54
      sleep 2 # wait for ajax stuff to complete
55
      first('.user-result').click
56

57
      click_button 'Save changes'
58

59
      page.within('.assignee') do
60
        expect(page).to have_content 'No assignee - assign yourself'
61 62
      end

63
      expect(issue.reload.assignee).to be_nil
64
    end
gitlabhq committed
65
  end
66

Phil Hughes committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
  describe 'due date', js: true do
    context 'on new form' do
      before do
        visit new_namespace_project_issue_path(project.namespace, project)
      end

      it 'should save with due date' do
        date = Date.today.at_beginning_of_month

        fill_in 'issue_title', with: 'bug 345'
        fill_in 'issue_description', with: 'bug description'

        page.within '.datepicker' do
          click_link date.day
        end

Phil Hughes committed
83
        expect(find('#issuable-due-date', visible: false).value).to eq date.to_s
Phil Hughes committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

        click_button 'Submit issue'

        page.within '.issuable-sidebar' do
          expect(page).to have_content date.to_s(:medium)
        end
      end
    end

    context 'on edit form' do
      let(:issue) { create(:issue, author: @user,project: project, due_date: Date.today.at_beginning_of_month.to_s) }

      before do
        visit edit_namespace_project_issue_path(project.namespace, project, issue)
      end

      it 'should save with due date' do
        date = Date.today.at_beginning_of_month

Phil Hughes committed
103
        expect(find('#issuable-due-date', visible: false).value).to eq date.to_s
Phil Hughes committed
104 105 106 107 108 109 110 111 112 113

        date = date.tomorrow

        fill_in 'issue_title', with: 'bug 345'
        fill_in 'issue_description', with: 'bug description'

        page.within '.datepicker' do
          click_link date.day
        end

Phil Hughes committed
114
        expect(find('#issuable-due-date', visible: false).value).to eq date.to_s
Phil Hughes committed
115 116 117 118 119 120 121 122 123 124

        click_button 'Save changes'

        page.within '.issuable-sidebar' do
          expect(page).to have_content date.to_s(:medium)
        end
      end
    end
  end

125 126 127
  describe 'Issue info' do
    it 'excludes award_emoji from comment count' do
      issue = create(:issue, author: @user, assignee: @user, project: project, title: 'foobar')
128
      create(:award_emoji, awardable: issue)
129 130 131 132 133 134 135 136

      visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)

      expect(page).to have_content 'foobar'
      expect(page.all('.issue-no-comments').first.text).to eq "0"
    end
  end

137
  describe 'Filter issue' do
138 139
    before do
      ['foobar', 'barbaz', 'gitlab'].each do |title|
Riyad Preukschas committed
140 141 142 143 144
        create(:issue,
               author: @user,
               assignee: @user,
               project: project,
               title: title)
145 146
      end

Dmitriy Zaporozhets committed
147
      @issue = Issue.find_by(title: 'foobar')
148 149 150
      @issue.milestone = create(:milestone, project: project)
      @issue.assignee = nil
      @issue.save
151 152
    end

153
    let(:issue) { @issue }
Riyad Preukschas committed
154

155
    it 'should allow filtering by issues with no specified assignee' do
156
      visit namespace_project_issues_path(project.namespace, project, assignee_id: IssuableFinder::NONE)
157

158 159 160
      expect(page).to have_content 'foobar'
      expect(page).not_to have_content 'barbaz'
      expect(page).not_to have_content 'gitlab'
161 162
    end

163
    it 'should allow filtering by a specified assignee' do
Vinnie Okada committed
164
      visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)
165

166 167 168
      expect(page).not_to have_content 'foobar'
      expect(page).to have_content 'barbaz'
      expect(page).to have_content 'gitlab'
169
    end
170
  end
171 172

  describe 'filter issue' do
Rémy Coutable committed
173
    titles = %w[foo bar baz]
174
    titles.each_with_index do |title, index|
175 176 177 178 179
      let!(title.to_sym) do
        create(:issue, title: title,
                       project: project,
                       created_at: Time.now - (index * 60))
      end
180
    end
181 182
    let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') }
    let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') }
183 184

    it 'sorts by newest' do
Vinnie Okada committed
185
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_created)
186

187 188
      expect(first_issue).to include('baz')
      expect(last_issue).to include('foo')
189 190 191
    end

    it 'sorts by oldest' do
Vinnie Okada committed
192
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_created)
193

194 195
      expect(first_issue).to include('foo')
      expect(last_issue).to include('baz')
196 197 198 199 200
    end

    it 'sorts by most recently updated' do
      baz.updated_at = Time.now + 100
      baz.save
Vinnie Okada committed
201
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_updated)
202

203
      expect(first_issue).to include('baz')
204 205 206 207 208
    end

    it 'sorts by least recently updated' do
      baz.updated_at = Time.now - 100
      baz.save
Vinnie Okada committed
209
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_updated)
210

211
      expect(first_issue).to include('baz')
212 213
    end

214
    describe 'sorting by due date' do
215
      before do
Rémy Coutable committed
216 217
        foo.update(due_date: 1.day.from_now)
        bar.update(due_date: 6.days.from_now)
218 219 220 221
      end

      it 'sorts by recently due date' do
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_soon)
Rémy Coutable committed
222

223 224 225 226 227
        expect(first_issue).to include('foo')
      end

      it 'sorts by least recently due date' do
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_later)
Rémy Coutable committed
228

229 230 231 232 233
        expect(first_issue).to include('bar')
      end

      it 'sorts by least recently due date by excluding nil due dates' do
        bar.update(due_date: nil)
Rémy Coutable committed
234

235
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_later)
Rémy Coutable committed
236

237 238
        expect(first_issue).to include('foo')
      end
239 240 241 242 243 244 245 246 247 248 249 250 251

      context 'with a filter on labels' do
        let(:label) { create(:label, project: project) }
        before { create(:label_link, label: label, target: foo) }

        it 'sorts by least recently due date by excluding nil due dates' do
          bar.update(due_date: nil)

          visit namespace_project_issues_path(project.namespace, project, label_names: [label.name], sort: sort_value_due_date_later)

          expect(first_issue).to include('foo')
        end
      end
252 253 254
    end

    describe 'filtering by due date' do
Rémy Coutable committed
255 256 257
      before do
        foo.update(due_date: 1.day.from_now)
        bar.update(due_date: 6.days.from_now)
258 259 260
      end

      it 'filters by none' do
261
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::NoDueDate.name)
Rémy Coutable committed
262 263 264 265

        expect(page).not_to have_content('foo')
        expect(page).not_to have_content('bar')
        expect(page).to have_content('baz')
266 267 268
      end

      it 'filters by any' do
269
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::AnyDueDate.name)
Rémy Coutable committed
270 271 272 273

        expect(page).to have_content('foo')
        expect(page).to have_content('bar')
        expect(page).to have_content('baz')
274 275
      end

276 277 278 279
      it 'filters by due this week' do
        foo.update(due_date: Date.today.beginning_of_week + 2.days)
        bar.update(due_date: Date.today.end_of_week)
        baz.update(due_date: Date.today - 8.days)
Rémy Coutable committed
280

281
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::DueThisWeek.name)
Rémy Coutable committed
282 283 284 285

        expect(page).to have_content('foo')
        expect(page).to have_content('bar')
        expect(page).not_to have_content('baz')
286 287
      end

288 289 290 291
      it 'filters by due this month' do
        foo.update(due_date: Date.today.beginning_of_month + 2.days)
        bar.update(due_date: Date.today.end_of_month)
        baz.update(due_date: Date.today - 50.days)
Rémy Coutable committed
292

293
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::DueThisMonth.name)
Rémy Coutable committed
294 295 296 297

        expect(page).to have_content('foo')
        expect(page).to have_content('bar')
        expect(page).not_to have_content('baz')
298 299
      end

300 301 302 303 304
      it 'filters by overdue' do
        foo.update(due_date: Date.today + 2.days)
        bar.update(due_date: Date.today + 20.days)
        baz.update(due_date: Date.yesterday)

Rémy Coutable committed
305 306 307 308 309 310
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::Overdue.name)

        expect(page).not_to have_content('foo')
        expect(page).not_to have_content('bar')
        expect(page).to have_content('baz')
      end
311 312
    end

313
    describe 'sorting by milestone' do
Rémy Coutable committed
314
      before do
315 316 317 318 319 320 321
        foo.milestone = newer_due_milestone
        foo.save
        bar.milestone = later_due_milestone
        bar.save
      end

      it 'sorts by recently due milestone' do
Vinnie Okada committed
322
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_soon)
323

324
        expect(first_issue).to include('foo')
325
        expect(last_issue).to include('baz')
326 327 328
      end

      it 'sorts by least recently due milestone' do
Vinnie Okada committed
329
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_later)
330

331
        expect(first_issue).to include('bar')
332
        expect(last_issue).to include('baz')
333 334 335 336 337 338
      end
    end

    describe 'combine filter and sort' do
      let(:user2) { create(:user) }

Rémy Coutable committed
339
      before do
340 341 342 343 344 345 346
        foo.assignee = user2
        foo.save
        bar.assignee = user2
        bar.save
      end

      it 'sorts with a filter applied' do
Vinnie Okada committed
347 348 349
        visit namespace_project_issues_path(project.namespace, project,
                                            sort: sort_value_oldest_created,
                                            assignee_id: user2.id)
350

351 352
        expect(first_issue).to include('foo')
        expect(last_issue).to include('bar')
353
        expect(page).not_to have_content 'baz'
354 355 356
      end
    end
  end
357

358
  describe 'update assignee from issue#show' do
359
    let(:issue) { create(:issue, project: project, author: @user, assignee: @user) }
360

361
    context 'by authorized user' do
362

363
      it 'allows user to select unassigned', js: true do
Vinnie Okada committed
364
        visit namespace_project_issue_path(project.namespace, project, issue)
365

366 367 368
        page.within('.assignee') do
          expect(page).to have_content "#{@user.name}"

Phil Hughes committed
369 370
          click_link 'Edit'
          click_link 'Unassigned'
371 372
          expect(page).to have_content 'No assignee'
        end
373

374
        expect(issue.reload.assignee).to be_nil
375
      end
376 377 378 379 380 381 382 383 384 385 386 387

      it 'allows user to select an assignee', js: true do
        issue2 = create(:issue, project: project, author: @user)
        visit namespace_project_issue_path(project.namespace, project, issue2)

        page.within('.assignee') do
          expect(page).to have_content "No assignee"
        end

        page.within '.assignee' do
          click_link 'Edit'
        end
Phil Hughes committed
388

389 390 391 392 393 394 395 396
        page.within '.dropdown-menu-user' do
          click_link @user.name
        end

        page.within('.assignee') do
          expect(page).to have_content @user.name
        end
      end
397 398 399
    end

    context 'by unauthorized user' do
Dmitriy Zaporozhets committed
400

401
      let(:guest) { create(:user) }
Dmitriy Zaporozhets committed
402

Rémy Coutable committed
403
      before do
404 405 406
        project.team << [[guest], :guest]
      end

407
      it 'shows assignee text', js: true do
408 409 410
        logout
        login_with guest

Vinnie Okada committed
411
        visit namespace_project_issue_path(project.namespace, project, issue)
412
        expect(page).to have_content issue.assignee.name
413 414 415 416 417 418 419 420 421 422 423
      end
    end
  end

  describe 'update milestone from issue#show' do
    let!(:issue) { create(:issue, project: project, author: @user) }
    let!(:milestone) { create(:milestone, project: project) }

    context 'by authorized user' do


424 425
      it 'allows user to select unassigned', js: true do
        visit namespace_project_issue_path(project.namespace, project, issue)
426

427 428 429
        page.within('.milestone') do
          expect(page).to have_content "None"
        end
430

431 432 433 434
        find('.block.milestone .edit-link').click
        sleep 2 # wait for ajax stuff to complete
        first('.dropdown-content li').click
        sleep 2
435
        page.within('.milestone') do
436
          expect(page).to have_content 'None'
437 438
        end

439
        expect(issue.reload.milestone).to be_nil
440 441 442 443 444
      end
    end

    context 'by unauthorized user' do
      let(:guest) { create(:user) }
Dmitriy Zaporozhets committed
445

Rémy Coutable committed
446
      before do
Dmitriy Zaporozhets committed
447
        project.team << [guest, :guest]
448 449 450 451
        issue.milestone = milestone
        issue.save
      end

452
      it 'shows milestone text', js: true do
453 454 455
        logout
        login_with guest

Vinnie Okada committed
456
        visit namespace_project_issue_path(project.namespace, project, issue)
457
        expect(page).to have_content milestone.title
458 459
      end
    end
460 461 462 463

    describe 'removing assignee' do
      let(:user2) { create(:user) }

Rémy Coutable committed
464
      before do
465 466 467 468
        issue.assignee = user2
        issue.save
      end
    end
469 470
  end

471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
  describe 'new issue' do
    context 'dropzone upload file', js: true do
      before do
        visit new_namespace_project_issue_path(project.namespace, project)
      end

      it 'should upload file when dragging into textarea' do
        drop_in_dropzone test_image_file

        # Wait for the file to upload
        sleep 1

        expect(page.find_field("issue_description").value).to have_content 'banana_sample'
      end
    end
  end

Phil Hughes committed
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
  describe 'due date' do
    context 'update due on issue#show', js: true do
      let(:issue) { create(:issue, project: project, author: @user, assignee: @user) }

      before do
        visit namespace_project_issue_path(project.namespace, project, issue)
      end

      it 'should add due date to issue' do
        page.within '.due_date' do
          click_link 'Edit'

          page.within '.ui-datepicker-calendar' do
            first('.ui-state-default').click
          end

          expect(page).to have_no_content 'None'
        end
      end

      it 'should remove due date from issue' do
        page.within '.due_date' do
          click_link 'Edit'

          page.within '.ui-datepicker-calendar' do
            first('.ui-state-default').click
          end

          expect(page).to have_no_content 'None'

          click_link 'remove due date'
          expect(page).to have_content 'None'
        end
      end
    end
  end

525
  def first_issue
Douwe Maan committed
526
    page.all('ul.issues-list > li').first.text
527 528 529
  end

  def last_issue
Douwe Maan committed
530
    page.all('ul.issues-list > li').last.text
531
  end
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552

  def drop_in_dropzone(file_path)
    # Generate a fake input selector
    page.execute_script <<-JS
      var fakeFileInput = window.$('<input/>').attr(
        {id: 'fakeFileInput', type: 'file'}
      ).appendTo('body');
    JS
    # Attach the file to the fake input selector with Capybara
    attach_file("fakeFileInput", file_path)
    # Add the file to a fileList array and trigger the fake drop event
    page.execute_script <<-JS
      var fileList = [$('#fakeFileInput')[0].files[0]];
      var e = jQuery.Event('drop', { dataTransfer : { files : fileList } });
      $('.div-dropzone')[0].dropzone.listeners[0].events.drop(e);
    JS
  end

  def test_image_file
    File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')
  end
Dmitriy Zaporozhets committed
553
end