diff --git a/app/controllers/my_profile/profile_design_controller.rb b/app/controllers/my_profile/profile_design_controller.rb
index cd4fc38..ad666e2 100644
--- a/app/controllers/my_profile/profile_design_controller.rb
+++ b/app/controllers/my_profile/profile_design_controller.rb
@@ -5,7 +5,7 @@ class ProfileDesignController < BoxOrganizerController
protect 'edit_profile_design', :profile
def available_blocks
- blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock ]
+ blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock ]
# blocks exclusive for organizations
if profile.has_members?
diff --git a/app/controllers/public/profile_search_controller.rb b/app/controllers/public/profile_search_controller.rb
new file mode 100644
index 0000000..a960fa3
--- /dev/null
+++ b/app/controllers/public/profile_search_controller.rb
@@ -0,0 +1,26 @@
+class ProfileSearchController < PublicController
+
+ include SearchHelper
+
+ needs_profile
+ before_filter :check_access_to_profile
+
+ def index
+ @q = params[:q].blank? ? '' : params[:q]
+ @filtered_query = remove_stop_words(@q)
+ if params[:where] == 'environment'
+ redirect_to :controller => 'search', :query => @q
+ else
+ @results = profile.articles.published.find_by_contents(@filtered_query).paginate(:per_page => 10, :page => params[:page])
+ end
+ end
+
+ protected
+
+ def check_access_to_profile
+ unless profile.display_info_to?(user)
+ redirect_to :controller => 'profile', :action => 'index'
+ end
+ end
+
+end
diff --git a/app/helpers/folder_helper.rb b/app/helpers/folder_helper.rb
index abeff3c..3b9a672 100644
--- a/app/helpers/folder_helper.rb
+++ b/app/helpers/folder_helper.rb
@@ -44,7 +44,11 @@ module FolderHelper
if (icon =~ /\//)
icon
else
- 'icon icon-' + icon
+ klasses = 'icon icon-' + icon
+ if article.kind_of?(UploadedFile)
+ klasses += ' icon-upload-file'
+ end
+ klasses
end
end
diff --git a/app/helpers/forms_helper.rb b/app/helpers/forms_helper.rb
index d636aef..6b3511f 100644
--- a/app/helpers/forms_helper.rb
+++ b/app/helpers/forms_helper.rb
@@ -41,8 +41,7 @@ module FormsHelper
the_class << ' ' << html_options[:class]
end
- # FIXME: should be in stylesheet
- bt_submit = submit_tag(label, html_options.merge(:style => 'height:28px; cursor:pointer', :class => the_class))
+ bt_submit = submit_tag(label, html_options.merge(:class => the_class))
bt_submit + bt_cancel
end
diff --git a/app/models/article.rb b/app/models/article.rb
index 43ffc10..318bf7e 100644
--- a/app/models/article.rb
+++ b/app/models/article.rb
@@ -473,6 +473,10 @@ class Article < ActiveRecord::Base
abstract.blank? ? first_paragraph : abstract
end
+ def short_lead
+ truncate sanitize_html(self.lead), 170, '...'
+ end
+
def creator
creator_id = versions[0][:last_changed_by_id]
creator_id && Profile.find(creator_id)
@@ -493,4 +497,9 @@ class Article < ActiveRecord::Base
tag_name.gsub(/[<>]/, '')
end
+ def sanitize_html(text)
+ sanitizer = HTML::FullSanitizer.new
+ sanitizer.sanitize(text)
+ end
+
end
diff --git a/app/models/profile_search_block.rb b/app/models/profile_search_block.rb
new file mode 100644
index 0000000..eae7518
--- /dev/null
+++ b/app/models/profile_search_block.rb
@@ -0,0 +1,22 @@
+class ProfileSearchBlock < Block
+
+ def self.description
+ _('Display a form to search the profile')
+ end
+
+ def default_title
+ _('Profile search')
+ end
+
+ def content
+ title = self.title
+ lambda do
+ render :file => 'blocks/profile_search', :locals => { :title => title }
+ end
+ end
+
+ def editable?
+ true
+ end
+
+end
diff --git a/app/models/text_article.rb b/app/models/text_article.rb
index 379135f..e07e787 100644
--- a/app/models/text_article.rb
+++ b/app/models/text_article.rb
@@ -4,4 +4,13 @@ class TextArticle < Article
xss_terminate :only => [ :name, :abstract, :body ], :on => 'validation'
include Noosfero::TranslatableContent
+
+ def self.icon_name(article = nil)
+ if article && !article.parent.nil? && article.parent.kind_of?(Blog)
+ Blog.icon_name
+ else
+ Article.icon_name
+ end
+ end
+
end
diff --git a/app/models/uploaded_file.rb b/app/models/uploaded_file.rb
index 45c3dcc..ef23258 100644
--- a/app/models/uploaded_file.rb
+++ b/app/models/uploaded_file.rb
@@ -47,8 +47,8 @@ class UploadedFile < Article
delay_attachment_fu_thumbnails
def self.icon_name(article = nil)
- if article && article.image?
- article.public_filename(:icon)
+ if article
+ article.image? ? article.public_filename(:icon) : article.mime_type.gsub(/[\/+.]/, '-')
else
'upload-file'
end
diff --git a/app/views/blocks/profile_search.rhtml b/app/views/blocks/profile_search.rhtml
new file mode 100644
index 0000000..d597920
--- /dev/null
+++ b/app/views/blocks/profile_search.rhtml
@@ -0,0 +1,3 @@
+<%= block_title(title) %>
+
+<%= render :partial => 'shared/profile_search_form' %>
diff --git a/app/views/profile/index.rhtml b/app/views/profile/index.rhtml
index 3560123..be3f86d 100644
--- a/app/views/profile/index.rhtml
+++ b/app/views/profile/index.rhtml
@@ -10,6 +10,9 @@
<%= profile.description %>
<% end %>
+
+ <%= render :partial => 'shared/profile_search_form' %>
+
<% end %>
diff --git a/app/views/profile_search/_article.rhtml b/app/views/profile_search/_article.rhtml
new file mode 100644
index 0000000..45fea5c
--- /dev/null
+++ b/app/views/profile_search/_article.rhtml
@@ -0,0 +1,5 @@
+
+ <%= link_to article.title, article.view_url, :class => 'result-title ' + icon_for_article(article) %>
+ <%= link_to article.short_lead, article.url, {:class => 'article-details'} %>
+ <%= link_to url_for(article.url), article.url, :class => 'article-url' %>
+
diff --git a/app/views/profile_search/_folder.rhtml b/app/views/profile_search/_folder.rhtml
new file mode 100644
index 0000000..c9bfd26
--- /dev/null
+++ b/app/views/profile_search/_folder.rhtml
@@ -0,0 +1,5 @@
+
+ <%= link_to article.title, article.view_url, :class => 'result-title ' + icon_for_article(article) %>
+ <%= link_to article.body.to_s, article.url, {:class => 'article-details'} %>
+ <%= link_to url_for(article.url), article.url, :class => 'article-url' %>
+
diff --git a/app/views/profile_search/_uploaded_file.rhtml b/app/views/profile_search/_uploaded_file.rhtml
new file mode 100644
index 0000000..9e7ae4b
--- /dev/null
+++ b/app/views/profile_search/_uploaded_file.rhtml
@@ -0,0 +1,11 @@
+<% if article.image? %>
+
+ <%= link_to image_tag(article.public_filename(:thumb), :alt => article.display_title), article.view_url, :class => 'article-details' %>
+
+<% else %>
+
+ <%= link_to article.title, article.view_url, :class => 'result-title ' + icon_for_article(article) %>
+ <%= link_to article.title, article.short_lead, :class => 'article-details' %>
+ <%= link_to url_for(article.url), article.url, :class => 'article-url' %>
+
+<% end %>
diff --git a/app/views/profile_search/index.rhtml b/app/views/profile_search/index.rhtml
new file mode 100644
index 0000000..84ac4fa
--- /dev/null
+++ b/app/views/profile_search/index.rhtml
@@ -0,0 +1,18 @@
+
+
<%= _("Search results on %s's profile") % profile.short_name %>
+
+ <%= render :partial => 'shared/profile_search_form' %>
+
+
+ <%= _("%s results found") % @results.total_entries %>
+
+
+
+ <% @results.sort_by { |r| r.is_image? ? 0 : 1}.each do |result| %>
+ <%= render :partial => partial_for_class(result.class), :locals => { :article => result } %>
+ <% end %>
+
+
+ <%= pagination_links @results %>
+
+
diff --git a/app/views/shared/_profile_search_form.rhtml b/app/views/shared/_profile_search_form.rhtml
new file mode 100644
index 0000000..d7b720e
--- /dev/null
+++ b/app/views/shared/_profile_search_form.rhtml
@@ -0,0 +1,12 @@
+<% form_tag( { :controller => 'profile_search', :profile => profile.identifier}, :method => 'get', :class => 'search_form' ) do %>
+
+
+ <%= text_field_tag 'q', @q, :title => _("Find %s's content") % profile.short_name %>
+
+ <%= submit_button(:search, _('Search')) %>
+
+ <%= labelled_radio_button __('on profile'), 'where', 'profile', true %>
+ <%= labelled_radio_button _('on %s') % environment.name, 'where', 'environment', false %>
+
+
+<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 8410e12..d3e2e44 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -75,6 +75,9 @@ ActionController::Routing::Routes.draw do |map|
map.tag 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format}/
map.tag 'profile/:profile/tags', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format}/
+ # profile search
+ map.profile_search 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format}/
+
# public profile information
map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/
diff --git a/features/profile_search.feature b/features/profile_search.feature
new file mode 100644
index 0000000..bb8fc2a
--- /dev/null
+++ b/features/profile_search.feature
@@ -0,0 +1,66 @@
+Feature: search inside a profile
+ As a noosfero user
+ I want to search
+ In order to find stuff from a profile
+
+ Background:
+ Given the following users
+ | login | name |
+ | joaosilva | Joao Silva |
+ And the following articles
+ | owner | name | body |
+ | joaosilva | bees and butterflies | this is an article about bees and butterflies |
+ | joaosilva | whales and dolphins | this is an article about whales and dolphins |
+
+ Scenario: search on profile
+ Given I go to Joao Silva's profile
+ And I fill in "q" with "bees"
+ And I press "Search"
+ Then I should see "bees and butterflies" within ".main-block"
+ And I should not see "whales and dolphins" within ".main-block"
+
+ Scenario: search for event on profile
+ Given the following events
+ | owner | name | start_date |
+ | joaosilva | Group meeting | 2009-10-01 |
+ | joaosilva | John Doe's birthday | 2009-09-01 |
+ When I go to Joao Silva's profile
+ And I fill in "q" with "birthday"
+ And I press "Search"
+ Then I should see "John Doe's birthday" within ".main-block"
+ And I should not see "Group meeting" within ".main-block"
+
+ Scenario: simple search for event on profile search block
+ Given the following blocks
+ | owner | type |
+ | joaosilva | ProfileSearchBlock |
+ When I go to Joao Silva's profile
+ And I fill in "q" with "bees" within ".profile-search-block"
+ And I press "Search"
+ Then I should see "bees and butterflies" within ".main-block"
+
+ Scenario: not display unpublished articles
+ Given the following articles
+ | owner | name | body | published |
+ | joaosilva | published article | this is a public article | true |
+ | joaosilva | unpublished article | this is a private article | false |
+ And I go to Joao Silva's profile
+ And I fill in "q" with "article"
+ And I press "Search"
+ Then I should see "public article" within ".main-block"
+ And I should not see "private article" within ".main-block"
+
+ Scenario: search on environment
+ Given I go to Joao Silva's profile
+ And I fill in "q" with "bees"
+ And I choose "on Colivre.net"
+ And I press "Search"
+ Then I should be on the search page
+ And I should see "bees and butterflies" within "#search-page"
+
+ Scenario: not display search on private profiles
+ Given the following users
+ | login | name | public_profile |
+ | mariasilva | Maria Silva | false |
+ And I go to /profile/mariasilva/search
+ Then I should see "friends only"
diff --git a/public/designs/icons/tango/style.css b/public/designs/icons/tango/style.css
index 0f5b9d6..c711478 100644
--- a/public/designs/icons/tango/style.css
+++ b/public/designs/icons/tango/style.css
@@ -69,7 +69,19 @@
.icon-newupload-file { background-image: url(Tango/16x16/actions/filesave.png) }
.icon-slideshow { background-image: url(Tango/16x16/mimetypes/x-office-presentation.png) }
.icon-photos { background-image: url(Tango/16x16/devices/camera-photo.png) }
+
.icon-text-html { background-image: url(Tango/16x16/mimetypes/text-html.png) }
+.icon-text-plain { background-image: url(Tango/16x16/mimetypes/text-x-generic.png) }
+.icon-image-svg-xml { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) }
+.icon-application-octet-stream { background-image: url(Tango/16x16/mimetypes/binary.png) }
+.icon-application-x-gzip { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-x-gzip.png) }
+.icon-application-postscript { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-postscript.png) }
+.icon-application-pdf { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-pdf.png) }
+.icon-application-ogg { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-ogg.png) }
+.icon-video-mpeg { background-image: url(Tango/16x16/mimetypes/video-x-generic.png) }
+.icon-application-vnd-oasis-opendocument-text { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.text.png) }
+.icon-application-vnd-oasis-opendocument-spreadsheet { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.spreadsheet.png) }
+.icon-application-vnd-oasis-opendocument-presentation { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.presentation.png) }
.icon-media-pause { background-image: url(Tango/16x16/actions/media-playback-pause.png) }
.icon-media-play { background-image: url(Tango/16x16/actions/media-playback-start.png) }
diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css
index dc0e86f..1b17688 100644
--- a/public/stylesheets/application.css
+++ b/public/stylesheets/application.css
@@ -1567,6 +1567,10 @@ input.button {
input.button {
background-position: 2px 50%;
}
+#content form input.button.submit {
+ height: 28px;
+ cursor: pointer;
+}
.button span {
display: none;
@@ -4372,6 +4376,98 @@ h1#agenda-title {
text-align: left;
}
+/* * * Profile search * * * * * * * */
+
+#public-profile-search,
+#profile-search-results form,
+.profile-search-block form {
+ padding: 10px;
+ margin-bottom: 15px;
+ background-color: #E6E6E6;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+}
+
+#public-profile-search .formfield input {
+ width: 400px;
+}
+
+/* * * Profile Search Results * * * * * * * */
+
+#profile-search-results ul {
+ padding-left: 0px;
+}
+
+#profile-search-results form .formfield input {
+ width: 395px;
+}
+
+#profile-search-results form .search_form .button {
+ margin-top: 5px;
+}
+
+#profile-search-results li {
+ list-style: none;
+ margin-bottom: 20px;
+ clear: left;
+}
+
+#profile-search-results li.result-image {
+ float: left;
+ clear: none;
+ height: 150px;
+ margin-right: 10px;
+ margin-left: 10px;
+}
+
+#profile-search-results .result-title {
+ font-size: 18px;
+}
+
+#profile-search-results p {
+ margin-top: 5px;
+ margin-bottom: 0px;
+}
+
+#profile-search-results .article-details {
+ color: #000;
+ text-decoration: none;
+}
+
+#profile-search-results a.article-url {
+ text-decoration: none;
+ color: #77AA44;
+}
+
+#profile-search-results a.article-url:hover {
+ text-decoration: underline;
+}
+
+#profile-search-results .results-list .icon {
+ background-repeat: no-repeat;
+ background-position: left;
+ padding: 0px 0px 3px 20px;
+ border: none;
+}
+
+#profile-search-results .results-list .icon:hover {
+ background-color: transparent;
+}
+
+#profile-search-results .results-found-message {
+ margin-top: 10px;
+ font-style: italic;
+}
+
+/* * * Profile search block * * * * * * * */
+
+.profile-search-block .formfield input {
+ width: 100%;
+}
+
+.profile-search-block .button.icon-search {
+ display: none;
+}
/* * * Sub-category stuff * * * * * * * */
diff --git a/test/functional/profile_design_controller_test.rb b/test/functional/profile_design_controller_test.rb
index c9ed20a..1d607e3 100644
--- a/test/functional/profile_design_controller_test.rb
+++ b/test/functional/profile_design_controller_test.rb
@@ -5,7 +5,7 @@ class ProfileDesignController; def rescue_action(e) raise e end; end
class ProfileDesignControllerTest < Test::Unit::TestCase
- COMMOM_BLOCKS = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock]
+ COMMOM_BLOCKS = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock ]
PERSON_BLOCKS = COMMOM_BLOCKS + [FriendsBlock, FavoriteEnterprisesBlock, CommunitiesBlock, EnterprisesBlock ]
PERSON_BLOCKS_WITH_MEMBERS = PERSON_BLOCKS + [MembersBlock]
PERSON_BLOCKS_WITH_BLOG = PERSON_BLOCKS + [BlogArchivesBlock]
diff --git a/test/functional/profile_search_controller_test.rb b/test/functional/profile_search_controller_test.rb
new file mode 100644
index 0000000..0feb6f9
--- /dev/null
+++ b/test/functional/profile_search_controller_test.rb
@@ -0,0 +1,106 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require 'profile_search_controller'
+
+# Re-raise errors caught by the controller.
+class ProfileSearchController; def rescue_action(e) raise e end; end
+
+class ProfileSearchControllerTest < Test::Unit::TestCase
+ def setup
+ @controller = ProfileSearchController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+
+ @person = fast_create(Person)
+ end
+ attr_reader :person
+
+ should 'filter stop words' do
+ @controller.expects(:locale).returns('en').at_least_once
+ get 'index', :profile => person.identifier, :q => 'an article about something'
+ assert_response :success
+ assert_template 'index'
+ assert_equal 'article something', assigns('filtered_query')
+ end
+
+ should 'espape xss attack' do
+ @controller.expects(:profile).returns(person).at_least_once
+ get 'index', :profile => person.identifier, :q => ''
+ assert_no_tag :tag => 'wslite'
+ end
+
+ should 'render success in search' do
+ get :index, :profile => person.identifier, :q => 'something not important'
+ assert_response :success
+ end
+
+ should 'search for articles' do
+ article = TextileArticle.create(:name => 'My article', :body => 'Article to test profile search', :profile => person)
+
+ get 'index', :profile => person.identifier, :q => 'article profile'
+ assert_includes assigns(:results), article
+ end
+
+ should 'display search results' do
+ article1 = fast_create(Article, :body => 'Article to test profile search
', :profile_id => person.id)
+ article2 = fast_create(Article, :body => 'Another article to test profile search
', :profile_id => person.id)
+
+ get 'index', :profile => person.identifier, :q => 'article'
+
+ [article1, article2].each do |article|
+ assert_tag :tag => 'li', :descendant => { :tag => 'a', :content => article.short_lead, :attributes => { :class => /article-details/ }}
+ end
+ end
+
+ should 'paginate results listing' do
+ (1..11).each do |i|
+ TextileArticle.create!(:name => "Article #{i}", :profile => person, :language => 'en')
+ end
+
+ get 'index', :profile => person.identifier, :q => 'Article'
+
+ assert_equal 10, assigns(:results).size
+ assert_tag :tag => 'a', :attributes => { :href => "/profile/#{person.identifier}/search?page=2&q=Article", :rel => 'next' }
+ end
+
+ should 'display abstract if given' do
+ article1 = TextileArticle.create(:name => 'Article 1', :abstract => 'Abstract to test', :body => 'Article to test profile search', :profile => person)
+ article2 = TextileArticle.create(:name => 'Article 2', :body => 'Another article to test profile search', :profile => person)
+
+ get 'index', :profile => person.identifier, :q => 'article profile'
+
+ assert_tag :tag => 'li', :descendant => { :tag => 'a', :content => article1.abstract, :attributes => { :class => /article-details/ }}
+ assert_no_tag :tag => 'li', :descendant => { :tag => 'a', :content => article1.body, :attributes => { :class => /article-details/ }}
+
+ assert_tag :tag => 'li', :descendant => { :tag => 'a', :content => article2.body, :attributes => { :class => /article-details/ }}
+ end
+
+ should 'display nothing if search is blank' do
+ article1 = TextileArticle.create(:name => 'Article 1', :body => 'Article to test profile search', :profile => person)
+ article2 = TextileArticle.create(:name => 'Article 2', :body => 'Another article to test profile search', :profile => person)
+
+ get 'index', :profile => person.identifier, :q => ''
+
+ assert_no_tag :tag => 'ul', :attributes => { :id => 'profile-search-results'}, :descendant => { :tag => 'li' }
+ end
+
+ should 'not display private articles' do
+ article1 = TextileArticle.create(:name => 'Article 1', :body => 'Article to test profile search', :profile => person, :published => false)
+ article2 = TextileArticle.create(:name => 'Article 2', :body => 'Another article to test profile search', :profile => person)
+
+ get 'index', :profile => person.identifier, :q => 'article profile'
+
+ assert_no_tag :tag => 'li', :descendant => { :tag => 'a', :content => article1.body, :attributes => { :class => /article-details/ }}
+
+ assert_tag :tag => 'li', :descendant => { :tag => 'a', :content => article2.body, :attributes => { :class => /article-details/ }}
+ end
+
+ should 'display number of results found' do
+ article1 = TextileArticle.create(:name => 'Article 1', :body => 'Article to test profile search', :body => 'Article to test profile search', :profile => person)
+ article2 = TextileArticle.create(:name => 'Article 2', :body => 'Another article to test profile search', :profile => person)
+
+ get 'index', :profile => person.identifier, :q => 'article profile'
+
+ assert_tag :tag => 'div', :attributes => { :class => 'results-found-message' }, :content => /2 results found/
+ end
+
+end
diff --git a/test/unit/article_test.rb b/test/unit/article_test.rb
index a41f41b..a26c8e9 100644
--- a/test/unit/article_test.rb
+++ b/test/unit/article_test.rb
@@ -921,6 +921,16 @@ class ArticleTest < Test::Unit::TestCase
assert_equal '', a.lead
end
+ should 'have short lead' do
+ a = fast_create(TinyMceArticle, :body => '' + ('a' *180) + '
')
+ assert_equal 170, a.short_lead.length
+ end
+
+ should 'remove html from short lead' do
+ a = Article.new(:body => "an article with html that should be removed
")
+ assert_equal 'an article with html that should be removed', a.short_lead
+ end
+
should 'track action when a published article is created outside a community' do
article = TinyMceArticle.create! :name => 'Tracked Article', :profile_id => profile.id
assert article.published?
diff --git a/test/unit/profile_search_block_test.rb b/test/unit/profile_search_block_test.rb
new file mode 100644
index 0000000..c4f4a53
--- /dev/null
+++ b/test/unit/profile_search_block_test.rb
@@ -0,0 +1,32 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ProfileSearchBlockTest < Test::Unit::TestCase
+
+ should 'describe itself' do
+ assert_not_equal Block.description, ProfileSearchBlock.description
+ end
+
+ should 'provide a default title' do
+ assert_not_equal Block.new.default_title, ProfileSearchBlock.new.default_title
+ end
+
+ should 'render profile search' do
+ person = fast_create(Person)
+
+ block = ProfileSearchBlock.new
+ block.stubs(:owner).returns(person)
+
+ self.expects(:render).with(:file => 'blocks/profile_search', :locals => { :title => block.title})
+ instance_eval(& block.content)
+ end
+
+ should 'provide view_title' do
+ person = fast_create(Person)
+ person.boxes << Box.new
+ block = ProfileSearchBlock.new(:title => 'Title from block')
+ person.boxes.first.blocks << block
+ block.save!
+ assert_equal 'Title from block', block.view_title
+ end
+
+end
diff --git a/test/unit/text_article_test.rb b/test/unit/text_article_test.rb
index e4ded47..34c5da7 100644
--- a/test/unit/text_article_test.rb
+++ b/test/unit/text_article_test.rb
@@ -43,4 +43,14 @@ class TextArticleTest < Test::Unit::TestCase
assert_kind_of Noosfero::TranslatableContent, TextArticle.new
end
+ should 'return article icon name' do
+ assert_equal Article.icon_name, TextArticle.icon_name
+ end
+
+ should 'return blog icon name if the article is a blog post' do
+ blog = fast_create(Blog)
+ article = TextArticle.new(:parent => blog)
+ assert_equal Blog.icon_name, TextArticle.icon_name(article)
+ end
+
end
--
libgit2 0.21.2