require File.dirname(__FILE__) + '/../test_helper'
require 'pages_controller'
require 'ftools'

#--######################################################################
# Copyright (c) 2006 Logica
# 
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# 
# Onno van der Straaten:: initial implementation
#++######################################################################
# {Copyright (c) 2006 Logica}[link:files/COPYRIGHT.html]

class PagesController; def rescue_action(e) raise e end; end

class PagesControllerTest < Test::Unit::TestCase

  fixtures :users
  
  def setup
    logger.debug "Test Case: #{name}"  
    @controller = PagesController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    @andy, @george, @tony = users(:andy), users(:george),users(:tony) 
    #@oup_20060721 = create_oup_20060721
    #@oupwiki = create_oup_wiki(@oup_20060721)     
    @wiki = create_templates
    @wiki.reload
    @bp = @wiki.baseline_process
    @emails = ActionMailer::Base::deliveries
    @emails.clear
  end
  
  def teardown
    [ENV['EPFWIKI_SITES_PATH'], ENV['EPFWIKI_WIKIS_PATH']].each do |p|
      FileUtils.rm_r(p) if File.exists?(p)
      File.makedirs(p)
    end
  end
  
  # Shows:
  # 1. 'View' does not require logon 
  # 2. 'View' of a Page with Comment records, displays these records
  # 3. Contributors are displayed on the page
  # 4. If the page is checked out, this is displayed in the page
  def test_view
    # 1
    @wiki.pages.each do |page|
      id = (@wiki.rel_path + page.rel_path).gsub('/', '_') # id allows us to cache the requests (pages)
      get :view, :url => page.url(true), :id => id
      assert_response :success
      assert_equal @wiki, assigns(:wiki)
      assert_equal page, assigns(:page)
      assert_not_nil assigns(:version)
      assert_equal [], assigns(:comments)
      assert_nil assigns(:checkout)
      assert_equal [], assigns(:contributor_names)
    end
    # 2
    page = @wiki.pages[3]
    Comment.create(:text => 'Comment', :user => @andy, :page => page, :site => @wiki, :version => page.current_version)
    Comment.create(:text => 'Another comment', :user => @andy, :page => page, :site => @wiki, :version => page.current_version)
    Comment.create(:text => 'And another comment', :user => @andy, :page => page, :site => @wiki, :version => page.current_version)
    page.reload
    assert_equal 3, page.comments.size 
    get :view, :url => page.url(true)
    assert_response :success
    assert_match "Comment", @response.body
    assert_match "Another comment", @response.body
    assert_match "And another comment", @response.body
    # 3
    assert_equal [@andy.name], assigns(:contributor_names)
    assert_match @andy.name, @response.body
    # 4
    co = Checkout.new(:user => @andy, :page => page, :site => @wiki)
    assert co.save
    get :view, :url => page.url(true)
    assert_response :success
    assert_match 'This page is currently being modified by ' + @andy.name, @response.body
  end

  # Shows:
  # 1. Access 'discussion' space for a page requires logon
  # 2. Comment submitted by specifying page and Wiki
  # 3. Users are immediately notified about the new comment
  # 4. user cannot mark 'todo', 'done'
  # 5. admin can, admin is recorded as the user that marked 'done'
  # 6. cadmin can, cadmin is recorded as the user that marked 'todo'
  def test_discussion
    # 1
    page = WikiPage.find_by_presentation_name('Toolmentor Template')
    get :discussion
    assert_redirected_to :controller => 'login'
    session['user'] = @tony
    get :discussion, :site_folder => @wiki.folder, :id => page.id
    assert_response :success
    assert_not_nil assigns(:wiki)
    assert_not_nil assigns(:page)
    assert_not_nil assigns(:comment)
    assert_not_nil assigns(:comments)
    assert_equal 1, page.versions.size
    assert_equal 0, assigns(:comments).size
    # preparation for 3
    [@andy, @george].each {|u|u.update_attributes(:notify_immediate => 1)}
    assert_equal 0, @emails.size
    # 2
    post :discussion, :comment => {:text => 'comment 1 submitted in test01_new', :page_id => page.id}
    assert_redirected_to :controller => 'pages', :site_folder => @wiki.folder, :id => page.id, :action => 'discussion'
    assert_not_nil assigns(:wiki)
    assert_not_nil assigns(:page)
    assert_not_nil assigns(:comment)
    assert_not_nil assigns(:comment).version
    assert_equal page.current_version, assigns(:comment).version
    assert_not_nil assigns(:comments)
    assert_no_errors
    assert_no_errors(assigns(:comment))
    assert_equal 1, assigns(:comments).size
    get :discussion, :site_folder => @wiki.folder, :id => page.id
    assert_response :success    
    # 3
    assert_equal 1, @emails.size
    assert_equal "[EPF Wiki - Test Enviroment] New comment about #{page.presentation_name}", @emails[0].subject
    assert_equal [@andy.email, @george.email, @tony.email], @emails[0].bcc # tony because he created the comment, george and andy because they want to be notified immediately
  end
  
  # Shows:
  # 1. 'Edit' requires logon, after logon redirects to 'Checkout'
  # 2. Get 'Checkout' will display the checkout dialog 
  # 3. We can create a checkout
  # 4. We cannot checkout again, if a checkout exists the HTML editor will open but a warning is displayed
  # 7. Can open page with TinyMCE if TinyMCE is installed in public/javascripts/tiny_mce
  # 8. All users can start the HTML editor but only the owner or cadmin can commit changes
  # 9. Other user can't save HTML
  # 10. Owner can save HTML
  # 11. Cadmin can save HTML of other user  
  # 12. Other user cannot checkin 
  # 13. Can checkin without submit of HTML 
  # 14. Checkout of version 1 of page
  # 15. Can checkin with submit of HTML
  # 16. Authentication to request form
  # 17. user request for form to create page based on a template
  # 18. form has field 'presentation_name', textarea 'note' and radio button for selecting a version, last version of first template is default
  # 19. new page '' based on 'Tool Mentor Template.html' creates a checkout
  # 20. page does not exist untill checkin
  # 21. undo checkout deletes new page 
  # 22. we can edit, preview, save and checkin a new page created based on a template
   def test_checkout_edithtml_save_checkin_new
    page = WikiPage.find_by_presentation_name('Toolmentor Template')
    assert_not_nil page
    assert !page.versions.empty?
    # 1
    get :edit, :id => page.id, :site_folder => @wiki.folder
    assert_redirected_to :controller => 'login'
    session['user'] = @tony
    get :edit, :id => page.id, :site_folder => @wiki.folder
    assert_redirected_to :action => 'checkout', :id => page.id, :site_folder => @wiki.folder
    # 2 
    get :checkout, :id => page.id, :site_folder => @wiki.folder
    assert_response :success
    assert_not_nil assigns(:page)
    assert_not_nil assigns(:wiki)      
    assert_not_nil assigns(:version)   
    assert_equal page.current_version, assigns(:version).source_version # source version is default current_version
    assert_not_nil @bp
    # 3
    post :checkout, :version => {:version_id => assigns(:version).source_version.id, :note => 'test01_checkout'}
    assert_not_nil page.checkout
    assert_redirected_to  :action => 'edit', :checkout_id => page.checkout.id 
    # 4
    session['user'] = @andy
    get :checkout, :id => page.id, :site_folder => @wiki.folder # get checkout will redirect
    assert_redirected_to  :action => 'edit', :checkout_id => page.checkout.id
    get :edit, :checkout_id => page.checkout.id # will just open the page in the HTML editor
    assert_response :success
    assert_match 'The page is currently checked out by user',@response.body
    # 7
    checkout = Checkout.find(:first)
    session['user'] = checkout.user
    ENV['EPFWIKI_EDITOR'] = 'tinymce' # TODO Bug 218832 - RTE
    assert File.exists?("#{ENV['EPFWIKI_ROOT_DIR']}public/javascripts/tiny_mce/tiny_mce.js")       
    get :edit, :checkout_id => checkout.id
    assert_response :success
    # 8
    session['user'] = @andy
    get :edit, :checkout_id => checkout.id
    assert_response :success
    assert_match "The page is currently checked out by user #{@tony.name}", @response.body
    assert_match "You can modify the HTML but you cannot commit any changes", @response.body
    session['user'] = @george
    get :edit, :checkout_id => checkout.id
    assert_response :success
    assert_not_nil assigns(:checkout)
    assert_match "The page is currently checked out by user #{@tony.name}", @response.body
    assert_match "As you are the central administrator you can perform operations on this checkout", @response.body
    # 9    
    page.reload
    assert_not_nil page.checkout
    co = page.checkout
    assert_equal co.version.source_version.page, co.page # ordinary checkout, not a new page
    html = co.version.html.gsub('</body>','adding some text</body>')
    session['user'] = @andy
    assert_raise(RuntimeError) {post :save, :html => html, :checkout_id => co.id}
    # 10
    session['user'] = checkout.user
    post :save, :html => html, :checkout_id => co.id
    assert_redirected_to :action => 'edit', :checkout_id => co.id
    assert_match 'adding some text', checkout.version.html 
    # 11
    session['user'] = @george
    post :save,  :checkout_id => co.id, :html => co.version.html.gsub('adding some text', 'adding some text, adding some more by by cadmin')
    assert_redirected_to :action => 'edit', :checkout_id => co.id    
    assert_equal nil, co.version.version
    assert_match 'adding some text, adding some more by by cadmin', co.version.html
    # 12     
    logger.debug 'test05_checkin'
    assert_equal 1, Checkout.count
    #page = WikiPage.find_by_presentation_name('Role Template')
    assert_not_nil page.checkout
    co = page.checkout
    session['user'] = @andy
    assert @andy != checkout.user
    assert_raise(RuntimeError) {post :checkin, :checkout_id => checkout.id}
    # 13
    session['user'] = checkout.user
    post :checkin, :checkout_id => checkout.id
    assert_raise(ActiveRecord::RecordNotFound) {Checkout.find(checkout.id)}
    assert_match 'adding some text, adding some more by by cadmin', page.html
    assert_enhanced_file(page.path)
    assert_version_file(page.current_version.path)  
    # 14
    page.reload
    assert_equal 1, page.versions[1].version
    post :checkout, :version => {:version_id => page.versions[1].id, :note => 'Checkout of version 1'}   
    assert_not_nil page.checkout
    assert_redirected_to :action => 'edit', :checkout_id => page.checkout.id
    co = page.checkout
    v = co.version
    # 15
    post :checkin, :checkout_id => co.id, :html => checkout.version.html.gsub('</body>', 'Checkin with submit of html</body>')
    assert_raise(ActiveRecord::RecordNotFound) {Checkout.find(co.id)}    
    assert_match 'Checkin with submit of html', page.html    
    assert_enhanced_file(page.path)
    v.reload
    assert_version_file(v.path)
    # 16
    #create_templates
    session['user'] = @tony
    get :new, :site_folder => @wiki.folder, :id => @wiki.pages[10]
    assert_not_nil assigns(:wiki)
    assert_not_nil assigns(:page)    
    assert_not_nil assigns(:new_page).source_version
    assert_not_nil assigns(:templates)    
    assert_equal 27, assigns(:templates).size
    assert_equal assigns(:templates)[0].id, assigns(:new_page).source_version
    #assert_tag :tag => 'input', :attributes => {:type => 'radio',  :name => 'new_page[source_version]', :value => assigns(:page).source_version, :checked => 'checked'}
    # 17
    #assert_field('page_presentation_name') TODO update
    #assert_tag :tag => 'textarea', :attributes => {:id => 'new_page_note', :name => 'new_page[note]'}
    #assigns(:templates).each do |version|
    #  assert_tag :tag => 'input', :attributes => {:type => 'radio', :id => "new_page_source_version_#{version.id.to_s}", :name => 'new_page[source_version]', :value => version.id}
    #end
    # 18
    template = WikiPage.find_by_presentation_name('Toolmentor Template')
    assert_not_nil template
    post :new, :id => template.id, :site_folder => template.site.folder, :page => {:presentation_name => 'A strange name&2//++-09976', :source_version => template.current_version.id, :note => 'test03_new_page_using_template'}
    assert_not_nil assigns(:checkout)
    co = assigns(:checkout)
    new_page = co.page
    assert_not_nil new_page.user
    assert_redirected_to :action => 'edit', :checkout_id => co.id
    assert_equal template.current_version, co.version.source_version
    assert_version_file(co.version.path)
    assert_equal 'a_strange_name209976.html', new_page.filename
    assert co.version.source_version.html.index('Tool Mentor: Toolmentor Template')
    # 19
    assert File.exists?(new_page.path) # 
    assert File.exists?(co.version.path)
    # 20
    # 21
    # 22
    page = WikiPage.find_by_presentation_name('A strange name&2//++-09976')
    assert_not_nil page.checkout
    co = page.checkout
    v = co.version
    session['user'] = co.user
    get :edit, :checkout_id => co.id # we can edit
    post :preview, :html => co.version.html.gsub('accomplish a piece of work', 'accomplish a piece of work####'), :checkout_id => co.id
    assert_redirected_to '/' + co.version.rel_path_root
    assert_match 'work####', co.version.html
    post :save, :html => co.version.html.gsub('work####', '####work####'), :checkout_id => co.id    
    assert_match '####work####', co.version.html    
    post :checkin, :checkout_id => co.id
    assert_raise(ActiveRecord::RecordNotFound) {Checkout.find(co.id)}
    assert_match '####work####', page.html
    assert_enhanced_file(page.path)
    v.reload
    assert_version_file(v.path)
  end 
  
  # Shows:
  # 1. Owner can undo checkout
  # 2. Other user can't undo
  # 3. Cadmin can undo any checkout
  # 4. Undo of new page deletes the checkout, version, page and redirects to first page of the wiki
  def test_undocheckout
    get :checkout
    session['user'] = @tony
    page = WikiPage.find_by_presentation_name('Toolmentor Template')
    assert_nil page.checkout
    # 1
    v = page.current_version
    assert_not_nil v
    post :checkout, :version => {:version_id => v.id, :note => 'test_undocheckout'}    
    assert_not_nil page.checkout
    assert_redirected_to :action => 'edit', :checkout_id => page.checkout.id
    co = page.checkout
    v = page.checkout.version
    get :undocheckout, :checkout_id => co.id
    assert !Checkout.exists?(co.id)
    assert !Version.exists?(v.id)
    # 2
    post :checkout, :version => {:version_id => page.current_version.id, :note => 'test_undocheckout'}    
    co = page.checkout
    v = page.checkout.version    
    session['user'] = @andy
    assert_raise(RuntimeError) {get :undocheckout, :checkout_id => co.id}
    # 3
    session['user'] = @george

    get :undocheckout, :checkout_id => co.id
    assert_redirected_to '/' + @wiki.rel_path + '/' + page.rel_path
    assert_nil page.checkout
    assert !Checkout.exists?(co.id)
    assert !Version.exists?(v.id)
    # 4 
    session['user'] = @tony
    page.reload
    assert_not_nil page
    assert_not_nil page.site
    assert page.site.pages.size > 0
    post :new, :id => page.site.pages[0].id, :site_folder =>page.site.folder, :page => {:presentation_name => "New page based on #{page.presentation_name}", :source_version => page.versions.last.id, :note => 'Undo also deletes page'}
    new_page = WikiPage.find_by_presentation_name("New page based on #{page.presentation_name}")
    assert_not_nil new_page
    assert_not_nil new_page.checkout
    assert_not_nil new_page.checkout.version
    co, v = new_page.checkout, new_page.checkout.version
    post :undocheckout, :checkout_id => new_page.checkout.id
    assert !Page.exists?(new_page.id)
    assert !Checkout.exists?(co.id)
    assert !Version.exists?(v.id)
    assert_redirected_to page.site.pages[0].url
    end
  
  # Shows:
  # 1. Creating a new version with some added text ####
  # 2. checkout, checkin van base version is rollback of CHANGE 1
  # 4. Cannot rollback checked out version
  def test_rollback
    get :new
    session['user'] = @tony
    page = WikiPage.find_by_presentation_name('Toolmentor Template')
    assert_equal 1, page.versions.size
    # 1
    post :checkout, :version => {:version_id => page.current_version.id, :note => 'test_rollback'}    
    assert_not_nil page.checkout
    co = page.checkout
    post :checkin, :checkout_id => co.id, :html => co.version.html.gsub('</body>', '####</body>')
    page.reload
    assert_nil page.checkout
    assert_match '####', page.html
    # 2
    post :rollback, :version => {:version_id => page.versions[0].id}    
    page.reload
    assert_nil page.checkout
    assert_equal 2, page.versions.last.version
    assert !page.versions.last.html.index('#### 1')
    assert !page.html.index('####')
  end
  
 end