Commit 6d7a082470e0580f338188c325f1fcded5dcd5c3
Exists in
master
and in
29 other branches
Merge remote-tracking branch 'dani/AI2822-fixes' into AI2822-fixes
Conflicts: public/stylesheets/application.css
Showing
18 changed files
with
355 additions
and
25 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
@@ -68,6 +68,9 @@ class CmsController < MyProfileController | @@ -68,6 +68,9 @@ class CmsController < MyProfileController | ||
68 | def edit | 68 | def edit |
69 | @success_back_to = params[:success_back_to] | 69 | @success_back_to = params[:success_back_to] |
70 | @article = profile.articles.find(params[:id]) | 70 | @article = profile.articles.find(params[:id]) |
71 | + version = params[:version] | ||
72 | + @article.revert_to(version) if version | ||
73 | + | ||
71 | @parent_id = params[:parent_id] | 74 | @parent_id = params[:parent_id] |
72 | @type = params[:type] || @article.class.to_s | 75 | @type = params[:type] || @article.class.to_s |
73 | translations if @article.translatable? | 76 | translations if @article.translatable? |
app/controllers/public/content_viewer_controller.rb
@@ -7,6 +7,7 @@ class ContentViewerController < ApplicationController | @@ -7,6 +7,7 @@ class ContentViewerController < ApplicationController | ||
7 | 7 | ||
8 | def view_page | 8 | def view_page |
9 | path = params[:page].join('/') | 9 | path = params[:page].join('/') |
10 | + @version = params[:version].to_i | ||
10 | 11 | ||
11 | if path.blank? | 12 | if path.blank? |
12 | @page = profile.home_page | 13 | @page = profile.home_page |
@@ -25,22 +26,15 @@ class ContentViewerController < ApplicationController | @@ -25,22 +26,15 @@ class ContentViewerController < ApplicationController | ||
25 | end | 26 | end |
26 | end | 27 | end |
27 | 28 | ||
28 | - if !@page.nil? && !@page.display_to?(user) | ||
29 | - if !profile.public? | ||
30 | - private_profile_partial_parameters | ||
31 | - render :template => 'profile/_private_profile.rhtml', :status => 403 | ||
32 | - else #if !profile.visible? | ||
33 | - message = _('You are not allowed to view this content.') | ||
34 | - message += ' ' + _('You can contact the owner of this profile to request access then.') | ||
35 | - render_access_denied(message) | ||
36 | - end | ||
37 | - return | ||
38 | - end | 29 | + return unless allow_access_to_page(path) |
39 | 30 | ||
40 | - # page not found, give error | ||
41 | - if @page.nil? | ||
42 | - render_not_found(@path) | ||
43 | - return | 31 | + if @version > 0 |
32 | + return render_access_denied unless @page.display_versions? | ||
33 | + @versioned_article = @page.versions.find_by_version(@version) | ||
34 | + if @versioned_article && @page.versions.latest.version != @versioned_article.version | ||
35 | + render :template => 'content_viewer/versioned_article.rhtml' | ||
36 | + return | ||
37 | + end | ||
44 | end | 38 | end |
45 | 39 | ||
46 | if request.xhr? && params[:toolbar] | 40 | if request.xhr? && params[:toolbar] |
@@ -128,6 +122,15 @@ class ContentViewerController < ApplicationController | @@ -128,6 +122,15 @@ class ContentViewerController < ApplicationController | ||
128 | end | 122 | end |
129 | end | 123 | end |
130 | 124 | ||
125 | + def article_versions | ||
126 | + path = params[:page].join('/') | ||
127 | + @page = profile.articles.find_by_path(path) | ||
128 | + return unless allow_access_to_page(path) | ||
129 | + | ||
130 | + render_access_denied unless @page.display_versions? | ||
131 | + @versions = @page.versions.paginate(:per_page => per_page, :page => params[:npage]) | ||
132 | + end | ||
133 | + | ||
131 | protected | 134 | protected |
132 | 135 | ||
133 | def per_page | 136 | def per_page |
@@ -158,4 +161,22 @@ class ContentViewerController < ApplicationController | @@ -158,4 +161,22 @@ class ContentViewerController < ApplicationController | ||
158 | end | 161 | end |
159 | helper_method :pass_without_comment_captcha? | 162 | helper_method :pass_without_comment_captcha? |
160 | 163 | ||
164 | + def allow_access_to_page(path) | ||
165 | + allowed = true | ||
166 | + if @page.nil? # page not found, give error | ||
167 | + render_not_found(path) | ||
168 | + allowed = false | ||
169 | + elsif !@page.display_to?(user) | ||
170 | + if !profile.public? | ||
171 | + private_profile_partial_parameters | ||
172 | + render :template => 'profile/_private_profile.rhtml', :status => 403 | ||
173 | + allowed = false | ||
174 | + else #if !profile.visible? | ||
175 | + render_access_denied | ||
176 | + allowed = false | ||
177 | + end | ||
178 | + end | ||
179 | + allowed | ||
180 | + end | ||
181 | + | ||
161 | end | 182 | end |
app/helpers/application_helper.rb
@@ -1404,4 +1404,8 @@ module ApplicationHelper | @@ -1404,4 +1404,8 @@ module ApplicationHelper | ||
1404 | content.nil? ? '' : content.id.to_s | 1404 | content.nil? ? '' : content.id.to_s |
1405 | end | 1405 | end |
1406 | 1406 | ||
1407 | + def display_article_versions(article, version = nil) | ||
1408 | + content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) | ||
1409 | + end | ||
1410 | + | ||
1407 | end | 1411 | end |
app/helpers/article_helper.rb
@@ -28,7 +28,7 @@ module ArticleHelper | @@ -28,7 +28,7 @@ module ArticleHelper | ||
28 | 'div', | 28 | 'div', |
29 | check_box(:article, :notify_comments) + | 29 | check_box(:article, :notify_comments) + |
30 | content_tag('label', _('I want to receive a notification of each comment written by e-mail'), :for => 'article_notify_comments') + | 30 | content_tag('label', _('I want to receive a notification of each comment written by e-mail'), :for => 'article_notify_comments') + |
31 | - observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked;$('article_moderate_comments').disabled = ! $('article_accept_comments').checked") | 31 | + observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked;$('article_moderate_comments').disabled = ! $('article_accept_comments').checked") |
32 | ) + | 32 | ) + |
33 | 33 | ||
34 | content_tag( | 34 | content_tag( |
@@ -42,7 +42,15 @@ module ArticleHelper | @@ -42,7 +42,15 @@ module ArticleHelper | ||
42 | 'div', | 42 | 'div', |
43 | check_box(:article, :display_hits) + | 43 | check_box(:article, :display_hits) + |
44 | content_tag('label', _('I want this article to display the number of hits it received'), :for => 'article_display_hits') | 44 | content_tag('label', _('I want this article to display the number of hits it received'), :for => 'article_display_hits') |
45 | + ) : '') + | ||
46 | + | ||
47 | + (article.can_display_versions? ? | ||
48 | + content_tag( | ||
49 | + 'div', | ||
50 | + check_box(:article, :display_versions) + | ||
51 | + content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') | ||
45 | ) : '') | 52 | ) : '') |
53 | + | ||
46 | ) | 54 | ) |
47 | end | 55 | end |
48 | 56 |
app/models/article.rb
@@ -201,6 +201,7 @@ class Article < ActiveRecord::Base | @@ -201,6 +201,7 @@ class Article < ActiveRecord::Base | ||
201 | acts_as_filesystem | 201 | acts_as_filesystem |
202 | 202 | ||
203 | acts_as_versioned | 203 | acts_as_versioned |
204 | + self.non_versioned_columns << 'setting' | ||
204 | 205 | ||
205 | def comment_data | 206 | def comment_data |
206 | comments.map {|item| [item.title, item.body].join(' ') }.join(' ') | 207 | comments.map {|item| [item.title, item.body].join(' ') }.join(' ') |
@@ -604,17 +605,34 @@ class Article < ActiveRecord::Base | @@ -604,17 +605,34 @@ class Article < ActiveRecord::Base | ||
604 | false | 605 | false |
605 | end | 606 | end |
606 | 607 | ||
607 | - def author | ||
608 | - if versions.empty? | ||
609 | - last_changed_by | ||
610 | - else | ||
611 | - author_id = versions.first.last_changed_by_id | 608 | + settings_items :display_versions, :type => :boolean, :default => false |
609 | + | ||
610 | + def can_display_versions? | ||
611 | + false | ||
612 | + end | ||
613 | + | ||
614 | + def display_versions? | ||
615 | + can_display_versions? && display_versions | ||
616 | + end | ||
617 | + | ||
618 | + def author(version_number = nil) | ||
619 | + if version_number | ||
620 | + version = versions.find_by_version(version_number) | ||
621 | + author_id = version.last_changed_by_id if version | ||
612 | Person.exists?(author_id) ? Person.find(author_id) : nil | 622 | Person.exists?(author_id) ? Person.find(author_id) : nil |
623 | + else | ||
624 | + if versions.empty? | ||
625 | + last_changed_by | ||
626 | + else | ||
627 | + author_id = versions.first.last_changed_by_id | ||
628 | + Person.exists?(author_id) ? Person.find(author_id) : nil | ||
629 | + end | ||
613 | end | 630 | end |
614 | end | 631 | end |
615 | 632 | ||
616 | - def author_name | ||
617 | - author ? author.name : (setting[:author_name] || _('Unknown')) | 633 | + def author_name(version_number = nil) |
634 | + person = version_number ? author(version_number) : author | ||
635 | + person ? person.name : (setting[:author_name] || _('Unknown')) | ||
618 | end | 636 | end |
619 | 637 | ||
620 | def author_url | 638 | def author_url |
@@ -625,13 +643,20 @@ class Article < ActiveRecord::Base | @@ -625,13 +643,20 @@ class Article < ActiveRecord::Base | ||
625 | author ? author.id : nil | 643 | author ? author.id : nil |
626 | end | 644 | end |
627 | 645 | ||
646 | + def version_license(version_number = nil) | ||
647 | + return license if version_number.nil? | ||
648 | + profile.environment.licenses.find_by_id(versions.find_by_version(version_number).license_id) | ||
649 | + end | ||
650 | + | ||
628 | alias :active_record_cache_key :cache_key | 651 | alias :active_record_cache_key :cache_key |
629 | def cache_key(params = {}, the_profile = nil, language = 'en') | 652 | def cache_key(params = {}, the_profile = nil, language = 'en') |
630 | active_record_cache_key+'-'+language + | 653 | active_record_cache_key+'-'+language + |
631 | (allow_post_content?(the_profile) ? "-owner" : '') + | 654 | (allow_post_content?(the_profile) ? "-owner" : '') + |
632 | (params[:npage] ? "-npage-#{params[:npage]}" : '') + | 655 | (params[:npage] ? "-npage-#{params[:npage]}" : '') + |
633 | (params[:year] ? "-year-#{params[:year]}" : '') + | 656 | (params[:year] ? "-year-#{params[:year]}" : '') + |
634 | - (params[:month] ? "-month-#{params[:month]}" : '') | 657 | + (params[:month] ? "-month-#{params[:month]}" : '') + |
658 | + (params[:version] ? "-version-#{params[:version]}" : '') | ||
659 | + | ||
635 | end | 660 | end |
636 | 661 | ||
637 | def first_paragraph | 662 | def first_paragraph |
app/models/text_article.rb
app/views/content_viewer/_article_toolbar.rhtml
@@ -48,6 +48,10 @@ | @@ -48,6 +48,10 @@ | ||
48 | <%= expirable_button @page, :suggest, content, url, options %> | 48 | <%= expirable_button @page, :suggest, content, url, options %> |
49 | <% end %> | 49 | <% end %> |
50 | 50 | ||
51 | + <% if @page.display_versions? %> | ||
52 | + <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> | ||
53 | + <% end %> | ||
54 | + | ||
51 | <%= report_abuse(profile, :link, @page) %> | 55 | <%= report_abuse(profile, :link, @page) %> |
52 | 56 | ||
53 | </div> | 57 | </div> |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +<%= article_title(@page, :no_link => true) %> | ||
2 | + | ||
3 | +<p><%= _('This is the list of all versions of this content. Select a version to see it and then revert to it.') %>.</p> | ||
4 | + | ||
5 | +<ul class='article-versions'> | ||
6 | + <% @versions.each do |v| %> | ||
7 | + <li> | ||
8 | + <%= link_to(_("Version #{v.version}"), @page.url.merge(:version => v.version)) %> | ||
9 | + <%= @page.version == v.version ? _('(current)') : '' %> | ||
10 | + <span class='updated-by'><%= _('by %{author}') % {:author => link_to(@page.author_name(v.version), @page.author_url)} %></span> | ||
11 | + <div class='updated-on'><%= show_time(v.updated_at) %></div> | ||
12 | + </li> | ||
13 | + <% end %> | ||
14 | +</ul> | ||
15 | + | ||
16 | +<%= pagination_links @versions, :param_name => 'npage' %> |
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +<div id="article" class="<%= @page.css_class_name %>"> | ||
2 | + | ||
3 | + <div id="article-actions"> | ||
4 | + <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> | ||
5 | + | ||
6 | + <% if @page.allow_edit?(user) && !remove_content_button(:edit) %> | ||
7 | + <% content = content_tag('span', _('Revert to this version')) %> | ||
8 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id, :version => @version }) %> | ||
9 | + <%= expirable_button @page, :edit, content, url, :id => 'article-revert-version-link' %> | ||
10 | + <% end %> | ||
11 | + </div> | ||
12 | + | ||
13 | + <div id="article-header"> | ||
14 | + <h1 class='title'><%= @versioned_article.name %></h1> | ||
15 | + <%= _("Version %{version} - %{author} on %{date}") % {:version => @version, :author => @page.author_name(@version), :date => show_time(@versioned_article.updated_at) } %> | ||
16 | + </div> | ||
17 | + | ||
18 | + <% if @page.version_license(@version).present? %> | ||
19 | + <div id='article-sub-header'> | ||
20 | + <% if @page.version_license(@version).present? %> | ||
21 | + <div id="article-license"> | ||
22 | + <%= _('Licensed under %s') % (@page.version_license(@version).url.present? ? link_to(@page.version_license(@version).name, @page.version_license(@version).url, :target => '_blank') : @page.version_license(@version).name) %> | ||
23 | + </div> | ||
24 | + <% end %> | ||
25 | + </div> | ||
26 | + <% end %> | ||
27 | + | ||
28 | + <% cache(@page.cache_key(params, user, language)) do %> | ||
29 | + <div class="<%="article-body article-body-" + @page.css_class_name %>"> | ||
30 | + <%= @versioned_article.body %> | ||
31 | + <br style="clear:both" /> | ||
32 | + </div> <!-- end class="article-body" --> | ||
33 | + <% end %> | ||
34 | + | ||
35 | + <%= display_source_info(@page) %> | ||
36 | + | ||
37 | +</div><!-- end id="article" --> | ||
38 | +<%= add_zoom_to_article_images %> |
config/routes.rb
@@ -126,12 +126,14 @@ ActionController::Routing::Routes.draw do |map| | @@ -126,12 +126,14 @@ ActionController::Routing::Routes.draw do |map| | ||
126 | # cache stuff - hack | 126 | # cache stuff - hack |
127 | map.cache 'public/:action/:id', :controller => 'public' | 127 | map.cache 'public/:action/:id', :controller => 'public' |
128 | 128 | ||
129 | + map.connect ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | ||
130 | + map.connect '*page/versions', :controller => 'content_viewer', :action => 'article_versions' | ||
129 | 131 | ||
130 | # match requests for profiles that don't have a custom domain | 132 | # match requests for profiles that don't have a custom domain |
131 | map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | 133 | map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } |
132 | 134 | ||
133 | - | ||
134 | # match requests for content in domains hosted for profiles | 135 | # match requests for content in domains hosted for profiles |
135 | map.connect '*page', :controller => 'content_viewer', :action => 'view_page' | 136 | map.connect '*page', :controller => 'content_viewer', :action => 'view_page' |
136 | 137 | ||
138 | + | ||
137 | end | 139 | end |
@@ -0,0 +1,87 @@ | @@ -0,0 +1,87 @@ | ||
1 | +Feature: article versioning | ||
2 | + As a user | ||
3 | + I want to see article versions | ||
4 | + In order to be able to change between versions of an article | ||
5 | + | ||
6 | + Background: | ||
7 | + Given the following users | ||
8 | + | login | name | | ||
9 | + | joaosilva | Joao Silva | | ||
10 | + And "joaosilva" has no articles | ||
11 | + And the following articles | ||
12 | + | owner | name | body | display_versions | | ||
13 | + | joaosilva | Sample Article | This is the first version of the article | true | | ||
14 | + And the article "Sample Article" is updated with | ||
15 | + | name | body | | ||
16 | + | Edited Article | This is the second version of the article | | ||
17 | + And I am logged in as "joaosilva" | ||
18 | + | ||
19 | + @selenium | ||
20 | + Scenario: enabling visualization of versions | ||
21 | + Given the following articles | ||
22 | + | owner | name | body | | ||
23 | + | joaosilva | New Article | Article to enable versions | | ||
24 | + Given I am on article "New Article" | ||
25 | + Then I should not see "All versions" | ||
26 | + When I follow "Edit" within "#article-actions" | ||
27 | + And I check "I want this article to display a link to older versions" | ||
28 | + And I press "Save" | ||
29 | + Then I should be on article "New Article" | ||
30 | + And I should see "All versions" | ||
31 | + | ||
32 | + @selenium | ||
33 | + Scenario: list versions of an article | ||
34 | + Given I am on article "Edited Article" | ||
35 | + When I follow "All versions" | ||
36 | + Then I should be on /joaosilva/edited-article/versions | ||
37 | + And I should see "Version 1" within ".article-versions" | ||
38 | + And I should see "Version 2" within ".article-versions" | ||
39 | + | ||
40 | + @selenium | ||
41 | + Scenario: see specific version | ||
42 | + Given I go to article "Edited Article" | ||
43 | + Then I should see "Edited Article" within ".title" | ||
44 | + And I should see "This is the second version of the article" within ".article-body" | ||
45 | + When I follow "All versions" | ||
46 | + And I follow "Version 1" | ||
47 | + Then I should see "Sample Article" within ".title" | ||
48 | + And I should see "This is the first version of the article" within ".article-body" | ||
49 | + | ||
50 | + @selenium | ||
51 | + Scenario: revert to a specific version generates a new version | ||
52 | + Given I go to article "Edited Article" | ||
53 | + When I follow "All versions" | ||
54 | + Then I should not see "Version 3" within ".article-versions" | ||
55 | + And I follow "Version 1" | ||
56 | + And I follow "Revert to this version" | ||
57 | + And I press "Save" | ||
58 | + Then I should see "Sample Article" within ".title" | ||
59 | + When I follow "All versions" | ||
60 | + Then I should see "Version 3" within ".article-versions" | ||
61 | + | ||
62 | + Scenario: try to access versions of unexistent article | ||
63 | + Given I go to /joaosilva/unexistent-article/versions | ||
64 | + Then I should see "There is no such page" | ||
65 | + | ||
66 | + Scenario: deny access to versions when disabled on article | ||
67 | + Given the following articles | ||
68 | + | owner | name | body | display_versions | | ||
69 | + | joaosilva | Versions disabled | Versions can't be displayed | false | | ||
70 | + And I go to /joaosilva/versions-disabled/versions | ||
71 | + Then I should see "Access denied" | ||
72 | + | ||
73 | + Scenario: deny access to specific version when disabled on article and not logged | ||
74 | + Given the article "Edited Article" is updated with | ||
75 | + | display_versions | | ||
76 | + | false | | ||
77 | + And I am not logged in | ||
78 | + And I go to /joaosilva/edited-article?version=1 | ||
79 | + Then I should see "Access denied" | ||
80 | + | ||
81 | + Scenario: deny access to specific version when disabled, private and not logged | ||
82 | + Given the article "Edited Article" is updated with | ||
83 | + | display_versions | published | | ||
84 | + | false | false | | ||
85 | + And I am not logged in | ||
86 | + And I go to /joaosilva/edited-article?version=1 | ||
87 | + Then I should see "Access denied" |
features/step_definitions/noosfero_steps.rb
@@ -687,6 +687,14 @@ Given /^the article "([^\"]*)" is updated by "([^\"]*)"$/ do |article, person| | @@ -687,6 +687,14 @@ Given /^the article "([^\"]*)" is updated by "([^\"]*)"$/ do |article, person| | ||
687 | a.save! | 687 | a.save! |
688 | end | 688 | end |
689 | 689 | ||
690 | +Given /^the article "([^\"]*)" is updated with$/ do |article, table| | ||
691 | + a = Article.find_by_name article | ||
692 | + | ||
693 | + row = table.hashes.first | ||
694 | + | ||
695 | + a.update_attributes(row) | ||
696 | +end | ||
697 | + | ||
690 | Given /^the cache is turned (on|off)$/ do |state| | 698 | Given /^the cache is turned (on|off)$/ do |state| |
691 | ActionController::Base.perform_caching = (state == 'on') | 699 | ActionController::Base.perform_caching = (state == 'on') |
692 | end | 700 | end |
public/designs/icons/tango/style.css
@@ -105,6 +105,7 @@ | @@ -105,6 +105,7 @@ | ||
105 | .icon-deactivate-user { background-image: url(Tango/16x16/emblems/emblem-unreadable.png) } | 105 | .icon-deactivate-user { background-image: url(Tango/16x16/emblems/emblem-unreadable.png) } |
106 | .icon-set-admin-role { background-image: url(mod/16x16/apps/user.png) } | 106 | .icon-set-admin-role { background-image: url(mod/16x16/apps/user.png) } |
107 | .icon-reset-admin-role { background-image: url(/images/icons-app/person-icon.png) } | 107 | .icon-reset-admin-role { background-image: url(/images/icons-app/person-icon.png) } |
108 | +.icon-clock { background-image: url(Tango/16x16/actions/appointment.png) } | ||
108 | 109 | ||
109 | /******************LARGE ICONS********************/ | 110 | /******************LARGE ICONS********************/ |
110 | .image-gallery-item .folder { background-image: url(mod/96x96/places/folder.png) } | 111 | .image-gallery-item .folder { background-image: url(mod/96x96/places/folder.png) } |
public/stylesheets/application.css
@@ -6466,3 +6466,15 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | @@ -6466,3 +6466,15 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | ||
6466 | width: 100px; | 6466 | width: 100px; |
6467 | text-align: center; | 6467 | text-align: center; |
6468 | } | 6468 | } |
6469 | + | ||
6470 | +#product-list .highlighted img.star { | ||
6471 | + position: absolute; | ||
6472 | + top: 2px; | ||
6473 | + right: 2px; | ||
6474 | + z-index: 1; | ||
6475 | +} | ||
6476 | + | ||
6477 | +ul.article-versions li { | ||
6478 | + font-size: 13px; | ||
6479 | + padding: 3px 0px; | ||
6480 | +} |
test/functional/cms_controller_test.rb
@@ -1719,6 +1719,23 @@ class CmsControllerTest < ActionController::TestCase | @@ -1719,6 +1719,23 @@ class CmsControllerTest < ActionController::TestCase | ||
1719 | assert_redirected_to '/' | 1719 | assert_redirected_to '/' |
1720 | end | 1720 | end |
1721 | 1721 | ||
1722 | + should 'edit article with content from older version' do | ||
1723 | + article = profile.articles.create(:name => 'first version') | ||
1724 | + article.name = 'second version'; article.save | ||
1725 | + | ||
1726 | + get :edit, :profile => profile.identifier, :id => article.id, :version => 1 | ||
1727 | + assert_equal 'second version', Article.find(article.id).name | ||
1728 | + assert_equal 'first version', assigns(:article).name | ||
1729 | + end | ||
1730 | + | ||
1731 | + should 'save article with content from older version' do | ||
1732 | + article = profile.articles.create(:name => 'first version') | ||
1733 | + article.name = 'second version'; article.save | ||
1734 | + | ||
1735 | + post :edit, :profile => profile.identifier, :id => article.id, :version => 1 | ||
1736 | + assert_equal 'first version', Article.find(article.id).name | ||
1737 | + end | ||
1738 | + | ||
1722 | protected | 1739 | protected |
1723 | 1740 | ||
1724 | # FIXME this is to avoid adding an extra dependency for a proper JSON parser. | 1741 | # FIXME this is to avoid adding an extra dependency for a proper JSON parser. |
test/functional/content_viewer_controller_test.rb
@@ -369,6 +369,35 @@ class ContentViewerControllerTest < ActionController::TestCase | @@ -369,6 +369,35 @@ class ContentViewerControllerTest < ActionController::TestCase | ||
369 | assert_redirected_to :host => p.default_hostname, :controller => 'content_viewer', :action => 'view_page', :profile => p.identifier, :page => a2.explode_path | 369 | assert_redirected_to :host => p.default_hostname, :controller => 'content_viewer', :action => 'view_page', :profile => p.identifier, :page => a2.explode_path |
370 | end | 370 | end |
371 | 371 | ||
372 | + should "display current article's versions" do | ||
373 | + page = TextArticle.create!(:name => 'myarticle', :body => 'test article', :display_versions => true, :profile => profile) | ||
374 | + page.body = 'test article edited'; page.save | ||
375 | + | ||
376 | + get :article_versions, :profile => profile.identifier, :page => [ 'myarticle' ] | ||
377 | + assert_tag :tag => 'ul', :attributes => { :class => 'article-versions' }, :descendant => { | ||
378 | + :tag => 'a', | ||
379 | + :attributes => { :href => "http://#{profile.environment.default_hostname}/#{profile.identifier}/#{page.path}?version=1" } | ||
380 | + } | ||
381 | + end | ||
382 | + | ||
383 | + should "fetch correct article version" do | ||
384 | + page = TextArticle.create!(:name => 'myarticle', :body => 'original article', :display_versions => true, :profile => profile) | ||
385 | + page.body = 'edited article'; page.save | ||
386 | + | ||
387 | + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ], :version => 1 | ||
388 | + | ||
389 | + assert_tag :tag => 'div', :attributes => { :class => /article-body/ }, :content => /original article/ | ||
390 | + end | ||
391 | + | ||
392 | + should "display current article if version does not exist" do | ||
393 | + page = TextArticle.create!(:name => 'myarticle', :body => 'original article', :display_versions => true, :profile => profile) | ||
394 | + page.body = 'edited article'; page.save | ||
395 | + | ||
396 | + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ], :version => 'bli' | ||
397 | + | ||
398 | + assert_tag :tag => 'div', :attributes => { :class => /article-body/ }, :content => /edited article/ | ||
399 | + end | ||
400 | + | ||
372 | should 'not return an article of a different user' do | 401 | should 'not return an article of a different user' do |
373 | p1 = create_user('test_user').person | 402 | p1 = create_user('test_user').person |
374 | a = p1.articles.create!(:name => 'old-name') | 403 | a = p1.articles.create!(:name => 'old-name') |
test/integration/routing_test.rb
@@ -256,4 +256,19 @@ class RoutingTest < ActionController::IntegrationTest | @@ -256,4 +256,19 @@ class RoutingTest < ActionController::IntegrationTest | ||
256 | assert_recognizes({:controller => 'not_found', :action => 'nothing', :stuff => ['aksdhf']}, '/user_themes/aksdhf') | 256 | assert_recognizes({:controller => 'not_found', :action => 'nothing', :stuff => ['aksdhf']}, '/user_themes/aksdhf') |
257 | end | 257 | end |
258 | 258 | ||
259 | + should 'have route to versions of an article' do | ||
260 | + | ||
261 | + assert_routing('/ze/work/free-software/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => 'ze', :page => ['work', "free-software"]) | ||
262 | + end | ||
263 | + | ||
264 | + should 'have route to versions of an article if profile has domain' do | ||
265 | + user = create_user('testuser').person | ||
266 | + domain = Domain.create!(:name => 'example.com', :owner => user) | ||
267 | + | ||
268 | + ActionController::TestRequest.any_instance.expects(:host).returns('www.example.com') | ||
269 | + | ||
270 | + assert_routing('/work/free-software/versions', :controller => 'content_viewer', :action => 'article_versions', :page => [ 'work', 'free-software'] ) | ||
271 | + end | ||
272 | + | ||
273 | + | ||
259 | end | 274 | end |
test/unit/article_test.rb
@@ -740,6 +740,11 @@ class ArticleTest < ActiveSupport::TestCase | @@ -740,6 +740,11 @@ class ArticleTest < ActiveSupport::TestCase | ||
740 | assert_match(/-year-2009-month-04/, a.cache_key(:year => '2009', :month => '04')) | 740 | assert_match(/-year-2009-month-04/, a.cache_key(:year => '2009', :month => '04')) |
741 | end | 741 | end |
742 | 742 | ||
743 | + should 'use revision number to compose cache key' do | ||
744 | + a = fast_create(Article, :name => 'Versioned article', :profile_id => profile.id) | ||
745 | + assert_match(/-version-2/,a.cache_key(:version => 2)) | ||
746 | + end | ||
747 | + | ||
743 | should 'not be highlighted by default' do | 748 | should 'not be highlighted by default' do |
744 | a = Article.new | 749 | a = Article.new |
745 | assert !a.highlighted | 750 | assert !a.highlighted |
@@ -1688,6 +1693,16 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1688,6 +1693,16 @@ class ArticleTest < ActiveSupport::TestCase | ||
1688 | assert_equal license, article.license | 1693 | assert_equal license, article.license |
1689 | end | 1694 | end |
1690 | 1695 | ||
1696 | + should 'return license from a specific version' do | ||
1697 | + cc = License.create!(:name => 'CC (by)', :environment => Environment.default) | ||
1698 | + gpl = License.create!(:name => 'GPLv3', :environment => Environment.default) | ||
1699 | + article = Article.create!(:name => 'first version', :profile => profile, :license => cc) | ||
1700 | + article.license = gpl | ||
1701 | + article.save | ||
1702 | + assert_equal cc, article.version_license(1) | ||
1703 | + assert_equal gpl, article.version_license(2) | ||
1704 | + end | ||
1705 | + | ||
1691 | should 'update path if parent is changed' do | 1706 | should 'update path if parent is changed' do |
1692 | f1 = Folder.create!(:name => 'Folder 1', :profile => profile) | 1707 | f1 = Folder.create!(:name => 'Folder 1', :profile => profile) |
1693 | f2 = Folder.create!(:name => 'Folder 2', :profile => profile) | 1708 | f2 = Folder.create!(:name => 'Folder 2', :profile => profile) |
@@ -1746,6 +1761,28 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1746,6 +1761,28 @@ class ArticleTest < ActiveSupport::TestCase | ||
1746 | assert_nil article.author_id | 1761 | assert_nil article.author_id |
1747 | end | 1762 | end |
1748 | 1763 | ||
1764 | + should "return the author of a specific version" do | ||
1765 | + author1 = fast_create(Person) | ||
1766 | + author2 = fast_create(Person) | ||
1767 | + article = Article.create!(:name => 'first version', :profile => profile, :last_changed_by => author1) | ||
1768 | + article.name = 'second version' | ||
1769 | + article.last_changed_by = author2 | ||
1770 | + article.save | ||
1771 | + assert_equal author1, article.author(1) | ||
1772 | + assert_equal author2, article.author(2) | ||
1773 | + end | ||
1774 | + | ||
1775 | + should "return the author_name of a specific version" do | ||
1776 | + author1 = fast_create(Person) | ||
1777 | + author2 = fast_create(Person) | ||
1778 | + article = Article.create!(:name => 'first version', :profile => profile, :last_changed_by => author1) | ||
1779 | + article.name = 'second version' | ||
1780 | + article.last_changed_by = author2 | ||
1781 | + article.save | ||
1782 | + assert_equal author1.name, article.author_name(1) | ||
1783 | + assert_equal author2.name, article.author_name(2) | ||
1784 | + end | ||
1785 | + | ||
1749 | should 'identify if belongs to forum' do | 1786 | should 'identify if belongs to forum' do |
1750 | p = create_user('user_forum_test').person | 1787 | p = create_user('user_forum_test').person |
1751 | forum = fast_create(Forum, :name => 'Forum test', :profile_id => p.id) | 1788 | forum = fast_create(Forum, :name => 'Forum test', :profile_id => p.id) |