Commit 2b33b24a authored by Clement Ho's avatar Clement Ho

Shorten task status phrase

parent c288916d
...@@ -7,6 +7,7 @@ v 8.12.0 (unreleased) ...@@ -7,6 +7,7 @@ v 8.12.0 (unreleased)
- Reduce contributions calendar data payload (ClemMakesApps) - Reduce contributions calendar data payload (ClemMakesApps)
- Add `web_url` field to issue, merge request, and snippet API objects (Ben Boeckel) - 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) - 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) - Add hover color to emoji icon (ClemMakesApps)
- Optimistic locking for Issues and Merge Requests (title and description overriding prevention) - Optimistic locking for Issues and Merge Requests (title and description overriding prevention)
- Add `wiki_page_events` to project hook APIs (Ben Boeckel) - Add `wiki_page_events` to project hook APIs (Ben Boeckel)
......
...@@ -52,11 +52,11 @@ module Taskable ...@@ -52,11 +52,11 @@ module Taskable
end end
# Return a string that describes the current state of this Taskable's task # 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 def task_status
return '' if description.blank? return '' if description.blank?
sum = tasks.summary 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
end end
...@@ -20,6 +20,22 @@ feature 'Task Lists', feature: true do ...@@ -20,6 +20,22 @@ feature 'Task Lists', feature: true do
MARKDOWN MARKDOWN
end 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 before do
Warden.test_mode! Warden.test_mode!
...@@ -34,77 +50,145 @@ feature 'Task Lists', feature: true do ...@@ -34,77 +50,145 @@ feature 'Task Lists', feature: true do
end end
describe 'for Issues' do 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 it 'renders' do
visit_issue(project, issue) visit_issue(project, issue)
expect(page).to have_selector('ul.task-list', count: 1) 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('li.task-list-item', count: 6)
expect(page).to have_selector('ul input[checked]', count: 2) expect(page).to have_selector('ul input[checked]', count: 2)
end end
it 'contains the required selectors' do
visit_issue(project, issue)
container = '.detail-page-description .description.js-task-list-container'
it 'contains the required selectors' do expect(page).to have_selector(container)
visit_issue(project, issue) 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
container = '.detail-page-description .description.js-task-list-container' it 'is only editable by author' do
visit_issue(project, issue)
expect(page).to have_selector('.js-task-list-container')
expect(page).to have_selector(container) logout(:user)
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") login_as(user2)
expect(page).to have_selector('form.js-issuable-update') visit current_path
expect(page).to have_selector('a.btn-close') 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 end
it 'is only editable by author' do describe 'single incomplete task' do
visit_issue(project, issue) let!(:issue) { create(:issue, description: singleIncompleteMarkdown, author: user, project: project) }
expect(page).to have_selector('.js-task-list-container')
logout(:user) it 'renders' do
visit_issue(project, issue)
login_as(user2) expect(page).to have_selector('ul.task-list', count: 1)
visit current_path expect(page).to have_selector('li.task-list-item', count: 1)
expect(page).not_to have_selector('.js-task-list-container') 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 end
it 'provides a summary on Issues#index' do describe 'single complete task' do
visit namespace_project_issues_path(project.namespace, project) let!(:issue) { create(:issue, description: singleCompleteMarkdown, author: user, project: project) }
expect(page).to have_content("6 tasks (2 completed, 4 remaining)")
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: 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("1 of 1 task completed")
end
end end
end end
describe 'for Notes' do describe 'for Notes' do
let!(:issue) { create(:issue, author: user, project: project) } let!(:issue) { create(:issue, author: user, project: project) }
let!(:note) do describe 'multiple tasks' do
create(:note, note: markdown, noteable: issue, let!(:note) do
project: project, author: user) 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 end
it 'renders for note body' do describe 'single incomplete task' do
visit_issue(project, issue) let!(:note) do
create(:note, note: singleIncompleteMarkdown, noteable: issue,
expect(page).to have_selector('.note ul.task-list', count: 1) project: project, author: user)
expect(page).to have_selector('.note li.task-list-item', count: 6) end
expect(page).to have_selector('.note ul input[checked]', count: 2)
end
it 'contains the required selectors' do it 'renders for note body' do
visit_issue(project, issue) visit_issue(project, issue)
expect(page).to have_selector('.note .js-task-list-container') expect(page).to have_selector('.note ul.task-list', count: 1)
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 li.task-list-item', count: 1)
expect(page).to have_selector('.note .js-task-list-container .js-task-list-field') expect(page).to have_selector('.note ul input[checked]', count: 0)
end
end end
it 'is only editable by author' do describe 'single complete task' do
visit_issue(project, issue) let!(:note) do
expect(page).to have_selector('.js-task-list-container') create(:note, note: singleCompleteMarkdown, noteable: issue,
project: project, author: user)
end
logout(:user) it 'renders for note body' do
visit_issue(project, issue)
login_as(user2) expect(page).to have_selector('.note ul.task-list', count: 1)
visit current_path expect(page).to have_selector('.note li.task-list-item', count: 1)
expect(page).not_to have_selector('.js-task-list-container') expect(page).to have_selector('.note ul input[checked]', count: 1)
end
end end
end end
...@@ -113,42 +197,78 @@ feature 'Task Lists', feature: true do ...@@ -113,42 +197,78 @@ feature 'Task Lists', feature: true do
visit namespace_project_merge_request_path(project.namespace, project, merge) visit namespace_project_merge_request_path(project.namespace, project, merge)
end 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 it 'renders for description' do
visit_merge_request(project, merge) visit_merge_request(project, merge)
expect(page).to have_selector('ul.task-list', count: 1) 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('li.task-list-item', count: 6)
expect(page).to have_selector('ul input[checked]', count: 2) expect(page).to have_selector('ul input[checked]', count: 2)
end end
it 'contains the required selectors' do it 'contains the required selectors' do
visit_merge_request(project, merge) visit_merge_request(project, merge)
container = '.detail-page-description .description.js-task-list-container' container = '.detail-page-description .description.js-task-list-container'
expect(page).to have_selector(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} .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("#{container} .js-task-list-field")
expect(page).to have_selector('form.js-issuable-update') expect(page).to have_selector('form.js-issuable-update')
expect(page).to have_selector('a.btn-close') expect(page).to have_selector('a.btn-close')
end end
it 'is only editable by author' do it 'is only editable by author' do
visit_merge_request(project, merge) visit_merge_request(project, merge)
expect(page).to have_selector('.js-task-list-container') expect(page).to have_selector('.js-task-list-container')
logout(:user) logout(:user)
login_as(user2) login_as(user2)
visit current_path visit current_path
expect(page).not_to have_selector('.js-task-list-container') 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 end
it 'provides a summary on MergeRequests#index' do describe 'single complete task' do
visit namespace_project_merge_requests_path(project.namespace, project) let!(:merge) { create(:merge_request, :simple, description: singleCompleteMarkdown, author: user, source_project: project) }
expect(page).to have_content("6 tasks (2 completed, 4 remaining)")
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: 1)
end
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 end
end end
...@@ -3,30 +3,57 @@ ...@@ -3,30 +3,57 @@
# Requires a context containing: # Requires a context containing:
# subject { Issue or MergeRequest } # subject { Issue or MergeRequest }
shared_examples 'a Taskable' do shared_examples 'a Taskable' do
before do describe 'with multiple tasks' do
subject.description = <<-EOT.strip_heredoc before do
* [ ] Task 1 subject.description = <<-EOT.strip_heredoc
* [x] Task 2 * [ ] Task 1
* [x] Task 3 * [x] Task 2
* [ ] Task 4 * [x] Task 3
* [ ] Task 5 * [ ] Task 4
EOT * [ ] Task 5
EOT
end
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 end
it 'returns the correct task status' do describe 'with an incomplete task' do
expect(subject.task_status).to match('5 tasks') before do
expect(subject.task_status).to match('2 completed') subject.description = <<-EOT.strip_heredoc
expect(subject.task_status).to match('3 remaining') * [ ] 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 end
describe '#tasks?' do describe 'with a complete task' do
it 'returns true when object has tasks' do before do
expect(subject.tasks?).to eq true subject.description = <<-EOT.strip_heredoc
* [x] Task 1
EOT
end end
it 'returns false when object has no tasks' do it 'returns the correct task status' do
subject.description = 'Now I have no tasks' expect(subject.task_status).to match('1 of')
expect(subject.tasks?).to eq false expect(subject.task_status).to match('1 task completed')
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment