Shorten task status phrase
This commit is contained in:
parent
c288916db1
commit
2b33b24a3a
4 changed files with 249 additions and 101 deletions
|
@ -7,6 +7,7 @@ v 8.12.0 (unreleased)
|
|||
- Reduce contributions calendar data payload (ClemMakesApps)
|
||||
- Add `web_url` field to issue, merge request, and snippet API objects (Ben Boeckel)
|
||||
- Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling)
|
||||
- Shorten task status phrase (ClemMakesApps)
|
||||
- Add hover color to emoji icon (ClemMakesApps)
|
||||
- Optimistic locking for Issues and Merge Requests (title and description overriding prevention)
|
||||
- Add `wiki_page_events` to project hook APIs (Ben Boeckel)
|
||||
|
|
|
@ -52,11 +52,11 @@ module Taskable
|
|||
end
|
||||
|
||||
# Return a string that describes the current state of this Taskable's task
|
||||
# list items, e.g. "20 tasks (12 completed, 8 remaining)"
|
||||
# list items, e.g. "12 of 20 tasks completed"
|
||||
def task_status
|
||||
return '' if description.blank?
|
||||
|
||||
sum = tasks.summary
|
||||
"#{sum.item_count} tasks (#{sum.complete_count} completed, #{sum.incomplete_count} remaining)"
|
||||
"#{sum.complete_count} of #{sum.item_count} #{'task'.pluralize(sum.item_count)} completed"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,6 +20,22 @@ feature 'Task Lists', feature: true do
|
|||
MARKDOWN
|
||||
end
|
||||
|
||||
let(:singleIncompleteMarkdown) do
|
||||
<<-MARKDOWN.strip_heredoc
|
||||
This is a task list:
|
||||
|
||||
- [ ] Incomplete entry 1
|
||||
MARKDOWN
|
||||
end
|
||||
|
||||
let(:singleCompleteMarkdown) do
|
||||
<<-MARKDOWN.strip_heredoc
|
||||
This is a task list:
|
||||
|
||||
- [x] Incomplete entry 1
|
||||
MARKDOWN
|
||||
end
|
||||
|
||||
before do
|
||||
Warden.test_mode!
|
||||
|
||||
|
@ -34,77 +50,145 @@ feature 'Task Lists', feature: true do
|
|||
end
|
||||
|
||||
describe 'for Issues' do
|
||||
let!(:issue) { create(:issue, description: markdown, author: user, project: project) }
|
||||
describe 'multiple tasks' do
|
||||
let!(:issue) { create(:issue, description: markdown, author: user, project: project) }
|
||||
|
||||
it 'renders' do
|
||||
visit_issue(project, issue)
|
||||
it 'renders' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 6)
|
||||
expect(page).to have_selector('ul input[checked]', count: 2)
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 6)
|
||||
expect(page).to have_selector('ul input[checked]', count: 2)
|
||||
end
|
||||
|
||||
it 'contains the required selectors' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
container = '.detail-page-description .description.js-task-list-container'
|
||||
|
||||
expect(page).to have_selector(container)
|
||||
expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
|
||||
expect(page).to have_selector("#{container} .js-task-list-field")
|
||||
expect(page).to have_selector('form.js-issuable-update')
|
||||
expect(page).to have_selector('a.btn-close')
|
||||
end
|
||||
|
||||
it 'is only editable by author' do
|
||||
visit_issue(project, issue)
|
||||
expect(page).to have_selector('.js-task-list-container')
|
||||
|
||||
logout(:user)
|
||||
|
||||
login_as(user2)
|
||||
visit current_path
|
||||
expect(page).not_to have_selector('.js-task-list-container')
|
||||
end
|
||||
|
||||
it 'provides a summary on Issues#index' do
|
||||
visit namespace_project_issues_path(project.namespace, project)
|
||||
expect(page).to have_content("2 of 6 tasks completed")
|
||||
end
|
||||
end
|
||||
|
||||
it 'contains the required selectors' do
|
||||
visit_issue(project, issue)
|
||||
describe 'single incomplete task' do
|
||||
let!(:issue) { create(:issue, description: singleIncompleteMarkdown, author: user, project: project) }
|
||||
|
||||
container = '.detail-page-description .description.js-task-list-container'
|
||||
it 'renders' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
expect(page).to have_selector(container)
|
||||
expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
|
||||
expect(page).to have_selector("#{container} .js-task-list-field")
|
||||
expect(page).to have_selector('form.js-issuable-update')
|
||||
expect(page).to have_selector('a.btn-close')
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 1)
|
||||
expect(page).to have_selector('ul input[checked]', count: 0)
|
||||
end
|
||||
|
||||
it 'provides a summary on Issues#index' do
|
||||
visit namespace_project_issues_path(project.namespace, project)
|
||||
expect(page).to have_content("0 of 1 task completed")
|
||||
end
|
||||
end
|
||||
|
||||
it 'is only editable by author' do
|
||||
visit_issue(project, issue)
|
||||
expect(page).to have_selector('.js-task-list-container')
|
||||
describe 'single complete task' do
|
||||
let!(:issue) { create(:issue, description: singleCompleteMarkdown, author: user, project: project) }
|
||||
|
||||
logout(:user)
|
||||
it 'renders' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
login_as(user2)
|
||||
visit current_path
|
||||
expect(page).not_to have_selector('.js-task-list-container')
|
||||
end
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 1)
|
||||
expect(page).to have_selector('ul input[checked]', count: 1)
|
||||
end
|
||||
|
||||
it 'provides a summary on Issues#index' do
|
||||
visit namespace_project_issues_path(project.namespace, project)
|
||||
expect(page).to have_content("6 tasks (2 completed, 4 remaining)")
|
||||
it 'provides a summary on Issues#index' do
|
||||
visit namespace_project_issues_path(project.namespace, project)
|
||||
expect(page).to have_content("1 of 1 task completed")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'for Notes' do
|
||||
let!(:issue) { create(:issue, author: user, project: project) }
|
||||
let!(:note) do
|
||||
create(:note, note: markdown, noteable: issue,
|
||||
project: project, author: user)
|
||||
describe 'multiple tasks' do
|
||||
let!(:note) do
|
||||
create(:note, note: markdown, noteable: issue,
|
||||
project: project, author: user)
|
||||
end
|
||||
|
||||
it 'renders for note body' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
expect(page).to have_selector('.note ul.task-list', count: 1)
|
||||
expect(page).to have_selector('.note li.task-list-item', count: 6)
|
||||
expect(page).to have_selector('.note ul input[checked]', count: 2)
|
||||
end
|
||||
|
||||
it 'contains the required selectors' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
expect(page).to have_selector('.note .js-task-list-container')
|
||||
expect(page).to have_selector('.note .js-task-list-container .task-list .task-list-item .task-list-item-checkbox')
|
||||
expect(page).to have_selector('.note .js-task-list-container .js-task-list-field')
|
||||
end
|
||||
|
||||
it 'is only editable by author' do
|
||||
visit_issue(project, issue)
|
||||
expect(page).to have_selector('.js-task-list-container')
|
||||
|
||||
logout(:user)
|
||||
|
||||
login_as(user2)
|
||||
visit current_path
|
||||
expect(page).not_to have_selector('.js-task-list-container')
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders for note body' do
|
||||
visit_issue(project, issue)
|
||||
describe 'single incomplete task' do
|
||||
let!(:note) do
|
||||
create(:note, note: singleIncompleteMarkdown, noteable: issue,
|
||||
project: project, author: user)
|
||||
end
|
||||
|
||||
expect(page).to have_selector('.note ul.task-list', count: 1)
|
||||
expect(page).to have_selector('.note li.task-list-item', count: 6)
|
||||
expect(page).to have_selector('.note ul input[checked]', count: 2)
|
||||
it 'renders for note body' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
expect(page).to have_selector('.note ul.task-list', count: 1)
|
||||
expect(page).to have_selector('.note li.task-list-item', count: 1)
|
||||
expect(page).to have_selector('.note ul input[checked]', count: 0)
|
||||
end
|
||||
end
|
||||
|
||||
it 'contains the required selectors' do
|
||||
visit_issue(project, issue)
|
||||
describe 'single complete task' do
|
||||
let!(:note) do
|
||||
create(:note, note: singleCompleteMarkdown, noteable: issue,
|
||||
project: project, author: user)
|
||||
end
|
||||
|
||||
expect(page).to have_selector('.note .js-task-list-container')
|
||||
expect(page).to have_selector('.note .js-task-list-container .task-list .task-list-item .task-list-item-checkbox')
|
||||
expect(page).to have_selector('.note .js-task-list-container .js-task-list-field')
|
||||
end
|
||||
it 'renders for note body' do
|
||||
visit_issue(project, issue)
|
||||
|
||||
it 'is only editable by author' do
|
||||
visit_issue(project, issue)
|
||||
expect(page).to have_selector('.js-task-list-container')
|
||||
|
||||
logout(:user)
|
||||
|
||||
login_as(user2)
|
||||
visit current_path
|
||||
expect(page).not_to have_selector('.js-task-list-container')
|
||||
expect(page).to have_selector('.note ul.task-list', count: 1)
|
||||
expect(page).to have_selector('.note li.task-list-item', count: 1)
|
||||
expect(page).to have_selector('.note ul input[checked]', count: 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -113,42 +197,78 @@ feature 'Task Lists', feature: true do
|
|||
visit namespace_project_merge_request_path(project.namespace, project, merge)
|
||||
end
|
||||
|
||||
let!(:merge) { create(:merge_request, :simple, description: markdown, author: user, source_project: project) }
|
||||
describe 'multiple tasks' do
|
||||
let!(:merge) { create(:merge_request, :simple, description: markdown, author: user, source_project: project) }
|
||||
|
||||
it 'renders for description' do
|
||||
visit_merge_request(project, merge)
|
||||
it 'renders for description' do
|
||||
visit_merge_request(project, merge)
|
||||
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 6)
|
||||
expect(page).to have_selector('ul input[checked]', count: 2)
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 6)
|
||||
expect(page).to have_selector('ul input[checked]', count: 2)
|
||||
end
|
||||
|
||||
it 'contains the required selectors' do
|
||||
visit_merge_request(project, merge)
|
||||
|
||||
container = '.detail-page-description .description.js-task-list-container'
|
||||
|
||||
expect(page).to have_selector(container)
|
||||
expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
|
||||
expect(page).to have_selector("#{container} .js-task-list-field")
|
||||
expect(page).to have_selector('form.js-issuable-update')
|
||||
expect(page).to have_selector('a.btn-close')
|
||||
end
|
||||
|
||||
it 'is only editable by author' do
|
||||
visit_merge_request(project, merge)
|
||||
expect(page).to have_selector('.js-task-list-container')
|
||||
|
||||
logout(:user)
|
||||
|
||||
login_as(user2)
|
||||
visit current_path
|
||||
expect(page).not_to have_selector('.js-task-list-container')
|
||||
end
|
||||
|
||||
it 'provides a summary on MergeRequests#index' do
|
||||
visit namespace_project_merge_requests_path(project.namespace, project)
|
||||
expect(page).to have_content("2 of 6 tasks completed")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'single incomplete task' do
|
||||
let!(:merge) { create(:merge_request, :simple, description: singleIncompleteMarkdown, author: user, source_project: project) }
|
||||
|
||||
it 'renders for description' do
|
||||
visit_merge_request(project, merge)
|
||||
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 1)
|
||||
expect(page).to have_selector('ul input[checked]', count: 0)
|
||||
end
|
||||
|
||||
it 'provides a summary on MergeRequests#index' do
|
||||
visit namespace_project_merge_requests_path(project.namespace, project)
|
||||
expect(page).to have_content("0 of 1 task completed")
|
||||
end
|
||||
end
|
||||
|
||||
it 'contains the required selectors' do
|
||||
visit_merge_request(project, merge)
|
||||
describe 'single complete task' do
|
||||
let!(:merge) { create(:merge_request, :simple, description: singleCompleteMarkdown, author: user, source_project: project) }
|
||||
|
||||
container = '.detail-page-description .description.js-task-list-container'
|
||||
it 'renders for description' do
|
||||
visit_merge_request(project, merge)
|
||||
|
||||
expect(page).to have_selector(container)
|
||||
expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
|
||||
expect(page).to have_selector("#{container} .js-task-list-field")
|
||||
expect(page).to have_selector('form.js-issuable-update')
|
||||
expect(page).to have_selector('a.btn-close')
|
||||
end
|
||||
expect(page).to have_selector('ul.task-list', count: 1)
|
||||
expect(page).to have_selector('li.task-list-item', count: 1)
|
||||
expect(page).to have_selector('ul input[checked]', count: 1)
|
||||
end
|
||||
|
||||
it 'is only editable by author' do
|
||||
visit_merge_request(project, merge)
|
||||
expect(page).to have_selector('.js-task-list-container')
|
||||
|
||||
logout(:user)
|
||||
|
||||
login_as(user2)
|
||||
visit current_path
|
||||
expect(page).not_to have_selector('.js-task-list-container')
|
||||
end
|
||||
|
||||
it 'provides a summary on MergeRequests#index' do
|
||||
visit namespace_project_merge_requests_path(project.namespace, project)
|
||||
expect(page).to have_content("6 tasks (2 completed, 4 remaining)")
|
||||
it 'provides a summary on MergeRequests#index' do
|
||||
visit namespace_project_merge_requests_path(project.namespace, project)
|
||||
expect(page).to have_content("1 of 1 task completed")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,30 +3,57 @@
|
|||
# Requires a context containing:
|
||||
# subject { Issue or MergeRequest }
|
||||
shared_examples 'a Taskable' do
|
||||
before do
|
||||
subject.description = <<-EOT.strip_heredoc
|
||||
* [ ] Task 1
|
||||
* [x] Task 2
|
||||
* [x] Task 3
|
||||
* [ ] Task 4
|
||||
* [ ] Task 5
|
||||
EOT
|
||||
end
|
||||
|
||||
it 'returns the correct task status' do
|
||||
expect(subject.task_status).to match('5 tasks')
|
||||
expect(subject.task_status).to match('2 completed')
|
||||
expect(subject.task_status).to match('3 remaining')
|
||||
end
|
||||
|
||||
describe '#tasks?' do
|
||||
it 'returns true when object has tasks' do
|
||||
expect(subject.tasks?).to eq true
|
||||
describe 'with multiple tasks' do
|
||||
before do
|
||||
subject.description = <<-EOT.strip_heredoc
|
||||
* [ ] Task 1
|
||||
* [x] Task 2
|
||||
* [x] Task 3
|
||||
* [ ] Task 4
|
||||
* [ ] Task 5
|
||||
EOT
|
||||
end
|
||||
|
||||
it 'returns false when object has no tasks' do
|
||||
subject.description = 'Now I have no tasks'
|
||||
expect(subject.tasks?).to eq false
|
||||
it 'returns the correct task status' do
|
||||
expect(subject.task_status).to match('2 of')
|
||||
expect(subject.task_status).to match('5 tasks completed')
|
||||
end
|
||||
|
||||
describe '#tasks?' do
|
||||
it 'returns true when object has tasks' do
|
||||
expect(subject.tasks?).to eq true
|
||||
end
|
||||
|
||||
it 'returns false when object has no tasks' do
|
||||
subject.description = 'Now I have no tasks'
|
||||
expect(subject.tasks?).to eq false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with an incomplete task' do
|
||||
before do
|
||||
subject.description = <<-EOT.strip_heredoc
|
||||
* [ ] Task 1
|
||||
EOT
|
||||
end
|
||||
|
||||
it 'returns the correct task status' do
|
||||
expect(subject.task_status).to match('0 of')
|
||||
expect(subject.task_status).to match('1 task completed')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a complete task' do
|
||||
before do
|
||||
subject.description = <<-EOT.strip_heredoc
|
||||
* [x] Task 1
|
||||
EOT
|
||||
end
|
||||
|
||||
it 'returns the correct task status' do
|
||||
expect(subject.task_status).to match('1 of')
|
||||
expect(subject.task_status).to match('1 task completed')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue