Actualizado plugin Redmine Questions 1.0.0 light

This commit is contained in:
Manuel Cillero 2019-03-21 17:52:05 +01:00
parent 27e60f8ec1
commit 5d7889f1c9
140 changed files with 5342 additions and 1430 deletions

View file

@ -0,0 +1,17 @@
_fixture:
model_class: Comment
comment_001:
content: text for cooment 001
commented_type: Question
commented_id: 1
author_id: 1
comment_002:
content: text for cooment 002
commented_type: Question
commented_id: 2
author_id: 1
comment_003:
content: text for cooment 003 (comment for answer!)
commented_type: Question
commented_id: 5
author_id: 1

View file

@ -0,0 +1,16 @@
comment_001:
comments: text for cooment 001
commented_type: Question
commented_id: 1
author_id: 1
comment_002:
comments: text for cooment 002
commented_type: Question
commented_id: 2
author_id: 1
comment_003:
comments: text for cooment 003 (comment for answer!)
commented_type: Question
commented_id: 5
author_id: 1

View file

@ -0,0 +1,26 @@
question_001:
id: 1
subject: Hard question
content: Text for hard question
author_id: 1
section_id: 1
question_002:
id: 2
subject: Another hard question
content: Text for Another hard question
author_id: 2
section_id: 1
featured: true
question_003:
id: 3
subject: Simple question
content: Text for simple question
author_id: 1
section_id: 2
question_004:
id: 4
subject: Another hard question
content: Text for simple hard question
author_id: 2
section_id: 2
locked: true

View file

@ -0,0 +1,12 @@
answer_001:
id: 1
content: This is answer for question_001
question_id: 1
author_id: 2
accepted: true
answer_002:
id: 2
content: This is answer for question_002
question_id: 2
author_id: 1
accepted: false

View file

@ -0,0 +1,25 @@
section_001:
id: 1
name: FAQ
section_type: questions
project_id: 1
section_002:
id: 2
name: Ideas
section_type: ideas
project_id: 2
section_003:
id: 3
name: Global FAQ
section_type: questions
project_id: 1
section_004:
id: 4
name: Off topic
section_type: questions
project_id: 1
section_005:
id: 5
name: Ideas in project 1
section_type: ideas
project_id: 1

View file

@ -0,0 +1,19 @@
tagging_001:
tag_id: 1
taggable_id: 1
taggable_type: Question
tagging_002:
tag_id: 1
taggable_id: 2
taggable_type: Question
tagging_003:
tag_id: 2
taggable_id: 3
taggable_type: Question
tagging_004:
tag_id: 2
taggable_id: 4
taggable_type: Question

View file

@ -0,0 +1,6 @@
tag_hard:
id: 1
name: hard
tag_simple:
id: 2
name: simple

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,39 @@
var oldToggleFilter = window.toggleFilter;
window.toggleFilter = function (field) {
oldToggleFilter(field);
return transform_to_select2(field);
};
function formatStateWithAvatar(opt) {
return $('<span>' + opt.avatar + '&nbsp;' + opt.text + '</span>');
};
var select2Filters = {};
function transform_to_select2(field) {
field = field.replace('.', '_');
var filter = select2Filters[field];
if (filter !== undefined && $('#tr_' + field + ' .values .select2').size() == 0) {
$('#tr_' + field + ' .toggle-multiselect').hide();
$('#tr_' + field + ' .values .value').attr('multiple', 'multiple');
$('#tr_' + field + ' .values .value').select2({
ajax: {
url: filter['url'],
dataType: 'json',
delay: 250,
data: function (params) {
return {q: params.term};
},
processResults: function (data, params) {
return {results: data};
},
cache: true
},
placeholder: ' ',
minimumInputLength: filter['minimumInputLength'],
width: filter['width'],
templateResult: filter['formatState']
});
}
};

View file

@ -0,0 +1,413 @@
.select2-container {
box-sizing: border-box;
display: inline-block;
margin: 0;
position: relative;
vertical-align: middle;
}
.select2-container .select2-selection--single {
box-sizing: border-box;
cursor: pointer;
display: block;
height: 28px;
user-select: none;
-webkit-user-select: none;
}
.select2-container .select2-selection--single .select2-selection__rendered {
display: block;
padding-left: 8px;
padding-right: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container .select2-selection--single .select2-selection__clear {
position: relative;
}
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 8px;
padding-left: 20px;
}
.select2-container .select2-selection--multiple {
box-sizing: border-box;
cursor: pointer;
display: block;
min-height: 24px;
user-select: none;
-webkit-user-select: none;
}
.select2-container .select2-selection--multiple .select2-selection__rendered {
/*display: inline-block;*/
overflow: hidden;
padding-left: 8px;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container .select2-search--inline {
float: left;
}
.select2-container .select2-search--inline .select2-search__field {
box-sizing: border-box;
border: none;
font-size: 100%;
margin-top: 2px;
padding: 0;
}
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none;
}
.select2-dropdown {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
box-sizing: border-box;
display: block;
position: absolute;
left: -100000px;
width: 100%;
z-index: 1051;
}
.select2-results {
display: block;
}
.select2-results__options {
list-style: none;
margin: 0;
padding: 0;
}
.select2-results__option {
padding: 6px;
user-select: none;
-webkit-user-select: none;
}
.select2-results__option[aria-selected] {
cursor: pointer;
}
.select2-container--open .select2-dropdown {
left: 0;
}
.select2-container--open .select2-dropdown--above {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--open .select2-dropdown--below {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-search--dropdown {
display: block;
padding: 4px;
}
.select2-search--dropdown .select2-search__field {
padding: 4px;
width: 100%;
box-sizing: border-box;
}
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none;
}
.select2-search--dropdown.select2-search--hide {
display: none;
}
.select2-close-mask {
border: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
left: 0;
top: 0;
min-height: 100%;
min-width: 100%;
height: auto;
width: auto;
opacity: 0;
z-index: 99;
background-color: #fff;
filter: alpha(opacity=0);
}
.select2-hidden-accessible {
border: 0 !important;
clip: rect(0 0 0 0) !important;
height: 1px !important;
margin: -1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
}
.select2-container--default .select2-selection--single {
background: #fff url(../images/vcard.png) no-repeat 2px 50%;
border: 1px solid #9EB1C2;
border-radius: 2px;
height: 21px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
padding-left: 21px;
line-height: 18px;
font-size: 11px;
}
.select2-container--default .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: normal;
color: #888;
}
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #999;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 20px;
position: absolute;
top: 0px;
right: 1px;
width: 20px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0;
}
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 1px;
right: auto;
}
.select2-container--default.select2-container--disabled .select2-selection--single {
background-color: #eee;
cursor: default;
}
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
display: none;
}
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--multiple {
background-color: white;
border: 1px solid #9EB1C2;
border-radius: 2px;
cursor: text;
}
#sidebar .select2-container--default .select2-selection--multiple .select2-selection__rendered,
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
list-style: none;
margin: 0;
padding: 0 2px 2px 2px;
width: 100%;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
list-style: none;
}
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
color: #999;
margin-top: 5px;
float: left;
}
.select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-top: 5px;
margin-right: 10px;
}
#sidebar .select2-container--default .select2-selection--multiple .select2-selection__choice,
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #efefef;
border-radius: 2px;
cursor: default;
float: left;
margin-right: 3px;
margin-top: 3px;
padding: 0 3px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #aaa;
cursor: pointer;
display: inline-block;
font-weight: normal;
margin-right: 2px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #333;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
.select2-container--default.select2-container--focus .select2-selection--multiple {
border: solid #aaa 1px;
outline: 0;
}
.select2-container--default.select2-container--disabled .select2-selection--multiple {
background-color: #eee;
cursor: default;
}
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
display: none;
}
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--default .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa;
}
.select2-container--default .select2-search--inline .select2-search__field {
background: transparent;
border: none;
outline: 0;
box-shadow: none;
-webkit-appearance: textfield;
}
.select2-container--default .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto;
}
.select2-container--default .select2-results__option[role=group] {
padding: 0;
}
.select2-container--default .select2-results__option[aria-disabled=true] {
color: #999;
}
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: #eee;
}
.select2-container--default .select2-results__option .select2-results__option {
padding-left: 1em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1em;
padding-left: 2em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -2em;
padding-left: 3em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -3em;
padding-left: 4em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -4em;
padding-left: 5em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -5em;
padding-left: 6em;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #eef5fd;
}
.select2-container--default .select2-results__group {
cursor: default;
display: block;
padding: 6px;
}
.filter .select2 {
margin: 1px;
}
.filter .select2-selection--multiple .select2-search--inline .select2-search__field {
border: 0px !important;
height: inherit !important;
padding: 0px !important;
}
.filter .select2-container--default .select2-selection--multiple .select2-selection__choice {
border: 0px;
padding: 2px 5px;
}
/* == Theming ===
.select2-container--default .select2-selection--single {
background: #fff url(../images/vcard.png) no-repeat 2px 50%;
border: 1px solid #9EB1C2;
border-radius: 2px;
height: 21px;
}
.select2-container--default .select2-selection--single:focus {
border-color: #2996cc;
outline: none;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
padding-left: 21px;
line-height: 18px;
font-size: 11px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 20px;
top: 0px;
right: 1px;
}
.select2-container--default .select2-selection--single .select2-selection__clear {
font-weight: normal;
color: #888;
}
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: #eee;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #eef5fd;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-color: #afafaf transparent transparent transparent;
}
.select2-dropdown {
border: 1px solid #e0e2e3;
border-radius: 3px;
}
*/

View file

@ -0,0 +1,149 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
class QuestionsAnswersControllerTest < ActionController::TestCase
fixtures :users, :projects, :roles,
:members,
:member_roles,
:trackers,
:enumerations,
:issue_statuses,
:projects_trackers,
:questions,
:questions_answers,
:questions_sections
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:questions, :questions_answers, :questions_sections])
def setup
RedmineQuestions::TestCase.prepare
@controller = QuestionsAnswersController.new
@project = projects(:projects_001)
User.current = nil
end
def test_post_create
@request.session[:user_id] = 1
ActionMailer::Base.deliveries.clear
user = User.find(1)
user.pref.no_self_notified = false
user.pref.save
Watcher.create(:watchable => questions(:question_001), :user => user)
question = questions(:question_001)
old_answer_count = question.answers.count
with_settings :notified_events => %w(question_answer_added) do
assert_difference 'QuestionsAnswer.count' do
compatible_request(
:post,
:create,
project_id: @project,
question_id: question,
answer: {
content: 'Answer for the first question',
question_id: question
}
)
end
end
answer = QuestionsAnswer.order(:created_on).last
mail = ActionMailer::Base.deliveries.last
assert_not_nil mail
assert_equal "[#{question.project.identifier} - #{question.section.name} - q&a#{question.id}] - answ##{answer.id} - RE: Hard question", mail.subject
assert_mail_body_match 'Answer for the first question', mail
assert_redirected_to :controller => 'questions',
:action => 'show',
:id => question,
:anchor => "question_item_#{QuestionsAnswer.order(:id).last.id}"
assert_equal old_answer_count + 1, question.answers.count
assert_equal 'Answer for the first question', question.answers.last.content
end
def test_preview_new_answer
@request.session[:user_id] = 1
answer = questions_answers(:answer_002)
compatible_xhr_request :post, :preview,
:answer => {
:content => "Previewed answer",
}
assert_response :success
assert_select 'fieldset' do
assert_select 'legend', :text => 'Preview'
assert_select 'p', :text => 'Previewed answer'
end
end
def test_preview_edited_answer
@request.session[:user_id] = 1
answer = questions_answers(:answer_002)
compatible_xhr_request :post, :preview, :id => answer.id,
:answer => {
:content => "Previewed answer 1",
}
assert_response :success
assert_select 'fieldset' do
assert_select 'legend', :text => 'Preview'
assert_select 'p', :text => 'Previewed answer 1'
end
end
def test_destroy
@request.session[:user_id] = 1
answer = questions_answers(:answer_002)
question = answer.question
assert_difference 'QuestionsAnswer.count', -1 do
compatible_request :post, :destroy, :id => answer.id
end
assert_redirected_to question_path(answer.question, :anchor => "question_item_#{answer.id}")
assert_nil QuestionsAnswer.find_by_id(answer.id)
end
def test_add_answer_to_locked_question
@request.session[:user_id] = 1
question = questions(:question_004)
assert_no_difference 'QuestionsAnswer.count' do
compatible_request :post, :create, :project_id => @project, :question_id => question.id,
:answer => { :content => 'Body of answer', :question_id => question.id }
end
end
def test_update_answer_with_mark_as_accepted_without_permission
@request.session[:user_id] = 3
answer = questions_answers(:answer_002)
compatible_request :post, :update, :id => answer.id,
:answer => {
:content => "Body of answer (changed)",
:accepted => 1
}
# assert_response :success
answer.reload
assert !answer.accepted, "Mark as officail answer did set for answer after update for user without permission"
end
end

View file

@ -0,0 +1,107 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
class QuestionsCommentsControllerTest < ActionController::TestCase
fixtures :users,
:projects,
:roles,
:members,
:member_roles,
:trackers,
:enumerations,
:projects_trackers,
:issues,
:issue_statuses,
:versions,
:trackers,
:projects_trackers,
:issue_categories,
:enabled_modules,
:workflows,
:questions,
:questions_answers,
:questions_sections
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:questions, :questions_answers, :questions_sections])
def setup
RedmineQuestions::TestCase.prepare
@controller = QuestionsCommentsController.new
@project = projects(:projects_001)
@comment = Comment.new(:comments => "Text", :author => users(:users_001))
questions(:question_001).comments << @comment
User.current = nil
end
def test_create_comment_for_question
@request.session[:user_id] = 2
ActionMailer::Base.deliveries.clear
user = User.find(2)
user.pref.no_self_notified = false
user.pref.save
Watcher.create(:watchable => questions(:question_001), :user => user)
comment_text = 'text for comment #123'
with_settings :notified_events => %w[question_comment_added] do
assert_difference 'Comment.count', 1 do
compatible_request :post, :create, :source_type => 'question', :source_id => 1, :comment => { :comments => comment_text }
end
end
question = questions(:question_001)
mail = ActionMailer::Base.deliveries.last
assert_not_nil mail, 'Notification has to be sent'
assert_equal "[#{question.project.identifier} - #{question.section.name} - q&a#{question.id}] RE: Hard question", mail.subject
assert_mail_body_match comment_text, mail
assert_response :redirect
question_comments = question.comments.order(:created_on).map{|c| c.try(:comments) || c.try(:content)}
assert_match comment_text, question_comments.join(', ')
end
def test_edit
@request.session[:user_id] = 1
compatible_request :get, :edit, :source_type => 'question', :source_id => questions(:question_001), :id => @comment
assert_response :success
end
def test_update
@request.session[:user_id] = 1
compatible_request :post, :update, :source_type => 'question', :source_id => questions(:question_001), :id => @comment,
:comment => {
:comments => 'Update text'
}
@comment.reload
assert_response :redirect
assert_equal 'Update text', @comment.comments
end
def test_destroy
@request.session[:user_id] = 1
assert_difference 'Comment.count', -1 do
compatible_request :delete, :destroy, :source_type => 'question', :source_id => questions(:question_001), :id => @comment
end
end
end

View file

@ -1,8 +1,238 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
class QuestionsControllerTest < ActionController::TestCase
# Replace this with your real tests.
def test_truth
assert true
fixtures :users,
:projects,
:roles,
:members,
:member_roles,
:trackers,
:enumerations,
:projects_trackers,
:issues,
:issue_statuses,
:versions,
:trackers,
:projects_trackers,
:issue_categories,
:enabled_modules,
:attachments,
:workflows,
:time_entries,
:questions,
:questions_answers,
:questions_sections
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/',
[:tags, :taggings, :comments])
def setup
RedmineQuestions::TestCase.prepare
@controller = QuestionsController.new
@project = projects(:projects_001)
@dev_role = Role.find(2)
@dev_role_permissions = @dev_role.permissions
User.current = nil
end
def test_get_index
@request.session[:user_id] = 1
compatible_request :get, :index, :project_id => @project
assert_response :success
assert_select 'div.topic h3.subject', {:count => @project.questions.count}
assert_select 'div.contextual a.icon-add', {:href => new_project_question_url(@project)}
latest_subject = Question.by_date.in_project(@project).limit(5)
assert_select 'ul.related-topics li', {:count => latest_subject.count}
end
def test_get_index_with_section
@request.session[:user_id] = 1
section = questions_sections(:section_001)
compatible_request :get, :index, :section_id => section.id, :project_id => section.project.id
assert_response :success
assert_select 'h2', {:text => section.name}
assert_select 'p.breadcrumb'
end
def test_post_create
@request.session[:user_id] = 1
ActionMailer::Base.deliveries.clear
user = User.find(1)
user.pref.no_self_notified = false
user.pref.save
with_settings :notified_events => %w(question_added) do
assert_difference 'Question.count' do
compatible_request :post, :create, :project_id => @project, :question => { :subject => 'Topic for new question',
:content => 'Body of text',
:section_id => 1 }
end
end
question = Question.where(:subject => 'Topic for new question').first
mail = ActionMailer::Base.deliveries.last
assert_not_nil mail
assert_equal "[#{question.project.identifier} - #{question.section.name} - q&a#{question.id}] Topic for new question", mail.subject
assert_mail_body_match 'Body of text', mail
end
def test_post_create_failed
@request.session[:user_id] = 1
compatible_request :post, :create, :project_id => @project,
:question => {
:content => "Body of text"
}
assert_response :success
end
def test_get_show
@request.session[:user_id] = 1
compatible_request :get, :show, :id => 1
assert_response :success
assert_select 'div h1', {:text => questions(:question_001).subject}
assert_match questions(:question_001).content, @response.body
assert_select 'div.add_comments .add-comment-form textarea'
assert_select 'div#reply'
assert_select 'a.icon-del'
assert_select 'a.add-comment-link'
assert_select 'span.items', {:text => "(1-1/1)"}
@dev_role.permissions << :add_answers
@dev_role.save
@request.session[:user_id] = 3
compatible_request :get, :show, :id => 1
assert_response :success
assert_select 'div h1', :text => questions(:question_001).subject
assert_match questions(:question_001).content, @response.body
assert_select 'div.add_comments .add-comment-form textarea', :count => 0
assert_select 'div#reply'
assert_select 'a.icon-del', :count => 0
@dev_role.permissions << :delete_questions
@dev_role.save
@request.session[:user_id] = 3
compatible_request :get, :show, :id => 1
assert_response :success
assert_select 'div h1', :text => questions(:question_001).subject
assert_match questions(:question_001).content, @response.body
assert_select 'div.add_comments .add-comment-form textarea', :count => 0
assert_select 'div#reply'
assert_select 'a.icon-del'
@dev_role.permissions << :comment_question
@dev_role.save
@request.session[:user_id] = 3
compatible_request :get, :show, :id => 1
assert_response :success
assert_select 'div h1', :text => questions(:question_001).subject
assert_match questions(:question_001).content, @response.body
assert_select 'div.add_comments .add-comment-form textarea', :count => 1
assert_select 'div#reply'
assert_select 'a.icon-del'
@dev_role.permissions = @dev_role_permissions
@dev_role.save
end
def test_destroy
@request.session[:user_id] = 1
question = questions(:question_001)
assert_difference 'Question.count', -1 do
compatible_request :post, :destroy, :id => question.id
end
assert_redirected_to questions_path(:section_id => question.section)
assert_nil Question.find_by_id(question.id)
end
def test_preview_new_question
@request.session[:user_id] = 1
question = questions(:question_001)
compatible_xhr_request :post, :preview,
:question => {
:content => "Previewed question",
}
assert_response :success
assert_select 'fieldset' do
assert_select 'legend', :text => 'Preview'
assert_select 'p', :text => 'Previewed question'
end
end
def test_update_question
@request.session[:user_id] = 1
question = Question.find 1
compatible_request :put, :update, :id => question.id,
:question => {
:content => "Update question",
:subject => "Changed subject",
:section_id => 1
}
question.reload
assert_equal "Update question", question.content
assert_equal "Changed subject", question.subject
end
def test_search_question
@request.session[:user_id] = 1
compatible_xhr_request :get, :autocomplete_for_subject, :project_id => @project, :q => "Hard"
assert_response :success
assert_select 'h3.subject', {:count => 2}
end
def test_should_not_get_create_by_deny_user
@request.session[:user_id] = 4
compatible_request :post, :create, :project_id => @project,
:question => {
:subject => "Topic for new question",
:content => "Body of text"
}
assert_response :forbidden
end
def test_should_not_allowed_to_update_question_by_deny_user
@request.session[:user_id] = 4
compatible_request :post, :update, :project_id => @project, :id => 1,
:question => {
:content => "new text",
:subject => "Changed subject"
}
assert_not_equal Question.find(1).subject, 'Changed subject'
end
# def test_convert_issue_to_question
# @request.session[:user_id] = 1
# compatible_request :get, :convert_issue_to_question, :project_id => @project, :issue_id => 1
# assert_response :redirect
# assert_equal Question.last.subject, Issue.find(1).subject
# end
# def test_convert_to_issue
# @request.session[:user_id] = 2
# compatible_request :get, :convert_to_issue, :project_id => @project, :id => 1
# issue = Issue.where(:subject => questions(:question_001).subject).first
# assert issue, "Not found issue after convertion"
# end
end

View file

@ -0,0 +1,156 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
class QuestionsSectionsControllerTest < ActionController::TestCase
fixtures :users,
:projects,
:roles,
:members,
:member_roles,
:trackers,
:enumerations,
:projects_trackers,
:issues,
:issue_statuses,
:versions,
:trackers,
:projects_trackers,
:issue_categories,
:enabled_modules,
:workflows,
:questions,
:questions_answers,
:questions_sections
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:questions, :questions_answers, :questions_sections])
def setup
RedmineQuestions::TestCase.prepare
@controller = QuestionsSectionsController.new
@dev_role = Role.find(2)
@project = Project.find(1)
@dev_role_permissions = @dev_role.permissions
User.current = nil
end
def test_global_index
@request.session[:user_id] = 1
compatible_request :get, :index
assert_response 200
assert_select 'a.section-tile', :count => QuestionsSection.visible.with_questions_count.to_a.size
assert_select 'div.project-forums h3', :count => 2
@request.session[:user_id] = 3
compatible_request :get, :index
assert_response 200
assert_select 'a.section-tile', :count => QuestionsSection.visible.where(:project_id => 1).with_questions_count.to_a.size
assert_select 'div.project-forums h3', :count => 1
assert_select 'body', :text => /New question/, :count => 0
@dev_role.permissions = @dev_role_permissions
@dev_role.save
end
def test_project_index
@request.session[:user_id] = 1
compatible_request :get, :index, :project_id => 1
assert_response 200
assert_select 'a.section-tile', :count => QuestionsSection.where(:project_id => 1).with_questions_count.to_a.size
assert_select 'a', /New question/
@request.session[:user_id] = 3
compatible_request :get, :index, :project_id => 1
assert_response 200
assert_select 'a.section-tile', :count => QuestionsSection.where(:project_id => 1).with_questions_count.to_a.size
assert_select 'body', :text => /New question/, :count => 0
@dev_role.permissions << :add_questions
@dev_role.save
@request.session[:user_id] = 3
compatible_request :get, :index, :project_id => 1
assert_response 200
assert_select 'a', /New question/
@dev_role.permissions = @dev_role_permissions
@dev_role.save
end
def test_new
@request.session[:user_id] = 1
compatible_request :get, :new, :project_id => @project
assert_response :success
end
def test_create_for_project
@request.session[:user_id] = 1
assert_difference 'QuestionsSection.count' do
compatible_request :post, :create, :project_id => @project,
:questions_section => {
:name => "New section",
:section_type => "solution"
}
end
assert_equal @project, QuestionsSection.last.project
end
def test_delete
@request.session[:user_id] = 1
section = questions_sections(:section_001)
assert_difference 'QuestionsSection.count', -1 do
compatible_request :delete, :destroy, :id => section
end
assert_nil QuestionsSection.find_by_id(section.id)
end
def test_update
@request.session[:user_id] = 1
section = questions_sections(:section_001)
compatible_request :put, :update, :id => section, :questions_section => {:name => 'Edited section'}
section.reload
assert_equal section.name, 'Edited section'
end
def test_new_from_question_form
@request.session[:user_id] = 1
compatible_xhr_request :get, :new, :project_id => '1'
assert_response :success
assert_equal 'text/javascript', response.content_type
end
def test_create_from_question_form
@request.session[:user_id] = 1
assert_difference 'QuestionsSection.count' do
compatible_xhr_request :post, :create, :project_id => '1', :questions_section => { 'section_type' => 'solution', :name => 'add_section_from_question_form' }
end
section = QuestionsSection.find_by_name("add_section_from_question_form")
assert_not_nil section
assert_equal 1, section.project_id
assert_response :success
assert_equal 'text/javascript', response.content_type
assert_include 'add_section_from_question_form', response.body
end
end

View file

@ -0,0 +1,66 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
class RedmineQuestions::CommonViewsTest < ActionDispatch::IntegrationTest
fixtures :users,
:projects,
:roles,
:members,
:member_roles,
:trackers,
:enumerations,
:projects_trackers,
:issues,
:issue_statuses,
:versions,
:trackers,
:projects_trackers,
:issue_categories,
:enabled_modules,
:workflows,
:questions,
:questions_answers,
:questions_sections
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:questions, :questions_answers, :questions_sections])
def setup
@project_1 = Project.find(1)
EnabledModule.create(:project => @project_1, :name => 'questions')
end
def test_view_activity_with_questions
log_user('admin', 'admin')
compatible_request :get, '/activity', :show_questions => 1
assert_response :success
end
def test_global_search_with_questions
log_user('admin', 'admin')
get '/search?q=simple&questions=1'
assert_response :success
end
end

View file

@ -1,2 +1,117 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
# Load the Redmine helper
require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')
module RedmineQuestions
module TestHelper
def compatible_request(type, action, parameters = {})
return send(type, action, parameters) if Redmine::VERSION.to_s < '3.5' && Redmine::VERSION::BRANCH == 'stable'
send(type, action, :params => parameters)
end
def compatible_xhr_request(type, action, parameters = {})
return xhr type, action, parameters if Redmine::VERSION.to_s < '3.5' && Redmine::VERSION::BRANCH == 'stable'
send(type, action, :params => parameters, :xhr => true)
end
def log_user(login, password)
User.anonymous
compatible_request :get, '/logout'
compatible_request :get, '/login'
assert_nil session[:user_id]
assert_response :success
compatible_request :post, '/login', :username => login, :password => password
assert_equal login, User.find(session[:user_id]).login
end
end
end
class RedmineQuestions::TestCase
include ActionDispatch::TestProcess
def self.plugin_fixtures(plugin, *fixture_names)
plugin_fixture_path = "#{Redmine::Plugin.find(plugin).directory}/test/fixtures"
if fixture_names.first == :all
fixture_names = Dir["#{plugin_fixture_path}/**/*.{yml}"]
fixture_names.map! { |f| f[(plugin_fixture_path.size + 1)..-5] }
else
fixture_names = fixture_names.flatten.map { |n| n.to_s }
end
ActiveRecord::Fixtures.create_fixtures(plugin_fixture_path, fixture_names)
end
def self.create_fixtures(fixtures_directory, table_names, class_names = {})
if ActiveRecord::VERSION::MAJOR >= 4
if Comment.column_names.include?('content')
table_names.map!{ |x| x.to_s.gsub('comments', 'comments-3.4.6').to_sym }
ActiveRecord::FixtureSet.create_fixtures(fixtures_directory, table_names, class_names = {})
else
ActiveRecord::FixtureSet.create_fixtures(fixtures_directory, table_names, class_names = {})
end
else
ActiveRecord::Fixtures.create_fixtures(fixtures_directory, table_names, class_names = {})
end
end
def self.prepare
Role.where(:id => [1, 3]).each do |r|
# user_2
r.permissions << :view_questions
r.permissions << :global_view_questions
r.permissions << :add_questions
r.permissions << :edit_questions
r.permissions << :add_answers
r.permissions << :update_questions
r.permissions << :comment_question
r.permissions << :vote_questions
r.permissions << :convert_questions
r.permissions << :accept_answers
r.permissions << :global_accept_answer
r.save
end
Role.where(:id => [5]).each do |r|
# anonymous
r.permissions << :global_view_questions
r.save
end
# user_3 only developer (role #2) for project #1
Role.where(:id => 2).each do |r|
r.permissions << :view_questions
r.save
end
Role.where(:id => 1).each do |r|
r.permissions << :accept_answers
r.save
end
Project.where(:id => [1, 2, 3, 4, 5]).each do |project|
EnabledModule.create(:project => project, :name => 'questions')
end
end
end
include RedmineQuestions::TestHelper

View file

@ -0,0 +1,166 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
class QuestionTest < ActiveSupport::TestCase
fixtures :users,
:projects,
:roles,
:members,
:member_roles,
:trackers,
:enumerations,
:projects_trackers,
:issues,
:issue_statuses,
:versions,
:trackers,
:projects_trackers,
:issue_categories,
:enabled_modules,
:workflows,
:questions,
:questions_answers,
:questions_sections
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/',
[:comments, :tags, :taggings])
def setup
RedmineQuestions::TestCase.prepare
end
def question(x)
q = 'question_'
q += '0' * (3 - x.to_s.length) + x.to_s
questions(q.to_sym)
end
def answer(x)
q = 'answer_'
q += '0' * (3 - x.to_s.length) + x.to_s
questions_answers(q.to_sym)
end
def test_creating
new_question = Question.new
new_question.subject = 'Some new question'
new_question.author = users(:users_001)
new_question.section = questions_sections(:section_001)
assert !new_question.save, 'Content cannot be blank'
end
def test_require_author
new_question = Question.new(:subject => 'Some new question')
assert !new_question.save, 'Question must have author'
end
def test_require_topic
new_question = Question.new(:author => users(:users_001))
assert !new_question.save, 'Question must have topic'
end
def test_creating_answer
answer = QuestionsAnswer.new
answer.author = users(:users_002)
answer.content = 'Answer text'
answer.question = question(1)
assert answer.save, 'Failed to save the answer'
end
def test_save_answer_without_question_relation
answer = answer(1)
answer.question = nil
assert !answer.save, 'Can save answer without question'
end
def test_add_answer_for_question
question = question(3)
new_ans = QuestionsAnswer.new
new_ans.author = users(:users_001)
new_ans.question = question
new_ans.content = 'some text'
assert new_ans.save
assert_equal question.answers.count, 1
end
def test_diny_add_answer_for_locked_question
question = question(4)
new_ans = QuestionsAnswer.new
new_ans.author = users(:users_001)
new_ans.question = question
new_ans.content = 'some text'
assert !new_ans.valid?
end
def test_destroy_question_with_answer
question = question(1)
ans = question.answers.first
question.destroy
assert_raises(ActiveRecord::RecordNotFound) { QuestionsAnswer.find(ans.id) }
end
def test_questions_for_project
assert_equal Question.in_project(projects(:projects_001)).count, 2
end
def test_related_questions
related_questons = Question.related(question(1), 2)
assert_equal 1, related_questons.size
related_questons.each do |rq|
assert_match /question/, rq.subject
end
end
def test_add_comment
question = Question.find 1
comment = Comment.new(:comments => 'comment text', :author => users(:users_001))
assert question.comments << comment, 'Error with adding comment to question'
question.comments.reload
assert_equal question.comments.size, 2
end
def test_commetable
assert question(1).commentable?(users(:users_002)), "Question not commentable for user with permission"
assert !question(1).commentable?(users(:users_004)), "Question commentable for user without permission"
end
def test_editable_by
assert question(1).editable_by?(users(:users_002)), "Question not editable for user with permission"
assert !question(1).editable_by?(users(:users_004)), "Question editable for user without permission"
end
def test_votable_by
assert question(1).votable_by?(users(:users_002)), "User with permission can not vote by question"
assert !question(1).votable_by?(users(:users_004)), "User #4 can vote by question"
end
def test_accepted_answer
answer = answer(1)
question = question(1)
answer.accepted = true
assert answer.accepted?, 'Mark as accepted_answer did not set for answer'
assert question.answered?, 'Mark as accepted_answer did set for question'
end
end

View file

@ -0,0 +1,42 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
class QuestionsSectionTest < ActiveSupport::TestCase
fixtures :questions, :questions_sections
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:questions, :questions_sections])
def test_relations
assert questions_sections(:section_001).questions
end
def test_to_s
assert_equal questions_sections(:section_001).name, questions_sections(:section_001).to_s
end
def test_l_type
assert_equal "Questions", questions_sections(:section_001).l_type
I18n.locale = "es"
assert_equal "Questions", questions_sections(:section_001).l_type
end
end

View file

@ -0,0 +1,34 @@
# encoding: utf-8
#
# This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine
#
# Copyright (C) 2011-2018 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# redmine_questions is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
class UserTest < ActiveSupport::TestCase
fixtures :users
def user
users(:users_001)
end
def test_user_voter
assert User.voter?, "User must be a voter, but it isn't it"
end
end