Don't use stubs for UserInfo.current_user_id because it blocks the use case where UserInfo.current_user_id is changed at runtime.
This commit is contained in:
parent
8096ee0892
commit
6606aa29cd
33 changed files with 482 additions and 242 deletions
|
@ -336,6 +336,7 @@ browser:build:
|
|||
paths:
|
||||
- public/assets/.sprockets-manifest*
|
||||
- public/assets/application-*
|
||||
- public/assets/knowledge_base*
|
||||
- public/assets/print-*
|
||||
|
||||
.services_browser_template: &services_browser_definition
|
||||
|
|
|
@ -86,13 +86,6 @@ Rails/HasManyOrHasOneDependent:
|
|||
- 'app/models/ticket/state_type.rb'
|
||||
- 'app/models/user.rb'
|
||||
|
||||
# Offense count: 15
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/helpers/**/*.rb
|
||||
Rails/HelperInstanceVariable:
|
||||
Exclude:
|
||||
- 'app/helpers/knowledge_base_helper.rb'
|
||||
|
||||
# Offense count: 808
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
|
58
app/helpers/knowledge_base_breadcrumb_helper.rb
Normal file
58
app/helpers/knowledge_base_breadcrumb_helper.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
module KnowledgeBaseBreadcrumbHelper
|
||||
def render_breadcrumb_if_needed(knowledge_base, object, alternative)
|
||||
objects = calculate_breadcrumb_path(object, alternative)
|
||||
|
||||
return if objects.empty?
|
||||
|
||||
render 'knowledge_base/public/breadcrumb',
|
||||
{
|
||||
objects: objects,
|
||||
knowledge_base: knowledge_base
|
||||
}
|
||||
end
|
||||
|
||||
def calculate_breadcrumb_path(object, alternative)
|
||||
objects = calculate_breadcrumb_to_category(object&.parent)
|
||||
|
||||
last = if alternative.present? && alternative.translations.any?
|
||||
Translation.translate(system_locale_via_uri&.locale, 'Alternative translations')
|
||||
else
|
||||
object
|
||||
end
|
||||
|
||||
objects + [last].compact
|
||||
end
|
||||
|
||||
def calculate_breadcrumb_to_category(category)
|
||||
return [] if category.blank?
|
||||
|
||||
output = [category]
|
||||
|
||||
parent = category
|
||||
while (parent = find_category(parent&.parent_id))
|
||||
output << parent
|
||||
end
|
||||
|
||||
output.compact.reverse
|
||||
end
|
||||
|
||||
def breadcrumb_path_for(object, locale = params.fetch(:locale))
|
||||
case object
|
||||
when KnowledgeBase
|
||||
help_root_path(locale: locale)
|
||||
when KnowledgeBase::Category
|
||||
help_category_path(object.translation, locale: locale)
|
||||
when KnowledgeBase::Answer
|
||||
help_answer_path(object.category.translation, object.translation, locale: locale)
|
||||
end
|
||||
end
|
||||
|
||||
def breadcrumb_text_for(object)
|
||||
case object
|
||||
when HasTranslations
|
||||
object.translation.title
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,97 +1,11 @@
|
|||
module KnowledgeBaseHelper
|
||||
def render_breadcrumb_if_needed
|
||||
objects = []
|
||||
def effective_layout_name(knowledge_base, object)
|
||||
layout_prefix = object.present? ? :category : :homepage
|
||||
|
||||
if @object
|
||||
objects += calculate_breadcrumb_to_category(@category || @object&.parent)
|
||||
knowledge_base.send("#{layout_prefix}_layout")
|
||||
end
|
||||
|
||||
last = if @alternative.present? && @alternative.translations.any?
|
||||
Translation.translate(system_locale_via_uri&.locale, 'Alternative translations')
|
||||
else
|
||||
@object
|
||||
end
|
||||
|
||||
objects << last if last.present?
|
||||
|
||||
return if objects.empty?
|
||||
|
||||
render 'knowledge_base/public/breadcrumb',
|
||||
{
|
||||
objects: objects,
|
||||
knowledge_base: @knowledge_base
|
||||
}
|
||||
end
|
||||
|
||||
def calculate_breadcrumb_to_category(category)
|
||||
output = [category]
|
||||
|
||||
parent = category
|
||||
while (parent = find_category(parent&.parent_id))
|
||||
output << parent
|
||||
end
|
||||
|
||||
output.compact.reverse
|
||||
end
|
||||
|
||||
def visibility_note(object)
|
||||
return if !current_user&.permissions?('knowledge_base.editor')
|
||||
|
||||
text = visibility_text(object)
|
||||
|
||||
return if text.nil?
|
||||
|
||||
render 'knowledge_base/public/visibility_note', text: text
|
||||
end
|
||||
|
||||
def visibility_text(object)
|
||||
case object
|
||||
when CanBePublished
|
||||
visiblity_text_can_be_published(object)
|
||||
when KnowledgeBase::Category
|
||||
visiblity_text_category(object)
|
||||
end
|
||||
end
|
||||
|
||||
def visiblity_text_can_be_published(object)
|
||||
case object.can_be_published_aasm.current_state
|
||||
when :internal
|
||||
'internal'
|
||||
when :archived
|
||||
'archived'
|
||||
when :draft
|
||||
'not published'
|
||||
end
|
||||
end
|
||||
|
||||
def visiblity_text_category(object)
|
||||
return if object.public_content?
|
||||
|
||||
if object.self_with_children_answers.only_internal.any?
|
||||
'hidden, visible only internally'
|
||||
else
|
||||
'hidden, no published answers'
|
||||
end
|
||||
end
|
||||
|
||||
def breadcrumb_path_for(object, locale = params.fetch(:locale))
|
||||
case object
|
||||
when KnowledgeBase
|
||||
help_root_path(locale: locale)
|
||||
when KnowledgeBase::Category
|
||||
help_category_path(object.translation, locale: locale)
|
||||
when KnowledgeBase::Answer
|
||||
help_answer_path(object.category.translation, object.translation, locale: locale)
|
||||
end
|
||||
end
|
||||
|
||||
def effective_layout_name
|
||||
layout_prefix = @object.present? ? :category : :homepage
|
||||
|
||||
@knowledge_base.send("#{layout_prefix}_layout")
|
||||
end
|
||||
|
||||
def custom_path_if_needed(path, knowledge_base = @knowledge_base)
|
||||
def custom_path_if_needed(path, knowledge_base)
|
||||
return path if knowledge_base.custom_address_matches? request
|
||||
|
||||
prefix = knowledge_base.custom_address_uri&.path
|
||||
|
@ -117,43 +31,6 @@ module KnowledgeBaseHelper
|
|||
"edit #{suffix}"
|
||||
end
|
||||
|
||||
def kb_top_bar_tag(object)
|
||||
case object
|
||||
when KnowledgeBase::Answer
|
||||
object.can_be_published_aasm.current_state
|
||||
when KnowledgeBase::Category
|
||||
kb_locale = object&.translation&.kb_locale
|
||||
object.public_content?(kb_locale) ? 'Visible' : 'Invisible'
|
||||
when KnowledgeBase
|
||||
'Published'
|
||||
end
|
||||
end
|
||||
|
||||
def kb_top_bar_color(object)
|
||||
case object
|
||||
when KnowledgeBase::Answer
|
||||
kb_answer_top_bar_color(object)
|
||||
when KnowledgeBase::Category
|
||||
kb_locale = object&.translation&.kb_locale
|
||||
object.public_content?(kb_locale) ? 'green' : 'yellow'
|
||||
when KnowledgeBase
|
||||
'green'
|
||||
end
|
||||
end
|
||||
|
||||
def kb_answer_top_bar_color(answer)
|
||||
case answer.can_be_published_aasm.current_state
|
||||
when :draft
|
||||
'yellow'
|
||||
when :internal
|
||||
'blue'
|
||||
when :published
|
||||
'green'
|
||||
when :archived
|
||||
'grey'
|
||||
end
|
||||
end
|
||||
|
||||
def build_kb_link(object)
|
||||
locale = params.fetch(:locale, object.translation.kb_locale)
|
||||
|
||||
|
@ -177,47 +54,4 @@ module KnowledgeBaseHelper
|
|||
.build(host: host, scheme: scheme, port: port, fragment: path)
|
||||
.to_s
|
||||
end
|
||||
|
||||
def kb_public_page_title
|
||||
title = @knowledge_base.translation.title
|
||||
|
||||
if @page_title_error
|
||||
suffix = case @page_title_error
|
||||
when :not_found
|
||||
'Not Found'
|
||||
when :alternatives
|
||||
'Alternative Translations'
|
||||
end
|
||||
|
||||
title + " - #{zt(suffix)}"
|
||||
elsif @object
|
||||
title + " - #{@object.translation.title}"
|
||||
else
|
||||
title
|
||||
end
|
||||
end
|
||||
|
||||
def prepare_rich_text_links(input)
|
||||
scrubber = Loofah::Scrubber.new do |node|
|
||||
next if node.name != 'a'
|
||||
next if !node.key? 'data-target-type'
|
||||
|
||||
case node['data-target-type']
|
||||
when 'knowledge-base-answer'
|
||||
if (translation = KnowledgeBase::Answer::Translation.find_by(id: node['data-target-id']))
|
||||
path = help_answer_path(translation.answer.category.translation_preferred(translation.kb_locale),
|
||||
translation,
|
||||
locale: translation.kb_locale.system_locale.locale)
|
||||
|
||||
node['href'] = custom_path_if_needed path
|
||||
else
|
||||
node['href'] = '#'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parsed = Loofah.scrub_fragment(input, scrubber).to_s.html_safe # rubocop:disable Rails/OutputSafety
|
||||
|
||||
parsed
|
||||
end
|
||||
end
|
||||
|
|
21
app/helpers/knowledge_base_public_page_title_helper.rb
Normal file
21
app/helpers/knowledge_base_public_page_title_helper.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
module KnowledgeBasePublicPageTitleHelper
|
||||
def kb_public_page_title(leading, trailing, exception)
|
||||
[
|
||||
leading&.translation&.title,
|
||||
kb_public_page_title_suffix(trailing, exception)
|
||||
].compact.join(' - ')
|
||||
end
|
||||
|
||||
def kb_public_page_title_suffix(item, exception)
|
||||
return item&.translation&.title if exception.blank?
|
||||
|
||||
suffix = case exception
|
||||
when :not_found
|
||||
'Not Found'
|
||||
when :alternatives
|
||||
'Alternative Translations'
|
||||
end
|
||||
|
||||
zt(suffix)
|
||||
end
|
||||
end
|
25
app/helpers/knowledge_base_rich_text_helper.rb
Normal file
25
app/helpers/knowledge_base_rich_text_helper.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
module KnowledgeBaseRichTextHelper
|
||||
def prepare_rich_text_links(input)
|
||||
scrubber = Loofah::Scrubber.new do |node|
|
||||
next if node.name != 'a'
|
||||
next if !node.key? 'data-target-type'
|
||||
|
||||
case node['data-target-type']
|
||||
when 'knowledge-base-answer'
|
||||
if (translation = KnowledgeBase::Answer::Translation.find_by(id: node['data-target-id']))
|
||||
path = help_answer_path(translation.answer.category.translation_preferred(translation.kb_locale),
|
||||
translation,
|
||||
locale: translation.kb_locale.system_locale.locale)
|
||||
|
||||
node['href'] = custom_path_if_needed path, translation.kb_locale.knowledge_base
|
||||
else
|
||||
node['href'] = '#'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parsed = Loofah.scrub_fragment(input, scrubber).to_s.html_safe # rubocop:disable Rails/OutputSafety
|
||||
|
||||
parsed
|
||||
end
|
||||
end
|
38
app/helpers/knowledge_base_top_bar_helper.rb
Normal file
38
app/helpers/knowledge_base_top_bar_helper.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
module KnowledgeBaseTopBarHelper
|
||||
def kb_top_bar_color(object)
|
||||
case object
|
||||
when KnowledgeBase::Answer
|
||||
kb_answer_top_bar_color(object)
|
||||
when KnowledgeBase::Category
|
||||
kb_locale = object&.translation&.kb_locale
|
||||
object.public_content?(kb_locale) ? 'green' : 'yellow'
|
||||
when KnowledgeBase
|
||||
'green'
|
||||
end
|
||||
end
|
||||
|
||||
def kb_answer_top_bar_color(answer)
|
||||
case answer.can_be_published_aasm.current_state
|
||||
when :draft
|
||||
'yellow'
|
||||
when :internal
|
||||
'blue'
|
||||
when :published
|
||||
'green'
|
||||
when :archived
|
||||
'grey'
|
||||
end
|
||||
end
|
||||
|
||||
def kb_top_bar_tag(object)
|
||||
case object
|
||||
when KnowledgeBase::Answer
|
||||
object.can_be_published_aasm.current_state
|
||||
when KnowledgeBase::Category
|
||||
kb_locale = object&.translation&.kb_locale
|
||||
object.public_content?(kb_locale) ? 'Visible' : 'Invisible'
|
||||
when KnowledgeBase
|
||||
'Published'
|
||||
end
|
||||
end
|
||||
end
|
41
app/helpers/knowledge_base_visibility_note_helper.rb
Normal file
41
app/helpers/knowledge_base_visibility_note_helper.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
module KnowledgeBaseVisibilityNoteHelper
|
||||
def visibility_note(object)
|
||||
return if !current_user&.permissions?('knowledge_base.editor')
|
||||
|
||||
text = visibility_text(object)
|
||||
|
||||
return if text.nil?
|
||||
|
||||
render 'knowledge_base/public/visibility_note', text: text
|
||||
end
|
||||
|
||||
def visibility_text(object)
|
||||
case object
|
||||
when CanBePublished
|
||||
visiblity_text_can_be_published(object)
|
||||
when KnowledgeBase::Category
|
||||
visiblity_text_category(object)
|
||||
end
|
||||
end
|
||||
|
||||
def visiblity_text_can_be_published(object)
|
||||
case object.can_be_published_aasm.current_state
|
||||
when :internal
|
||||
'internal'
|
||||
when :archived
|
||||
'archived'
|
||||
when :draft
|
||||
'not published'
|
||||
end
|
||||
end
|
||||
|
||||
def visiblity_text_category(object)
|
||||
return if object.public_content?
|
||||
|
||||
if object.self_with_children_answers.only_internal.any?
|
||||
'hidden, visible only internally'
|
||||
else
|
||||
'hidden, no published answers'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -18,6 +18,9 @@ class KnowledgeBase::Answer < ApplicationModel
|
|||
|
||||
validates :category, presence: true
|
||||
|
||||
# provide consistent naming with KB category
|
||||
alias_attribute :parent, :category
|
||||
|
||||
alias assets_essential assets
|
||||
|
||||
def attributes_with_association_ids
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<nav class="breadcrumbs">
|
||||
<div class="container">
|
||||
<% ([knowledge_base] + objects).each do |object| %>
|
||||
<%= link_to custom_path_if_needed(breadcrumb_path_for(object)), class: :breadcrumb do %>
|
||||
<%= link_to custom_path_if_needed(breadcrumb_path_for(object), knowledge_base), class: :breadcrumb do %>
|
||||
<%= icon_for_object(object, knowledge_base.iconset) %>
|
||||
|
||||
<span>
|
||||
<%= object.translation.title %>
|
||||
<%= breadcrumb_text_for(object) %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<main class="main main--article"
|
||||
data-base-path='<%= custom_path_if_needed help_answer_path(@category, @object, locale: '{locale}') %>'
|
||||
data-base-path='<%= custom_path_if_needed help_answer_path(@category, @object, locale: '{locale}'), @knowledge_base %>'
|
||||
data-available-locales='<%= @object_locales.map(&:locale).join(',') %>'>
|
||||
<article class="article">
|
||||
<div class="container">
|
||||
|
@ -16,7 +16,7 @@ data-available-locales='<%= @object_locales.map(&:locale).join(',') %>'>
|
|||
<%= icon 'paperclip' %>
|
||||
<div class="attachments-title"><%= zt('Attached Files') %></div>
|
||||
<% attachments.each do |attachment| %>
|
||||
<%= link_to custom_path_if_needed(attachment_path(attachment)), class: 'attachment', download: true do %>
|
||||
<%= link_to custom_path_if_needed(attachment_path(attachment), @knowledge_base), class: 'attachment', download: true do %>
|
||||
<span class="attachment-name u-highlight"><%= attachment.filename %></span>
|
||||
<div class="attachment-size">404kb</div>
|
||||
<% end %>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<%= link_to custom_path_if_needed help_answer_path(answer.category.translation, answer.translation, locale: params[:locale]) do %>
|
||||
<%= link_to custom_path_if_needed help_answer_path(answer.category.translation, answer.translation, locale: params[:locale]), @knowledge_base do %>
|
||||
<span class="section-inner">
|
||||
<%= icon('knowledge-base-answer') %>
|
||||
<%= answer.translation.title %> <%= visibility_note(answer) %>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<li class="section <%= visibility_class_name(category) %>">
|
||||
<%= link_to custom_path_if_needed help_category_path(category.translation, locale: params[:locale]) do %>
|
||||
<%= link_to custom_path_if_needed help_category_path(category.translation, locale: params[:locale]), @knowledge_base do %>
|
||||
<span class="section-inner">
|
||||
<%= icon(category.category_icon, knowledge_base.iconset) %>
|
||||
<span><%= category.translation.title %></span>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<main class="main main--categories"
|
||||
<% if @object %>
|
||||
data-base-path='<%= custom_path_if_needed help_category_path(@object, locale: '{locale}') %>'
|
||||
data-base-path='<%= custom_path_if_needed help_category_path(@object, locale: '{locale}'), @knowledge_base %>'
|
||||
data-available-locales='<%= @object_locales.map(&:locale).join(',') %>'
|
||||
<% end %>>
|
||||
<div class="container">
|
||||
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
<% else %>
|
||||
<% if @categories&.present? %>
|
||||
<ul class="sections sections--<%= effective_layout_name %>" data-less-than-four="<%= @categories.length < 4 %>">
|
||||
<ul class="sections sections--<%= effective_layout_name(@knowledge_base, @object) %>" data-less-than-four="<%= @categories.length < 4 %>">
|
||||
<% @categories.each do |category| %>
|
||||
<%= render 'category', { category: category, knowledge_base: @knowledge_base } %>
|
||||
<% end %>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<h1><%= zt('Page not found') %></h1>
|
||||
<p>
|
||||
<%= zt('The page you were looking for does not exist.') %>
|
||||
<%= link_to zt('Click here'), custom_path_if_needed(help_root_path(locale: fallback_locale.locale)) %>
|
||||
<%= link_to zt('Click here'), custom_path_if_needed(help_root_path(locale: fallback_locale.locale), @knowledge_base) %>
|
||||
<%= zt('to go to the homepage.') %>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<% @alternative.translations.each do |translation| %>
|
||||
<li>
|
||||
<%= translation.kb_locale.system_locale.name %>:
|
||||
<%= link_to translation.title, custom_path_if_needed(url_for(locale: translation_locale_code(translation))) %>
|
||||
<%= link_to translation.title, custom_path_if_needed(url_for(locale: translation_locale_code(translation)), @knowledge_base) %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
data-id='<%= @knowledge_base.id %>'
|
||||
data-iconset='<%= @knowledge_base.iconset %>'
|
||||
data-available-locales='<%= all_locales.map(&:locale).join(',') %>'
|
||||
data-base-path='<%= custom_path_if_needed help_root_path(locale: '{locale}') %>'
|
||||
data-base-path='<%= custom_path_if_needed help_root_path(locale: '{locale}'), @knowledge_base %>'
|
||||
data-primary-locale="<%= (filter_primary_kb_locale || all_locales.first)&.locale %>">
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title><%= kb_public_page_title %></title>
|
||||
<title><%= kb_public_page_title(@knowledge_base, @object, @page_title_error) %></title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
|
||||
<%= stylesheet_link_tag "knowledge_base.css", :media => 'all' %>
|
||||
<%= render 'knowledge_base/public/inline_stylesheet', knowledge_base: @knowledge_base %>
|
||||
|
@ -18,7 +18,7 @@
|
|||
<header class="header js-header">
|
||||
<div class="container">
|
||||
<h1 class="logo">
|
||||
<%= link_to custom_path_if_needed(help_root_path(locale: params[:locale])) do %>
|
||||
<%= link_to custom_path_if_needed(help_root_path(locale: params[:locale]), @knowledge_base) do %>
|
||||
<img src="/assets/images/<%= Setting.get('product_logo') %>">
|
||||
<% end %>
|
||||
</h1>
|
||||
|
@ -39,7 +39,7 @@
|
|||
</div>
|
||||
</header>
|
||||
|
||||
<%= render_breadcrumb_if_needed %>
|
||||
<%= render_breadcrumb_if_needed(@knowledge_base, @object, @alternative) %>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
|||
<ul class="dropdown-menu dropdown-menu-right dropdown-menu-up" role="menu">
|
||||
<% @object_locales&.each do |locale| %>
|
||||
<li class="<%= 'is-selected' if locale.name == system_locale_via_uri.name %>">
|
||||
<%= link_to custom_path_if_needed(url_for(locale: locale.locale)), hreflang: locale.locale do %>
|
||||
<%= link_to custom_path_if_needed(url_for(locale: locale.locale), @knowledge_base), hreflang: locale.locale do %>
|
||||
<%= icon 'checkmark' %>
|
||||
<%= locale.name %>
|
||||
<% end %>
|
||||
|
|
|
@ -16,7 +16,7 @@ FactoryBot.define do
|
|||
end
|
||||
|
||||
if kb.kb_locales.blank?
|
||||
kb.kb_locales << build(:knowledge_base_locale, knowledge_base: kb)
|
||||
kb.kb_locales << build(:knowledge_base_locale, knowledge_base: kb, primary: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
FactoryBot.define do
|
||||
factory 'knowledge_base/answer', aliases: %i[knowledge_base_answer] do
|
||||
category { create(:knowledge_base_category) }
|
||||
|
||||
before(:create) do |answer|
|
||||
next if answer.translations.present?
|
||||
|
||||
answer.translations << build('knowledge_base/answer/translation', answer: answer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,12 +2,25 @@ FactoryBot.define do
|
|||
factory 'knowledge_base/answer/translation', aliases: %i[knowledge_base_answer_translation] do
|
||||
answer { nil }
|
||||
kb_locale { nil }
|
||||
title { Faker::Appliance.equipment }
|
||||
sequence(:title) { |n| "#{Faker::Appliance.equipment} ##{n}" }
|
||||
content { build(:knowledge_base_answer_translation_content) }
|
||||
|
||||
before(:create) do |translation|
|
||||
if translation.answer.nil? && translation.kb_locale.nil?
|
||||
translation.answer = create(:knowledge_base_answer)
|
||||
before(:create) do |translation, _context|
|
||||
if translation.answer.nil?
|
||||
build(:knowledge_base_answer, translations: [translation])
|
||||
end
|
||||
|
||||
if translation.kb_locale.nil?
|
||||
translation.kb_locale = translation.answer.category.knowledge_base.kb_locales.first
|
||||
end
|
||||
end
|
||||
|
||||
after(:build) do |translation, _context|
|
||||
if translation.answer.nil?
|
||||
build(:knowledge_base_answer, translations: [translation])
|
||||
end
|
||||
|
||||
if translation.kb_locale.nil?
|
||||
translation.kb_locale = translation.answer.category.knowledge_base.kb_locales.first
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ FactoryBot.define do
|
|||
|
||||
before(:create) do |content|
|
||||
if content.translation.nil?
|
||||
content.translation = create(:knowledge_base_answer_translation)
|
||||
create(:knowledge_base_answer_translation, content: content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,6 +2,12 @@ FactoryBot.define do
|
|||
factory 'knowledge_base/category', aliases: %i[knowledge_base_category] do
|
||||
knowledge_base { parent&.knowledge_base || create(:knowledge_base) }
|
||||
category_icon { 'f04b' }
|
||||
|
||||
before(:create) do |category|
|
||||
next if category.translations.present?
|
||||
|
||||
category.translations << create('knowledge_base/category/translation', category: category)
|
||||
end
|
||||
end
|
||||
|
||||
factory 'kb_category_with_tree', parent: 'knowledge_base/category' do
|
||||
|
|
|
@ -1,14 +1,30 @@
|
|||
FactoryBot.define do
|
||||
factory 'knowledge_base/category/translation', aliases: %i[knowledge_base_category_translation] do
|
||||
transient do
|
||||
knowledge_base { nil }
|
||||
parent_category { nil }
|
||||
end
|
||||
|
||||
category { nil }
|
||||
kb_locale { nil }
|
||||
title { Faker::Appliance.brand }
|
||||
sequence(:title) { |n| "#{Faker::Appliance.brand} ##{n}" }
|
||||
|
||||
before(:create) do |translation|
|
||||
if translation.category.nil? && translation.kb_locale.nil?
|
||||
translation.category = create(:knowledge_base_category)
|
||||
translation.kb_locale = translation.category.knowledge_base.kb_locales.first
|
||||
end
|
||||
before(:create) do |translation, context|
|
||||
if translation.category.nil?
|
||||
attrs = if context.parent_category
|
||||
{ parent: context.parent_category }
|
||||
elsif context.knowledge_base
|
||||
{ knowledge_base: context.knowledge_base }
|
||||
else
|
||||
{}
|
||||
end
|
||||
|
||||
attrs[:translations] = [translation]
|
||||
|
||||
build(:knowledge_base_category, attrs)
|
||||
end
|
||||
|
||||
translation.kb_locale = translation.category.knowledge_base.kb_locales.first if translation.kb_locale.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,5 +3,6 @@ FactoryBot.define do
|
|||
knowledge_base { kb_locale.knowledge_base }
|
||||
kb_locale { nil }
|
||||
title { Faker::Company.name }
|
||||
footer_note { 'footer' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
require 'rails_helper'
|
||||
require 'models/contexts/factory_context'
|
||||
|
||||
RSpec.describe KnowledgeBase::Answer::Translation::Content, type: :model do
|
||||
RSpec.describe KnowledgeBase::Answer::Translation::Content, type: :model, current_user_id: 1 do
|
||||
subject { create(:knowledge_base_answer_translation_content) }
|
||||
|
||||
before { UserInfo.current_user_id = 1 }
|
||||
|
||||
include_context 'factory'
|
||||
|
||||
it { is_expected.to have_one(:translation) }
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
require 'rails_helper'
|
||||
require 'models/contexts/factory_context'
|
||||
|
||||
RSpec.describe KnowledgeBase::Answer::Translation, type: :model do
|
||||
RSpec.describe KnowledgeBase::Answer::Translation, type: :model, current_user_id: 1 do
|
||||
subject { create(:knowledge_base_answer_translation) }
|
||||
|
||||
before { UserInfo.current_user_id = 1 }
|
||||
|
||||
include_context 'factory'
|
||||
|
||||
it { is_expected.to validate_presence_of(:title) }
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'rails_helper'
|
|||
require 'models/concerns/checks_kb_client_notification_examples'
|
||||
require 'models/contexts/factory_context'
|
||||
|
||||
RSpec.describe KnowledgeBase::Answer, type: :model do
|
||||
RSpec.describe KnowledgeBase::Answer, type: :model, current_user_id: 1 do
|
||||
subject!(:kb_answer) { create(:knowledge_base_answer) }
|
||||
|
||||
include_context 'factory'
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'rails_helper'
|
|||
require 'models/concerns/checks_kb_client_notification_examples'
|
||||
require 'models/contexts/factory_context'
|
||||
|
||||
RSpec.describe KnowledgeBase::Category, type: :model do
|
||||
RSpec.describe KnowledgeBase::Category, type: :model, current_user_id: 1 do
|
||||
subject(:kb_category) { create(:knowledge_base_category) }
|
||||
|
||||
include_context 'factory'
|
||||
|
|
|
@ -35,3 +35,22 @@ end
|
|||
Capybara.add_selector(:table_row) do
|
||||
css { |id| %(tr[data-id='#{id}']) }
|
||||
end
|
||||
|
||||
Capybara.add_selector(:link_containing) do
|
||||
xpath { |text| ".//a//*[text()[contains(.,\"#{text}\")]]" }
|
||||
end
|
||||
|
||||
# Knowledge Base
|
||||
Capybara.add_selector(:knowledge_base_editor_bar) do
|
||||
css { '.topbar' }
|
||||
end
|
||||
|
||||
Capybara.add_selector(:knowledge_base_language_banner) do
|
||||
css { '.language-banner' }
|
||||
end
|
||||
|
||||
# don't use "knowledge_base" prefix because breadcrumbs
|
||||
# could be available in other contexts (in the future)
|
||||
Capybara.add_selector(:breadcrumb) do
|
||||
css { '.breadcrumbs .breadcrumb span' }
|
||||
end
|
||||
|
|
35
spec/support/knowledge_base_contexts.rb
Normal file
35
spec/support/knowledge_base_contexts.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
RSpec.shared_context 'Knowledge Base users' do
|
||||
let(:admin_user) { create :admin_user }
|
||||
let(:agent_user) { create :agent_user }
|
||||
let(:customer_user) { create :customer_user }
|
||||
end
|
||||
|
||||
RSpec.shared_context 'basic Knowledge Base', current_user_id: 1 do
|
||||
let :knowledge_base do
|
||||
create(:knowledge_base)
|
||||
end
|
||||
|
||||
let :primary_locale do
|
||||
knowledge_base.translation_primary.kb_locale
|
||||
end
|
||||
|
||||
let :alternative_locale do
|
||||
create(:knowledge_base_locale, knowledge_base: knowledge_base, system_locale: Locale.find_by(locale: 'lt'))
|
||||
end
|
||||
|
||||
let :category do
|
||||
create(:knowledge_base_category, knowledge_base: knowledge_base)
|
||||
end
|
||||
|
||||
let :answer do
|
||||
create(:knowledge_base_answer, category: category)
|
||||
end
|
||||
|
||||
let :published_answer do
|
||||
create(:knowledge_base_answer, category: category, published_at: 1.week.ago)
|
||||
end
|
||||
|
||||
let :internal_answer do
|
||||
create(:knowledge_base_answer, category: category, internal_at: 1.week.ago)
|
||||
end
|
||||
end
|
|
@ -1,37 +1,19 @@
|
|||
# This module registers a before and after each hook callback that
|
||||
# This file registers a before and after each hook callback that
|
||||
# resets the stored current_user_id in the UserInfo which will otherwise
|
||||
# persists across multiple examples.
|
||||
# This can lead to issues where actions were performed by a user created
|
||||
# via a FactoryBot factory which will get removed after the example is
|
||||
# completed. The UserInfo.current_user_id will persist which leads to e.g.
|
||||
# DB ForeignKey violation errors.
|
||||
module ZammadSpecSupportUserInfo
|
||||
|
||||
def self.included(base)
|
||||
|
||||
# Execute in RSpec class context
|
||||
base.class_exec do
|
||||
|
||||
before(:each) do |_example|
|
||||
UserInfo.current_user_id = nil
|
||||
end
|
||||
|
||||
after(:each) do |_example|
|
||||
UserInfo.current_user_id = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# If a `:current_user_id` metadata argument is set the initial value for
|
||||
# UserInfo.current_user_id will be set to the arguments given value
|
||||
RSpec.configure do |config|
|
||||
config.include ZammadSpecSupportUserInfo
|
||||
|
||||
config.around(:each, :current_user_id) do |example|
|
||||
config.before(:each) do |example|
|
||||
UserInfo.current_user_id = example.metadata[:current_user_id]
|
||||
begin
|
||||
example.run
|
||||
ensure
|
||||
end
|
||||
|
||||
config.after(:each) do |_example|
|
||||
UserInfo.current_user_id = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
42
spec/system/knowledge_base_public/editor_spec.rb
Normal file
42
spec/system/knowledge_base_public/editor_spec.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Public Knowledge Base for editor', type: :system, authenticated: true do
|
||||
include_context 'basic Knowledge Base'
|
||||
|
||||
before do
|
||||
published_answer && answer && internal_answer
|
||||
end
|
||||
|
||||
context 'homepage' do
|
||||
before { visit help_no_locale_path }
|
||||
|
||||
it { expect(page).to have_selector(:knowledge_base_editor_bar) }
|
||||
|
||||
it 'expect to have edit button' do
|
||||
button = find '.topbar-btn'
|
||||
expect(button['href']).to match(/edit$/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'category' do
|
||||
before { visit help_category_path(primary_locale.system_locale.locale, category) }
|
||||
|
||||
it 'shows published answer' do
|
||||
within '.main' do
|
||||
expect(page).to have_selector(:link_containing, published_answer.translation.title)
|
||||
end
|
||||
end
|
||||
|
||||
it 'shows draft answer' do
|
||||
within '.main' do
|
||||
expect(page).to have_selector(:link_containing, answer.translation.title)
|
||||
end
|
||||
end
|
||||
|
||||
it 'shows internal answer' do
|
||||
within '.main' do
|
||||
expect(page).to have_selector(:link_containing, internal_answer.translation.title)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
110
spec/system/knowledge_base_public/guest_spec.rb
Normal file
110
spec/system/knowledge_base_public/guest_spec.rb
Normal file
|
@ -0,0 +1,110 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Public Knowledge Base for guest', type: :system, authenticated: false do
|
||||
include_context 'basic Knowledge Base'
|
||||
|
||||
before do
|
||||
published_answer && answer && internal_answer
|
||||
end
|
||||
|
||||
context 'homepage' do
|
||||
before { visit help_no_locale_path }
|
||||
|
||||
it('is redirected to primary locale') { expect(page).to have_current_path help_root_path(primary_locale.system_locale.locale) }
|
||||
|
||||
it { expect(page).not_to have_selector(:breadcrumb) }
|
||||
it { expect(page).not_to have_selector(:knowledge_base_editor_bar) }
|
||||
|
||||
it 'shows category' do
|
||||
within '.main' do
|
||||
expect(page).to have_selector(:link_containing, published_answer.category.translation.title)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not show answer' do
|
||||
within '.main' do
|
||||
expect(page).not_to have_selector(:link_containing, published_answer.translation.title)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'category' do
|
||||
before { visit help_category_path(primary_locale.system_locale.locale, category) }
|
||||
|
||||
it { expect(page).to have_selector(:breadcrumb) }
|
||||
|
||||
it 'shows published answer' do
|
||||
within '.main' do
|
||||
expect(page).to have_selector(:link_containing, published_answer.translation.title)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not show draft answer' do
|
||||
within '.main' do
|
||||
expect(page).not_to have_selector(:link_containing, answer.translation.title)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not show internal answer' do
|
||||
within '.main' do
|
||||
expect(page).not_to have_selector(:link_containing, internal_answer.translation.title)
|
||||
end
|
||||
end
|
||||
|
||||
context 'breadcrumb' do
|
||||
it { expect(page).to have_selector(:breadcrumb, count: 2) }
|
||||
it { expect(page.all(:breadcrumb)[0]).to have_text(knowledge_base.translation.title) }
|
||||
it { expect(page.all(:breadcrumb)[1]).to have_text(category.translation.title) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'answer' do
|
||||
before { visit help_answer_path(primary_locale.system_locale.locale, category, published_answer) }
|
||||
|
||||
context 'breadcrumb' do
|
||||
it { expect(page).to have_selector(:breadcrumb, count: 3) }
|
||||
it { expect(page.all(:breadcrumb)[0]).to have_text(knowledge_base.translation.title) }
|
||||
it { expect(page.all(:breadcrumb)[1]).to have_text(category.translation.title) }
|
||||
it { expect(page.all(:breadcrumb)[2]).to have_text(published_answer.translation.title) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'wrong locale' do
|
||||
before { visit help_root_path(alternative_locale.system_locale.locale) }
|
||||
|
||||
it { expect(page).to have_selector(:knowledge_base_language_banner) }
|
||||
|
||||
context 'switch to correct locale after clicking on language banner' do
|
||||
before do
|
||||
within '.language-banner' do
|
||||
click_on 'activate'
|
||||
end
|
||||
end
|
||||
|
||||
it { expect(page).not_to have_selector(:knowledge_base_language_banner) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'offer in another locale' do
|
||||
before do
|
||||
create(:knowledge_base_translation, kb_locale: alternative_locale)
|
||||
visit help_answer_path(alternative_locale.system_locale.locale, category, published_answer)
|
||||
end
|
||||
|
||||
it { expect(page).to have_text(published_answer.translation_primary.title) }
|
||||
it { expect(page).to have_text('only available in these languages') }
|
||||
it { expect(page).not_to have_selector('h1', text: published_answer.translation_primary.title) }
|
||||
|
||||
context 'follow primary locale' do
|
||||
before { click_on published_answer.translation_primary.title }
|
||||
|
||||
it { expect(page).to have_selector('h1', text: published_answer.translation_primary.title) }
|
||||
end
|
||||
end
|
||||
|
||||
context '404' do
|
||||
before { visit help_answer_path(primary_locale.system_locale.locale, category, 12_345) }
|
||||
|
||||
it { expect(page).to have_text('Page not found') }
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue