move to AR
This commit is contained in:
parent
c4b7b2d9f2
commit
26c046cdfa
51 changed files with 2345 additions and 516 deletions
202
Rakefile
Normal file
202
Rakefile
Normal file
|
@ -0,0 +1,202 @@
|
|||
require 'rake'
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
|
||||
$VERBOSE = nil
|
||||
TEST_CHANGES_SINCE = Time.now - 600
|
||||
|
||||
desc "Run all the tests on a fresh test database"
|
||||
task :default => [ :test_units, :test_functional ]
|
||||
|
||||
|
||||
desc 'Require application environment.'
|
||||
task :environment do
|
||||
unless defined? RAILS_ROOT
|
||||
require File.dirname(__FILE__) + '/config/environment'
|
||||
end
|
||||
end
|
||||
|
||||
desc "Generate API documentation, show coding stats"
|
||||
task :doc => [ :appdoc, :stats ]
|
||||
|
||||
|
||||
# Look up tests for recently modified sources.
|
||||
def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
|
||||
FileList[source_pattern].map do |path|
|
||||
if File.mtime(path) > touched_since
|
||||
test = "#{test_path}/#{File.basename(path, '.rb')}_test.rb"
|
||||
test if File.exists?(test)
|
||||
end
|
||||
end.compact
|
||||
end
|
||||
|
||||
desc 'Test recent changes.'
|
||||
Rake::TestTask.new(:recent => [ :clone_structure_to_test ]) do |t|
|
||||
since = TEST_CHANGES_SINCE
|
||||
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
|
||||
recent_tests('app/models/*.rb', 'test/unit', since) +
|
||||
recent_tests('app/controllers/*.rb', 'test/functional', since)
|
||||
|
||||
t.libs << 'test'
|
||||
t.verbose = true
|
||||
t.test_files = touched.uniq
|
||||
end
|
||||
task :test_recent => [ :clone_structure_to_test ]
|
||||
|
||||
desc "Run the unit tests in test/unit"
|
||||
Rake::TestTask.new("test_units") { |t|
|
||||
t.libs << "test"
|
||||
t.pattern = 'test/unit/**/*_test.rb'
|
||||
t.verbose = true
|
||||
}
|
||||
task :test_units => [ :clone_structure_to_test ]
|
||||
|
||||
desc "Run the functional tests in test/functional"
|
||||
Rake::TestTask.new("test_functional") { |t|
|
||||
t.libs << "test"
|
||||
t.pattern = 'test/functional/**/*_test.rb'
|
||||
t.verbose = true
|
||||
}
|
||||
task :test_functional => [ :clone_structure_to_test ]
|
||||
|
||||
desc "Generate documentation for the application"
|
||||
Rake::RDocTask.new("appdoc") { |rdoc|
|
||||
rdoc.rdoc_dir = 'doc/app'
|
||||
rdoc.title = "Rails Application Documentation"
|
||||
rdoc.options << '--line-numbers --inline-source'
|
||||
rdoc.rdoc_files.include('doc/README_FOR_APP')
|
||||
rdoc.rdoc_files.include('app/**/*.rb')
|
||||
}
|
||||
|
||||
desc "Generate documentation for the Rails framework"
|
||||
Rake::RDocTask.new("apidoc") { |rdoc|
|
||||
rdoc.rdoc_dir = 'doc/api'
|
||||
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
||||
rdoc.title = "Rails Framework Documentation"
|
||||
rdoc.options << '--line-numbers --inline-source'
|
||||
rdoc.rdoc_files.include('README')
|
||||
rdoc.rdoc_files.include('CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
|
||||
rdoc.rdoc_files.include('vendor/rails/activerecord/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
|
||||
rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/api/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/client/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/container/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/dispatcher/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/protocol/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/support/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/activesupport/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/activesupport/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
|
||||
}
|
||||
|
||||
desc "Report code statistics (KLOCs, etc) from the application"
|
||||
task :stats => [ :environment ] do
|
||||
require 'code_statistics'
|
||||
CodeStatistics.new(
|
||||
["Helpers", "app/helpers"],
|
||||
["Controllers", "app/controllers"],
|
||||
["APIs", "app/apis"],
|
||||
["Components", "components"],
|
||||
["Functionals", "test/functional"],
|
||||
["Models", "app/models"],
|
||||
["Units", "test/unit"]
|
||||
).to_s
|
||||
end
|
||||
|
||||
desc "Recreate the test databases from the development structure"
|
||||
task :clone_structure_to_test => [ :db_structure_dump, :purge_test_database ] do
|
||||
abcs = ActiveRecord::Base.configurations
|
||||
case abcs["test"]["adapter"]
|
||||
when "mysql"
|
||||
ActiveRecord::Base.establish_connection(:test)
|
||||
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
|
||||
IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
|
||||
ActiveRecord::Base.connection.execute(table)
|
||||
end
|
||||
when "postgresql"
|
||||
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
|
||||
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
|
||||
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
|
||||
`psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
|
||||
when "sqlite", "sqlite3"
|
||||
`#{abcs[RAILS_ENV]["adapter"]} #{abcs["test"]["dbfile"]} < db/#{RAILS_ENV}_structure.sql`
|
||||
when "sqlserver"
|
||||
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
|
||||
else
|
||||
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Dump the database structure to a SQL file"
|
||||
task :db_structure_dump => :environment do
|
||||
abcs = ActiveRecord::Base.configurations
|
||||
case abcs[RAILS_ENV]["adapter"]
|
||||
when "mysql"
|
||||
ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
|
||||
File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
|
||||
when "postgresql"
|
||||
ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
|
||||
ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
|
||||
ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
|
||||
`pg_dump -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{abcs[RAILS_ENV]["database"]}`
|
||||
when "sqlite", "sqlite3"
|
||||
`#{abcs[RAILS_ENV]["adapter"]} #{abcs[RAILS_ENV]["dbfile"]} .schema > db/#{RAILS_ENV}_structure.sql`
|
||||
when "sqlserver"
|
||||
`scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
|
||||
`scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
|
||||
else
|
||||
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Empty the test database"
|
||||
task :purge_test_database => :environment do
|
||||
abcs = ActiveRecord::Base.configurations
|
||||
case abcs["test"]["adapter"]
|
||||
when "mysql"
|
||||
ActiveRecord::Base.establish_connection(:test)
|
||||
ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
|
||||
when "postgresql"
|
||||
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
|
||||
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
|
||||
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
|
||||
`dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
|
||||
`createdb -T template0 -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
|
||||
when "sqlite","sqlite3"
|
||||
File.delete(abcs["test"]["dbfile"]) if File.exist?(abcs["test"]["dbfile"])
|
||||
when "sqlserver"
|
||||
dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
|
||||
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
|
||||
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
|
||||
else
|
||||
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Clears all *.log files in log/"
|
||||
task :clear_logs => :environment do
|
||||
FileList["log/*.log"].each do |log_file|
|
||||
f = File.open(log_file, "w")
|
||||
f.close
|
||||
end
|
||||
end
|
||||
|
||||
desc "Migrate the database according to the migrate scripts in db/migrate (only supported on PG/MySQL). A specific version can be targetted with VERSION=x"
|
||||
task :migrate => :environment do
|
||||
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/db/migrate/', ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
||||
end
|
|
@ -46,7 +46,6 @@ class AdminController < ApplicationController
|
|||
end
|
||||
|
||||
def edit_web
|
||||
|
||||
system_password = @params['system_password']
|
||||
if system_password
|
||||
# form submitted
|
||||
|
@ -67,6 +66,7 @@ class AdminController < ApplicationController
|
|||
flash[:info] = "Web '#{@params['address']}' was successfully updated"
|
||||
redirect_home(@params['address'])
|
||||
rescue Instiki::ValidationError => e
|
||||
logger.warn e.message
|
||||
@error = e.message
|
||||
# and re-render the same template again
|
||||
end
|
||||
|
|
|
@ -10,12 +10,12 @@ class ApplicationController < ActionController::Base
|
|||
# a global variable is used here because Rails reloads controller and model classes in the
|
||||
# development environment; therefore, storing it as a class variable does not work
|
||||
# class variable is, anyway, not much different from a global variable
|
||||
$instiki_wiki_service = the_wiki
|
||||
#$instiki_wiki_service = the_wiki
|
||||
logger.debug("Wiki service: #{the_wiki.to_s}")
|
||||
end
|
||||
|
||||
def self.wiki
|
||||
$instiki_wiki_service
|
||||
Wiki.new
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -146,7 +146,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def wiki
|
||||
$instiki_wiki_service
|
||||
self.class.wiki
|
||||
end
|
||||
|
||||
def needs_authorization?(action)
|
||||
|
|
|
@ -78,7 +78,7 @@ class FileController < ApplicationController
|
|||
return false
|
||||
end
|
||||
|
||||
unless @web.allow_uploads
|
||||
unless @web.allow_uploads?
|
||||
render_text 'File uploads are blocked by the webmaster', '403 Forbidden'
|
||||
return false
|
||||
end
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
require 'application'
|
||||
require 'fileutils'
|
||||
require 'redcloth_for_tex'
|
||||
require 'parsedate'
|
||||
|
@ -156,7 +155,7 @@ class WikiController < ApplicationController
|
|||
end
|
||||
|
||||
def published
|
||||
if @web.published
|
||||
if @web.published?
|
||||
@page = wiki.read_page(@web_name, @page_name || 'HomePage')
|
||||
else
|
||||
redirect_home
|
||||
|
@ -270,7 +269,7 @@ class WikiController < ApplicationController
|
|||
end
|
||||
|
||||
def export_web_to_tex(file_path)
|
||||
@tex_content = table_of_contents(@web.pages['HomePage'].content, render_tex_web)
|
||||
@tex_content = table_of_contents(@web.page('HomePage').content, render_tex_web)
|
||||
File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex_web')) }
|
||||
end
|
||||
|
||||
|
@ -342,7 +341,7 @@ class WikiController < ApplicationController
|
|||
end
|
||||
|
||||
def rss_with_content_allowed?
|
||||
@web.password.nil? or @web.published
|
||||
@web.password.nil? or @web.published?
|
||||
end
|
||||
|
||||
def truncate(text, length = 30, truncate_string = '...')
|
||||
|
|
|
@ -1,4 +1,125 @@
|
|||
class Page < ActiveRecord::Base
|
||||
belongs_to :web
|
||||
has_many :pages
|
||||
end
|
||||
has_many :revisions, :order => 'number'
|
||||
has_one :current_revision, :class_name => 'Revision', :order => 'number DESC'
|
||||
|
||||
def revise(content, created_at, author)
|
||||
revisions_size = new_record? ? 0 : revisions.size
|
||||
if (revisions_size > 0) and content == current_revision.content
|
||||
raise Instiki::ValidationError.new(
|
||||
"You have tried to save page '#{name}' without changing its content")
|
||||
end
|
||||
|
||||
author = Author.new(author.to_s) unless author.is_a?(Author)
|
||||
|
||||
# Try to render content to make sure that markup engine can take it,
|
||||
# before addin a revision to the page
|
||||
Revision.new(:page => self, :content => content, :created_at => created_at, :author => author).force_rendering
|
||||
|
||||
# A user may change a page, look at it and make some more changes - several times.
|
||||
# Not to record every such iteration as a new revision, if the previous revision was done
|
||||
# by the same author, not more than 30 minutes ago, then update the last revision instead of
|
||||
# creating a new one
|
||||
if (revisions_size > 0) && continous_revision?(created_at, author)
|
||||
current_revision.update_attributes(:created_at => created_at, :content => content)
|
||||
else
|
||||
Revision.create(:page => self, :content => content, :created_at => created_at, :author => author)
|
||||
end
|
||||
|
||||
self.created_at = created_at
|
||||
save
|
||||
web.refresh_pages_with_references(name) if revisions_size == 0
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def rollback(revision_number, created_at, author_ip = nil)
|
||||
roll_back_revision = Revision.find(:first, :conditions => ['page_id = ? AND number = ?', id, revision_number])
|
||||
revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
|
||||
end
|
||||
|
||||
def revisions?
|
||||
revisions.size > 1
|
||||
end
|
||||
|
||||
def revised_on
|
||||
created_on
|
||||
end
|
||||
|
||||
def in_category?(cat)
|
||||
cat.nil? || cat.empty? || categories.include?(cat)
|
||||
end
|
||||
|
||||
def categories
|
||||
display_content.find_chunks(Category).map { |cat| cat.list }.flatten
|
||||
end
|
||||
|
||||
def authors
|
||||
revisions.collect { |rev| rev.author }
|
||||
end
|
||||
|
||||
def references
|
||||
web.select.pages_that_reference(name)
|
||||
end
|
||||
|
||||
def linked_from
|
||||
web.select.pages_that_link_to(name)
|
||||
end
|
||||
|
||||
def included_from
|
||||
web.select.pages_that_include(name)
|
||||
end
|
||||
|
||||
# Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
|
||||
def plain_name
|
||||
web.brackets_only? ? name : WikiWords.separate(name)
|
||||
end
|
||||
|
||||
# used to build chunk ids.
|
||||
#def id
|
||||
# @id ||= name.unpack('H*').first
|
||||
#end
|
||||
|
||||
def link(options = {})
|
||||
web.make_link(name, nil, options)
|
||||
end
|
||||
|
||||
def author_link(options = {})
|
||||
web.make_link(author, nil, options)
|
||||
end
|
||||
|
||||
LOCKING_PERIOD = 30.minutes
|
||||
|
||||
def lock(time, locked_by)
|
||||
update_attributes(:locked_at => time, :locked_by => locked_by)
|
||||
end
|
||||
|
||||
def lock_duration(time)
|
||||
((time - locked_at) / 60).to_i unless locked_at.nil?
|
||||
end
|
||||
|
||||
def unlock
|
||||
update_attribute(:locked_at, nil)
|
||||
end
|
||||
|
||||
def locked?(comparison_time)
|
||||
locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def continous_revision?(created_at, author)
|
||||
current_revision.author == author && current_revision.created_at + 30.minutes > created_at
|
||||
end
|
||||
|
||||
# Forward method calls to the current revision, so the page responds to all revision calls
|
||||
def method_missing(method_id, *args, &block)
|
||||
method_name = method_id.to_s
|
||||
# Perform a hand-off to AR::Base#method_missing
|
||||
if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
|
||||
super(method_id, *args, &block)
|
||||
else
|
||||
current_revision.send(method_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,122 @@
|
|||
require 'diff'
|
||||
class Revision < ActiveRecord::Base
|
||||
belongs_to :page
|
||||
end
|
||||
composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
|
||||
|
||||
def created_on
|
||||
created_at.to_date
|
||||
end
|
||||
|
||||
def pretty_created_at
|
||||
# Must use DateTime because Time doesn't support %e on at least some platforms
|
||||
DateTime.new(
|
||||
created_at.year, created_at.mon, created_at.day, created_at.hour, created_at.min
|
||||
).strftime "%B %e, %Y %H:%M"
|
||||
end
|
||||
|
||||
# todo: drop next_revision, previuous_revision and number from here - unused code
|
||||
def next_revision
|
||||
Revision.find_by_number_and_page_id(number+1, page_id)
|
||||
end
|
||||
|
||||
def previous_revision
|
||||
@previous_revions ||= number > 0 ? Revision.find_by_number_and_page_id(number-1, page_id) : nil
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiIncludes present in the content of this revision.
|
||||
def wiki_includes
|
||||
unless @wiki_includes_cache
|
||||
chunks = display_content.find_chunks(Include)
|
||||
@wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_includes_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiReferences present in the content of this revision.
|
||||
def wiki_references
|
||||
unless @wiki_references_cache
|
||||
chunks = display_content.find_chunks(WikiChunk::WikiReference)
|
||||
@wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_references_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision.
|
||||
def wiki_words
|
||||
unless @wiki_words_cache
|
||||
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
|
||||
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_words_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision.
|
||||
# that already exists as a page in the web.
|
||||
def existing_pages
|
||||
wiki_words.select { |wiki_word| page.web.page(wiki_word) }
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision
|
||||
# that *doesn't* already exists as a page in the web.
|
||||
def unexisting_pages
|
||||
wiki_words - existing_pages
|
||||
end
|
||||
|
||||
# Explicit check for new type of display cache with chunks_by_type method.
|
||||
# Ensures new version works with older snapshots.
|
||||
def display_content
|
||||
unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
|
||||
@display_cache = WikiContent.new(self)
|
||||
@display_cache.render!
|
||||
end
|
||||
@display_cache
|
||||
end
|
||||
|
||||
def display_diff
|
||||
previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
|
||||
end
|
||||
|
||||
def clear_display_cache
|
||||
@wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
|
||||
@wiki_references_cache = nil
|
||||
end
|
||||
|
||||
def display_published
|
||||
unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
|
||||
@published_cache = WikiContent.new(self, {:mode => :publish})
|
||||
@published_cache.render!
|
||||
end
|
||||
@published_cache
|
||||
end
|
||||
|
||||
def display_content_for_export
|
||||
WikiContent.new(self, {:mode => :export} ).render!
|
||||
end
|
||||
|
||||
def force_rendering
|
||||
begin
|
||||
display_content.render!
|
||||
rescue => e
|
||||
logger.error "Failed rendering page #{@name}"
|
||||
logger.error e
|
||||
message = e.message
|
||||
# substitute content with an error message
|
||||
self.content = <<-EOL
|
||||
<p>Markup engine has failed to render this page, raising the following error:</p>
|
||||
<p>#{message}</p>
|
||||
<pre>#{self.content}</pre>
|
||||
EOL
|
||||
clear_display_cache
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
before_create :set_revision_number
|
||||
after_create :force_rendering
|
||||
after_save :clear_display_cache
|
||||
|
||||
def set_revision_number
|
||||
self.number = self.class.count(['page_id = ?', page_id]) + 1
|
||||
end
|
||||
end
|
||||
|
|
4
app/models/system.rb
Normal file
4
app/models/system.rb
Normal file
|
@ -0,0 +1,4 @@
|
|||
class System < ActiveRecord::Base
|
||||
set_table_name 'system'
|
||||
validates_presence_of :password
|
||||
end
|
|
@ -1,3 +1,173 @@
|
|||
require 'cgi'
|
||||
|
||||
class Web < ActiveRecord::Base
|
||||
has_many :pages
|
||||
end
|
||||
has_many :pages#, :include => [:current_revision, :web]
|
||||
|
||||
def wiki
|
||||
Wiki.new
|
||||
end
|
||||
|
||||
def file_yard
|
||||
@file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
|
||||
end
|
||||
|
||||
def settings_changed?(markup, safe_mode, brackets_only)
|
||||
self.markup != markup ||
|
||||
self.safe_mode != safe_mode ||
|
||||
self.brackets_only != brackets_only
|
||||
end
|
||||
|
||||
def add_page(name, content, created_at, author)
|
||||
page = page(name) || Page.new(:web => self, :name => name)
|
||||
page.revise(content, created_at, author)
|
||||
end
|
||||
|
||||
def authors
|
||||
select.authors
|
||||
end
|
||||
|
||||
def categories
|
||||
select.map { |page| page.categories }.flatten.uniq.sort
|
||||
end
|
||||
|
||||
def page(name)
|
||||
pages.find(:first, :conditions => ['name = ?', name])
|
||||
end
|
||||
|
||||
def has_page?(name)
|
||||
Page.count(['web_id = ? AND name = ?', id, name]) > 0
|
||||
end
|
||||
|
||||
def has_file?(name)
|
||||
wiki.file_yard(self).has_file?(name)
|
||||
end
|
||||
|
||||
def markup
|
||||
read_attribute('markup').to_sym
|
||||
end
|
||||
|
||||
def make_file_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode
|
||||
when :export
|
||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
|
||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||
when :publish
|
||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{base_url}/published/#{link}\">#{text}</a>"
|
||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||
else
|
||||
if has_file?(name)
|
||||
"<a class=\"existingWikiWord\" href=\"#{base_url}/file/#{link}\">#{text}</a>"
|
||||
else
|
||||
"<span class=\"newWikiWord\">#{text}<a href=\"#{base_url}/file/#{link}\">?</a></span>"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Create a link for the given page name and link text based
|
||||
# on the render mode in options and whether the page exists
|
||||
# in the this web.
|
||||
# The links a relative, and will work only if displayed on another WikiPage.
|
||||
# It should not be used in menus, templates and such - instead, use link_to_page helper
|
||||
def make_link(name, text = nil, options = {})
|
||||
text = CGI.escapeHTML(text || WikiWords.separate(name))
|
||||
mode = options[:mode] || :show
|
||||
base_url = options[:base_url] || '..'
|
||||
link_type = options[:link_type] || :show
|
||||
case link_type.to_sym
|
||||
when :show
|
||||
make_page_link(mode, name, text, base_url)
|
||||
when :file
|
||||
make_file_link(mode, name, text, base_url)
|
||||
when :pic
|
||||
make_pic_link(mode, name, text, base_url)
|
||||
else
|
||||
raise "Unknown link type: #{link_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def make_page_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode.to_sym
|
||||
when :export
|
||||
if has_page?(name) then %{<a class="existingWikiWord" href="#{link}.html">#{text}</a>}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
when :publish
|
||||
if has_page?(name) then %{<a class="existingWikiWord" href="#{base_url}/published/#{link}">#{text}</a>}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
else
|
||||
if has_page?(name)
|
||||
%{<a class="existingWikiWord" href="#{base_url}/show/#{link}">#{text}</a>}
|
||||
else
|
||||
%{<span class="newWikiWord">#{text}<a href="#{base_url}/show/#{link}">?</a></span>}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def make_pic_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode.to_sym
|
||||
when :export
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
|
||||
else %{<img alt="#{text}" src="no image" />} end
|
||||
when :publish
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
else
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{base_url}/pic/#{link}" />}
|
||||
else %{<span class="newWikiWord">#{text}<a href="#{base_url}/pic/#{link}">?</a></span>} end
|
||||
end
|
||||
end
|
||||
|
||||
# Clears the display cache for all the pages with references to
|
||||
def refresh_pages_with_references(page_name)
|
||||
#select.pages_that_reference(page_name).each { |page|
|
||||
# page.revisions.each { |revision| revision.clear_display_cache }
|
||||
#}
|
||||
end
|
||||
|
||||
def refresh_revisions
|
||||
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
|
||||
end
|
||||
|
||||
def remove_pages(pages_to_be_removed)
|
||||
pages_to_be_removed.each { |p| p.destroy }
|
||||
end
|
||||
|
||||
def revised_on
|
||||
select.most_recent_revision
|
||||
end
|
||||
|
||||
def select(&condition)
|
||||
PageSet.new(self, pages, condition)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns an array of all the wiki words in any current revision
|
||||
def wiki_words
|
||||
pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
||||
end
|
||||
|
||||
# Returns an array of all the page names on this web
|
||||
def page_names
|
||||
pages.map { |p| p.name }
|
||||
end
|
||||
|
||||
protected
|
||||
before_save :sanitize_markup
|
||||
before_validation :validate_address
|
||||
validates_uniqueness_of :address
|
||||
validates_length_of :color, :in => 3..6
|
||||
|
||||
def sanitize_markup
|
||||
self.markup = markup.to_s
|
||||
end
|
||||
|
||||
def validate_address
|
||||
unless address == CGI.escape(address)
|
||||
self.errors.add(:address, 'should contain only valid URI characters')
|
||||
raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</li>
|
||||
<% end %></ul>
|
||||
|
||||
<% if @web.count_pages %>
|
||||
<% if @web.count_pages? %>
|
||||
<% total_chars = @pages_in_category.characters %>
|
||||
<p><small>All content: <%= total_chars %> chars / <%= sprintf("%-.1f", (total_chars / 2275 )) %> pages</small></p>
|
||||
<% end %>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
|
||||
by <%= @page.author_link %>
|
||||
<%= "(#{@page.author.ip})" if @page.author.respond_to?(:ip) %>
|
||||
<% if @web.count_pages %>
|
||||
<% if @web.count_pages? %>
|
||||
<% total_chars = @page.content.length %>
|
||||
(<%= total_chars %> characters / <%= sprintf("%-.1f", (total_chars / 2275 rescue 0)) %> pages)
|
||||
<% end %>
|
||||
|
|
|
@ -1,30 +1,65 @@
|
|||
# SQLite is enabled by default. Remember to change the dbfile path.
|
||||
production:
|
||||
adapter: sqlite3
|
||||
dbfile: /tmp/instiki_prod.db
|
||||
|
||||
# Uncomment this section for MySQL:
|
||||
# production:
|
||||
# adapter: mysql
|
||||
# host: localhost
|
||||
# database: instiki
|
||||
# username: instiki
|
||||
# password: pass
|
||||
|
||||
# Uncomment this section for PostgreSQL:
|
||||
# production:
|
||||
# adapter: postgresql
|
||||
# host: localhost
|
||||
# database: instiki
|
||||
# username: instiki
|
||||
# password: pass
|
||||
|
||||
# The following settings are only used for testing and development.
|
||||
dbfile: db/prod.db
|
||||
development:
|
||||
adapter: sqlite3
|
||||
dbfile: /tmp/instiki_dev.db
|
||||
|
||||
dbfile: db/dev.db
|
||||
test:
|
||||
adapter: sqlite3
|
||||
dbfile: /tmp/instiki_test.db
|
||||
dbfile: db/test.db
|
||||
|
||||
# Sample Sqlite 2 Config
|
||||
#production:
|
||||
# adapter: sqlite
|
||||
# dbfile: db/prod.db
|
||||
#development:
|
||||
# adapter: sqlite
|
||||
# dbfile: db/dev.db
|
||||
#test:
|
||||
# adapter: sqlite
|
||||
# dbfile: db/test.db
|
||||
|
||||
# Sample Postgresql Config
|
||||
#production:
|
||||
# adapter: postgresql
|
||||
# host: localhost
|
||||
# database: instiki_prod
|
||||
# username: user
|
||||
# password: pass
|
||||
#
|
||||
#development:
|
||||
# adapter: postgresql
|
||||
# host: localhost
|
||||
# database: instiki_dev
|
||||
# username: user
|
||||
# password: pass
|
||||
#
|
||||
#test:
|
||||
# adapter: postgresql
|
||||
# host: localhost
|
||||
# database: instiki_test
|
||||
# username: user
|
||||
# password: pass
|
||||
|
||||
# Sample MySQL Config
|
||||
#production:
|
||||
# adapter: mysql
|
||||
# host: localhost
|
||||
# database: instiki_prod
|
||||
# username: user
|
||||
# password: pass
|
||||
#
|
||||
#development:
|
||||
# adapter: mysql
|
||||
# host: localhost
|
||||
# database: instiki_dev
|
||||
# username: user
|
||||
# password: pass
|
||||
#
|
||||
#test:
|
||||
# adapter: mysql
|
||||
# host: localhost
|
||||
# database: instiki_test
|
||||
# username: user
|
||||
# password: pass
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ require 'rubygems' unless File.directory?("#{RAILS_ROOT}/vendor/rails")
|
|||
require 'active_support'
|
||||
require 'active_record'
|
||||
require 'action_controller'
|
||||
require 'action_mailer'
|
||||
require 'action_web_service'
|
||||
|
||||
# Environment-specific configuration.
|
||||
require_dependency "environments/#{RAILS_ENV}"
|
||||
|
|
|
@ -2,4 +2,3 @@ Dependencies.mechanism = :require
|
|||
ActionController::Base.consider_all_requests_local = true
|
||||
ActionController::Base.perform_caching = false
|
||||
BREAKPOINT_SERVER_PORT = 42531
|
||||
$instiki_debug_logging = true
|
||||
|
|
|
@ -1,15 +1,4 @@
|
|||
Dependencies.mechanism = :require
|
||||
ActionController::Base.consider_all_requests_local = true
|
||||
ActionController::Base.perform_caching = false
|
||||
|
||||
require 'fileutils'
|
||||
FileUtils.mkdir_p(RAILS_ROOT + "/log")
|
||||
|
||||
unless defined? TEST_LOGGER
|
||||
timestamp = Time.now.strftime('%Y%m%d%H%M%S')
|
||||
log_name = RAILS_ROOT + "/log/instiki_test.#{timestamp}.log"
|
||||
$stderr.puts "To see the Rails log:\n less #{log_name}"
|
||||
|
||||
TEST_LOGGER = ActionController::Base.logger = Logger.new(log_name)
|
||||
$instiki_debug_logging = true
|
||||
end
|
||||
FileYard.restrict_upload_access = false
|
40
db/development_structure.sql
Normal file
40
db/development_structure.sql
Normal file
|
@ -0,0 +1,40 @@
|
|||
CREATE TABLE pages (
|
||||
id INTEGER PRIMARY KEY,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
web_id INTEGER NOT NULL,
|
||||
locked_by VARCHAR(60),
|
||||
name VARCHAR(60),
|
||||
locked_at DATETIME
|
||||
);
|
||||
CREATE TABLE revisions (
|
||||
id INTEGER PRIMARY KEY,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
page_id INTEGER NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
author VARCHAR(60),
|
||||
ip VARCHAR(60),
|
||||
number INTEGER
|
||||
);
|
||||
CREATE TABLE system (
|
||||
id INTEGER PRIMARY KEY,
|
||||
'password' VARCHAR(60)
|
||||
);
|
||||
CREATE TABLE webs (
|
||||
id INTEGER PRIMARY KEY,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
name VARCHAR(60) NOT NULL,
|
||||
address VARCHAR(60) NOT NULL,
|
||||
'password' VARCHAR(60),
|
||||
additional_style VARCHAR(255),
|
||||
allow_uploads INTEGER DEFAULT '1',
|
||||
published INTEGER DEFAULT '0',
|
||||
count_pages INTEGER DEFAULT '0',
|
||||
markup VARCHAR(50) DEFAULT 'textile',
|
||||
color VARCHAR(6) DEFAULT '008B26',
|
||||
max_upload_size INTEGER DEFAULT 100,
|
||||
safe_mode INTEGER DEFAULT '0',
|
||||
brackets_only INTEGER DEFAULT '0'
|
||||
);
|
|
@ -2,5 +2,8 @@ CREATE TABLE pages (
|
|||
id <%= @pk %>,
|
||||
created_at <%= @datetime %> NOT NULL,
|
||||
updated_at <%= @datetime %> NOT NULL,
|
||||
web_id INTEGER NOT NULL
|
||||
) <%= create_options %>;
|
||||
web_id INTEGER NOT NULL,
|
||||
locked_by VARCHAR(60),
|
||||
name VARCHAR(60),
|
||||
locked_at <%= @datetime %>
|
||||
) <%= create_options %>;
|
|
@ -1,7 +1,10 @@
|
|||
CREATE TABLE revisions (
|
||||
id <%= @pk %>,
|
||||
created_at <%= @datetime %> NOT NULL,
|
||||
updated_at <%= @datetime %> NOT NULL,
|
||||
page_id INTEGER NOT NULL,
|
||||
content TEXT NOT NULL
|
||||
) <%= create_options %>;
|
||||
id <%= @pk %>,
|
||||
created_at <%= @datetime %> NOT NULL,
|
||||
updated_at <%= @datetime %> NOT NULL,
|
||||
page_id INTEGER NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
author VARCHAR(60),
|
||||
ip VARCHAR(60),
|
||||
number INTEGER
|
||||
) <%= create_options %>;
|
43
db/schema.postgre.sql
Normal file
43
db/schema.postgre.sql
Normal file
|
@ -0,0 +1,43 @@
|
|||
CREATE TABLE pages (
|
||||
id serial primary key,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
web_id integer NOT NULL,
|
||||
locked_by character varying(60),
|
||||
name character varying(60),
|
||||
locked_at timestamp without time zone
|
||||
);
|
||||
|
||||
CREATE TABLE revisions (
|
||||
id serial primary key,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
page_id integer NOT NULL,
|
||||
content text NOT NULL,
|
||||
author character varying(60),
|
||||
ip character varying(60),
|
||||
number integer
|
||||
);
|
||||
|
||||
CREATE TABLE system (
|
||||
id serial primary key,
|
||||
"password" character varying(60)
|
||||
);
|
||||
|
||||
CREATE TABLE webs (
|
||||
id serial primary key,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
name character varying(60) NOT NULL,
|
||||
address character varying(60) NOT NULL,
|
||||
"password" character varying(60),
|
||||
additional_style character varying(255),
|
||||
allow_uploads boolean DEFAULT true,
|
||||
published boolean DEFAULT false,
|
||||
count_pages boolean DEFAULT false,
|
||||
markup character varying(50) DEFAULT 'textile'::character varying,
|
||||
color character varying(6) DEFAULT '008B26'::character varying,
|
||||
max_upload_size integer DEFAULT 100,
|
||||
safe_mode boolean DEFAULT false,
|
||||
brackets_only boolean DEFAULT false
|
||||
);
|
4
db/system.erbsql
Normal file
4
db/system.erbsql
Normal file
|
@ -0,0 +1,4 @@
|
|||
CREATE TABLE system (
|
||||
id <%= @pk %>,
|
||||
<%= db_quote('password') %> VARCHAR(60)
|
||||
) <%= create_options %>;
|
|
@ -3,5 +3,15 @@ CREATE TABLE webs (
|
|||
created_at <%= @datetime %> NOT NULL,
|
||||
updated_at <%= @datetime %> NOT NULL,
|
||||
name VARCHAR(60) NOT NULL,
|
||||
address VARCHAR(60) NOT NULL
|
||||
) <%= create_options %>;
|
||||
address VARCHAR(60) NOT NULL,
|
||||
<%= db_quote('password') %> VARCHAR(60),
|
||||
additional_style VARCHAR(255),
|
||||
allow_uploads <%= @boolean %> DEFAULT '1',
|
||||
published <%= @boolean %> DEFAULT '0',
|
||||
count_pages <%= @boolean %> DEFAULT '0',
|
||||
markup VARCHAR(50) DEFAULT 'textile',
|
||||
color VARCHAR(6) DEFAULT '008B26',
|
||||
max_upload_size INTEGER DEFAULT 100,
|
||||
safe_mode <%= @boolean %> DEFAULT '0',
|
||||
brackets_only <%= @boolean %> DEFAULT '0'
|
||||
) <%= create_options %>;
|
18
lib/author.rb
Normal file
18
lib/author.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
class Author < String
|
||||
attr_accessor :ip
|
||||
attr_reader :name
|
||||
def initialize(name, ip = nil)
|
||||
@ip = ip
|
||||
super(name)
|
||||
end
|
||||
|
||||
def name=(value)
|
||||
self.gsub!(/.+/, value)
|
||||
end
|
||||
|
||||
alias_method :name, :to_s
|
||||
|
||||
def <=>(other)
|
||||
name <=> other.to_s
|
||||
end
|
||||
end
|
|
@ -4,7 +4,7 @@ class ChunkTest < Test::Unit::TestCase
|
|||
|
||||
# Asserts a number of tests for the given type and text.
|
||||
def match(type, test_text, expected)
|
||||
pattern = type.pattern
|
||||
pattern = type.pattern
|
||||
assert_match(pattern, test_text)
|
||||
pattern =~ test_text # Previous assertion guarantees match
|
||||
chunk = type.new($~)
|
||||
|
|
|
@ -6,6 +6,17 @@ def create_options
|
|||
end
|
||||
end
|
||||
|
||||
def db_quote(column)
|
||||
case @db
|
||||
when 'postgresql'
|
||||
return "\"#{column}\""
|
||||
when 'sqlite', 'sqlite3'
|
||||
return "'#{column}'"
|
||||
when 'mysql'
|
||||
return "`#{column}`"
|
||||
end
|
||||
end
|
||||
|
||||
def db_structure(db)
|
||||
db.downcase!
|
||||
@db = db
|
||||
|
@ -13,12 +24,15 @@ def db_structure(db)
|
|||
when 'postgresql'
|
||||
@pk = 'SERIAL PRIMARY KEY'
|
||||
@datetime = 'TIMESTAMP'
|
||||
@boolean = "BOOLEAN"
|
||||
when 'sqlite', 'sqlite3'
|
||||
@pk = 'INTEGER PRIMARY KEY'
|
||||
@datetime = 'DATETIME'
|
||||
@boolean = "INTEGER"
|
||||
when 'mysql'
|
||||
@pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
|
||||
@datetime = 'DATETIME'
|
||||
@boolean = "TINYINT"
|
||||
@mysql_engine = 'InnoDB'
|
||||
else
|
||||
raise "Unknown db type #{db}"
|
||||
|
|
59
lib/file_yard.rb
Normal file
59
lib/file_yard.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
require 'fileutils'
|
||||
require 'instiki_errors'
|
||||
|
||||
class FileYard
|
||||
cattr_accessor :restrict_upload_access
|
||||
restrict_upload_access = true
|
||||
attr_reader :files_path
|
||||
|
||||
def initialize(files_path, max_upload_size)
|
||||
@files_path, @max_upload_size = files_path, max_upload_size
|
||||
FileUtils.mkdir_p(@files_path) unless File.exist?(@files_path)
|
||||
@files = Dir["#{@files_path}/*"].collect{|path| File.basename(path) if File.file?(path) }.compact
|
||||
end
|
||||
|
||||
def upload_file(name, io)
|
||||
sanitize_file_name(name)
|
||||
if io.kind_of?(Tempfile)
|
||||
io.close
|
||||
check_upload_size(io.size)
|
||||
File.chmod(600, file_path(name)) if File.exists? file_path(name)
|
||||
FileUtils.mv(io.path, file_path(name))
|
||||
else
|
||||
content = io.read
|
||||
check_upload_size(content.length)
|
||||
File.open(file_path(name), 'wb') { |f| f.write(content) }
|
||||
end
|
||||
# just in case, restrict read access and prohibit write access to the uploaded file
|
||||
FileUtils.chmod(0440, file_path(name)) if restrict_upload_access
|
||||
end
|
||||
|
||||
def files
|
||||
Dir["#{files_path}/*"].collect{|path| File.basename(path) if File.file?(path)}.compact
|
||||
end
|
||||
|
||||
def has_file?(name)
|
||||
files.include?(name)
|
||||
end
|
||||
|
||||
def file_path(name)
|
||||
"#{files_path}/#{name}"
|
||||
end
|
||||
|
||||
SANE_FILE_NAME = /[a-zA-Z0-9\-_\. ]{1,255}/
|
||||
|
||||
def sanitize_file_name(name)
|
||||
unless name =~ SANE_FILE_NAME or name == '.' or name == '..'
|
||||
raise Instiki::ValidationError.new("Invalid file name: '#{name}'.\n" +
|
||||
"Only latin characters, digits, dots, underscores, dashes and spaces are accepted.")
|
||||
end
|
||||
end
|
||||
|
||||
def check_upload_size(actual_upload_size)
|
||||
if actual_upload_size > @max_upload_size.kilobytes
|
||||
raise Instiki::ValidationError.new("Uploaded file size (#{actual_upload_size / 1024} " +
|
||||
"kbytes) exceeds the maximum (#{@max_upload_size} kbytes) set for this wiki")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
89
lib/page_set.rb
Normal file
89
lib/page_set.rb
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Container for a set of pages with methods for manipulation.
|
||||
|
||||
class PageSet < Array
|
||||
attr_reader :web
|
||||
|
||||
def initialize(web, pages = nil, condition = nil)
|
||||
@web = web
|
||||
# if pages is not specified, make a list of all pages in the web
|
||||
if pages.nil?
|
||||
super(web.pages)
|
||||
# otherwise use specified pages and condition to produce a set of pages
|
||||
elsif condition.nil?
|
||||
super(pages)
|
||||
else
|
||||
super(pages.select { |page| condition[page] })
|
||||
end
|
||||
end
|
||||
|
||||
def most_recent_revision
|
||||
self.map { |page| page.created_at }.max || Time.at(0)
|
||||
end
|
||||
|
||||
|
||||
def by_name
|
||||
PageSet.new(@web, sort_by { |page| page.name })
|
||||
end
|
||||
|
||||
alias :sort :by_name
|
||||
|
||||
def by_revision
|
||||
PageSet.new(@web, sort_by { |page| page.created_at }).reverse
|
||||
end
|
||||
|
||||
def pages_that_reference(page_name)
|
||||
self.select { |page| page.wiki_references.include?(page_name) }
|
||||
end
|
||||
|
||||
def pages_that_link_to(page_name)
|
||||
self.select { |page| page.wiki_words.include?(page_name) }
|
||||
end
|
||||
|
||||
def pages_that_include(page_name)
|
||||
self.select { |page| page.wiki_includes.include?(page_name) }
|
||||
end
|
||||
|
||||
def pages_authored_by(author)
|
||||
self.select { |page| page.authors.include?(author) }
|
||||
end
|
||||
|
||||
def characters
|
||||
self.inject(0) { |chars,page| chars += page.content.size }
|
||||
end
|
||||
|
||||
# Returns all the orphaned pages in this page set. That is,
|
||||
# pages in this set for which there is no reference in the web.
|
||||
# The HomePage and author pages are always assumed to have
|
||||
# references and so cannot be orphans
|
||||
# Pages that refer to themselves and have no links from outside are oprphans.
|
||||
def orphaned_pages
|
||||
never_orphans = web.select.authors + ['HomePage']
|
||||
self.select { |page|
|
||||
if never_orphans.include? page.name
|
||||
false
|
||||
else
|
||||
references = pages_that_reference(page.name)
|
||||
references.empty? or references == [page]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# Returns all the wiki words in this page set for which
|
||||
# there are no pages in this page set's web
|
||||
def wanted_pages
|
||||
wiki_words - web.select.names
|
||||
end
|
||||
|
||||
def names
|
||||
self.map { |page| page.name }
|
||||
end
|
||||
|
||||
def wiki_words
|
||||
self.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
||||
end
|
||||
|
||||
def authors
|
||||
self.inject([]) { |authors, page| authors << page.authors }.flatten.uniq.sort
|
||||
end
|
||||
|
||||
end
|
96
lib/wiki.rb
Normal file
96
lib/wiki.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
class Wiki
|
||||
cattr_accessor :storage_path, :logger
|
||||
self.storage_path = "#{RAILS_ROOT}/storage/"
|
||||
self.logger = RAILS_DEFAULT_LOGGER
|
||||
|
||||
def authenticate(password)
|
||||
password == (system.password || 'instiki')
|
||||
end
|
||||
|
||||
def create_web(name, address, password = nil)
|
||||
@webs = nil
|
||||
Web.create(:name => name, :address => address, :password => password)
|
||||
end
|
||||
|
||||
def delete_web(address)
|
||||
web = Web.find_by_address(address)
|
||||
unless web.nil?
|
||||
web.destroy
|
||||
@webs = nil
|
||||
end
|
||||
end
|
||||
|
||||
def file_yard(web)
|
||||
web.file_yard
|
||||
end
|
||||
|
||||
def edit_web(old_address, new_address, name, markup, color, additional_style, safe_mode = false,
|
||||
password = nil, published = false, brackets_only = false, count_pages = false,
|
||||
allow_uploads = true, max_upload_size = nil)
|
||||
|
||||
if not (web = Web.find_by_address(old_address))
|
||||
raise Instiki::ValidationError.new("Web with address '#{old_address}' does not exist")
|
||||
end
|
||||
|
||||
web.refresh_revisions if web.settings_changed?(markup, safe_mode, brackets_only)
|
||||
web.update_attributes(:address => new_address, :name => name, :markup => markup, :color => color,
|
||||
:additional_style => additional_style, :safe_mode => safe_mode, :password => password, :published => published,
|
||||
:brackets_only => brackets_only, :count_pages => count_pages, :allow_uploads => allow_uploads, :max_upload_size => max_upload_size)
|
||||
@webs = nil
|
||||
raise Instiki::ValidationError.new("There is already a web with address '#{new_address}'") unless web.errors.on(:address).nil?
|
||||
web
|
||||
end
|
||||
|
||||
def read_page(web_address, page_name)
|
||||
self.class.logger.debug "Reading page '#{page_name}' from web '#{web_address}'"
|
||||
web = Web.find_by_address(web_address)
|
||||
if web.nil?
|
||||
self.class.logger.debug "Web '#{web_address}' not found"
|
||||
return nil
|
||||
else
|
||||
page = web.pages.find(:first, :conditions => ['name = ?', page_name])
|
||||
self.class.logger.debug "Page '#{page_name}' #{page.nil? ? 'not' : ''} found"
|
||||
return page
|
||||
end
|
||||
end
|
||||
|
||||
def remove_orphaned_pages(web_address)
|
||||
web = Web.find_by_address(web_address)
|
||||
web.remove_pages(web.select.orphaned_pages)
|
||||
end
|
||||
|
||||
def revise_page(web_address, page_name, content, revised_on, author)
|
||||
page = read_page(web_address, page_name)
|
||||
page.revise(content, revised_on, author)
|
||||
end
|
||||
|
||||
def rollback_page(web_address, page_name, revision_number, created_at, author_id = nil)
|
||||
page = read_page(web_address, page_name)
|
||||
page.rollback(revision_number, created_at, author_id)
|
||||
end
|
||||
|
||||
def setup(password, web_name, web_address)
|
||||
system.update_attribute(:password, password)
|
||||
create_web(web_name, web_address)
|
||||
end
|
||||
|
||||
def system
|
||||
@system ||= (System.find(:first) || System.create)
|
||||
end
|
||||
|
||||
def setup?
|
||||
Web.count > 0
|
||||
end
|
||||
|
||||
def webs
|
||||
@webs ||= Web.find(:all).inject({}) { |webs, web| webs.merge(web.address => web) }
|
||||
end
|
||||
|
||||
def storage_path
|
||||
self.class.storage_path
|
||||
end
|
||||
|
||||
def write_page(web_address, page_name, content, written_on, author)
|
||||
Web.find_by_address(web_address).add_page(page_name, content, written_on, author)
|
||||
end
|
||||
end
|
206
lib/wiki_content.rb
Normal file
206
lib/wiki_content.rb
Normal file
|
@ -0,0 +1,206 @@
|
|||
require 'cgi'
|
||||
require 'chunks/engines'
|
||||
require 'chunks/category'
|
||||
require 'chunks/include'
|
||||
require 'chunks/wiki'
|
||||
require 'chunks/literal'
|
||||
require 'chunks/uri'
|
||||
require 'chunks/nowiki'
|
||||
|
||||
# Wiki content is just a string that can process itself with a chain of
|
||||
# actions. The actions can modify wiki content so that certain parts of
|
||||
# it are protected from being rendered by later actions.
|
||||
#
|
||||
# When wiki content is rendered, it can be interrogated to find out
|
||||
# which chunks were rendered. This means things like categories, wiki
|
||||
# links, can be determined.
|
||||
#
|
||||
# Exactly how wiki content is rendered is determined by a number of
|
||||
# settings that are optionally passed in to a constructor. The current
|
||||
# options are:
|
||||
# * :engine
|
||||
# => The structural markup engine to use (Textile, Markdown, RDoc)
|
||||
# * :engine_opts
|
||||
# => A list of options to pass to the markup engines (safe modes, etc)
|
||||
# * :pre_engine_actions
|
||||
# => A list of render actions or chunks to be processed before the
|
||||
# markup engine is applied. By default this is:
|
||||
# Category, Include, URIChunk, WikiChunk::Link, WikiChunk::Word
|
||||
# * :post_engine_actions
|
||||
# => A list of render actions or chunks to apply after the markup
|
||||
# engine. By default these are:
|
||||
# Literal::Pre, Literal::Tags
|
||||
# * :mode
|
||||
# => How should the content be rendered? For normal display (show),
|
||||
# publishing (:publish) or export (:export)?
|
||||
|
||||
module ChunkManager
|
||||
attr_reader :chunks_by_type, :chunks_by_id, :chunks, :chunk_id
|
||||
|
||||
ACTIVE_CHUNKS = [ NoWiki, Category, WikiChunk::Link, URIChunk, LocalURIChunk,
|
||||
WikiChunk::Word ]
|
||||
|
||||
HIDE_CHUNKS = [ Literal::Pre, Literal::Tags ]
|
||||
|
||||
MASK_RE = {
|
||||
ACTIVE_CHUNKS => Chunk::Abstract.mask_re(ACTIVE_CHUNKS),
|
||||
HIDE_CHUNKS => Chunk::Abstract.mask_re(HIDE_CHUNKS)
|
||||
}
|
||||
|
||||
def init_chunk_manager
|
||||
@chunks_by_type = Hash.new
|
||||
Chunk::Abstract::derivatives.each{|chunk_type|
|
||||
@chunks_by_type[chunk_type] = Array.new
|
||||
}
|
||||
@chunks_by_id = Hash.new
|
||||
@chunks = []
|
||||
@chunk_id = 0
|
||||
end
|
||||
|
||||
def add_chunk(c)
|
||||
@chunks_by_type[c.class] << c
|
||||
@chunks_by_id[c.id] = c
|
||||
@chunks << c
|
||||
@chunk_id += 1
|
||||
end
|
||||
|
||||
def delete_chunk(c)
|
||||
@chunks_by_type[c.class].delete(c)
|
||||
@chunks_by_id.delete(c.id)
|
||||
@chunks.delete(c)
|
||||
end
|
||||
|
||||
def merge_chunks(other)
|
||||
other.chunks.each{|c| add_chunk(c)}
|
||||
end
|
||||
|
||||
def scan_chunkid(text)
|
||||
text.scan(MASK_RE[ACTIVE_CHUNKS]){|a| yield a[0] }
|
||||
end
|
||||
|
||||
def find_chunks(chunk_type)
|
||||
@chunks.select { |chunk| chunk.kind_of?(chunk_type) and chunk.rendered? }
|
||||
end
|
||||
|
||||
# for testing and WikiContentStub; we need a page_id even if we have no page
|
||||
def page_id
|
||||
0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# A simplified version of WikiContent. Useful to avoid recursion problems in
|
||||
# WikiContent.new
|
||||
class WikiContentStub < String
|
||||
attr_reader :options
|
||||
include ChunkManager
|
||||
def initialize(content, options)
|
||||
super(content)
|
||||
@options = options
|
||||
init_chunk_manager
|
||||
end
|
||||
|
||||
# Detects the mask strings contained in the text of chunks of type chunk_types
|
||||
# and yields the corresponding chunk ids
|
||||
# example: content = "chunk123categorychunk <pre>chunk456categorychunk</pre>"
|
||||
# inside_chunks(Literal::Pre) ==> yield 456
|
||||
def inside_chunks(chunk_types)
|
||||
chunk_types.each{|chunk_type| chunk_type.apply_to(self) }
|
||||
|
||||
chunk_types.each{|chunk_type| @chunks_by_type[chunk_type].each{|hide_chunk|
|
||||
scan_chunkid(hide_chunk.text){|id| yield id }
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
class WikiContent < String
|
||||
|
||||
include ChunkManager
|
||||
|
||||
DEFAULT_OPTS = {
|
||||
:active_chunks => ACTIVE_CHUNKS,
|
||||
:engine => Engines::Textile,
|
||||
:engine_opts => [],
|
||||
:mode => :show
|
||||
}.freeze
|
||||
|
||||
attr_reader :web, :options, :revision, :not_rendered, :pre_rendered
|
||||
|
||||
# Create a new wiki content string from the given one.
|
||||
# The options are explained at the top of this file.
|
||||
def initialize(revision, options = {})
|
||||
@revision = revision
|
||||
@web = @revision.page.web
|
||||
|
||||
@options = DEFAULT_OPTS.dup.merge(options)
|
||||
@options[:engine] = Engines::MAP[@web.markup]
|
||||
@options[:engine_opts] = [:filter_html, :filter_styles] if @web.safe_mode?
|
||||
@options[:active_chunks] = (ACTIVE_CHUNKS - [WikiChunk::Word] ) if @web.brackets_only?
|
||||
|
||||
@not_rendered = @pre_rendered = nil
|
||||
|
||||
super(@revision.content)
|
||||
init_chunk_manager
|
||||
build_chunks
|
||||
@not_rendered = String.new(self)
|
||||
end
|
||||
|
||||
# Call @web.page_link using current options.
|
||||
def page_link(name, text, link_type)
|
||||
@options[:link_type] = (link_type || :show)
|
||||
@web.make_link(name, text, @options)
|
||||
end
|
||||
|
||||
def build_chunks
|
||||
# create and mask Includes and "active_chunks" chunks
|
||||
Include.apply_to(self)
|
||||
@options[:active_chunks].each{|chunk_type| chunk_type.apply_to(self)}
|
||||
|
||||
# Handle hiding contexts like "pre" and "code" etc..
|
||||
# The markup (textile, rdoc etc) can produce such contexts with its own syntax.
|
||||
# To reveal them, we work on a copy of the content.
|
||||
# The copy is rendered and used to detect the chunks that are inside protecting context
|
||||
# These chunks are reverted on the original content string.
|
||||
|
||||
copy = WikiContentStub.new(self, @options)
|
||||
@options[:engine].apply_to(copy)
|
||||
|
||||
copy.inside_chunks(HIDE_CHUNKS) do |id|
|
||||
@chunks_by_id[id].revert
|
||||
end
|
||||
end
|
||||
|
||||
def pre_render!
|
||||
unless @pre_rendered
|
||||
@chunks_by_type[Include].each{|chunk| chunk.unmask }
|
||||
@pre_rendered = String.new(self)
|
||||
end
|
||||
@pre_rendered
|
||||
end
|
||||
|
||||
def render!
|
||||
pre_render!
|
||||
@options[:engine].apply_to(self)
|
||||
# unmask in one go. $~[1] is the chunk id
|
||||
gsub!(MASK_RE[ACTIVE_CHUNKS]){
|
||||
if chunk = @chunks_by_id[$~[1]]
|
||||
chunk.unmask_text
|
||||
# if we match a chunkmask that existed in the original content string
|
||||
# just keep it as it is
|
||||
else
|
||||
$~[0]
|
||||
end}
|
||||
self
|
||||
end
|
||||
|
||||
def page_name
|
||||
@revision.page.name
|
||||
end
|
||||
|
||||
def page_id
|
||||
@revision.page.id
|
||||
end
|
||||
|
||||
end
|
||||
|
23
lib/wiki_words.rb
Normal file
23
lib/wiki_words.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Contains all the methods for finding and replacing wiki words
|
||||
module WikiWords
|
||||
# In order of appearance: Latin, greek, cyrillian, armenian
|
||||
I18N_HIGHER_CASE_LETTERS =
|
||||
"À<EFBFBD>?ÂÃÄÅĀĄĂÆÇĆČĈĊĎ<C48A>?ÈÉÊËĒĘĚĔĖĜĞĠĢĤĦÌ<C4A6>?Î<>?ĪĨĬĮİIJĴĶ<C4B4>?ĽĹĻĿÑŃŇŅŊÒÓÔÕÖØŌ<C398>?ŎŒŔŘŖŚŠŞŜȘŤŢŦȚÙÚÛÜŪŮŰŬŨŲŴ<C5B2>?ŶŸŹŽŻ" +
|
||||
"ΑΒΓΔΕΖΗΘΙΚΛΜ<EFBFBD>?ΞΟΠΡΣΤΥΦΧΨΩ" +
|
||||
"ΆΈΉΊΌΎ<EFBFBD>?ѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎ<D28C>?ҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾ<D2BC>?ӃӅӇӉӋ<D389>?<3F>?ӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӸЖ" +
|
||||
"ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀ<EFBFBD>?ՂՃՄՅՆՇՈՉՊՋՌ<D58B>?<3F>?<3F>?ՑՒՓՔՕՖ"
|
||||
|
||||
I18N_LOWER_CASE_LETTERS =
|
||||
"àáâãäå<EFBFBD>?ąăæçć<C3A7>?ĉċ<C489>?đèéêëēęěĕėƒ<C497>?ğġģĥħìíîïīĩĭįıijĵķĸłľĺļŀñńňņʼnŋòóôõöø<C3B6>?ő<>?œŕřŗśšş<C5A1>?șťţŧțùúûüūůűŭũųŵýÿŷžżźÞþßſ<C39F>?ð" +
|
||||
"άέήίΰαβγδεζηθικλμνξοπ<EFBFBD>?ςστυφχψωϊϋό<CF8B>?ώ<>?" +
|
||||
"абвгдежзийклмнопр<EFBFBD>?туфхцчшщъыь<D18B>?ю<>?<3F>?ёђѓєѕіїјљћќ<D19B>?ўџѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿ<D1BD>?ҋ<>?<3F>?ґғҕҗҙқ<D299>?ҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӀӂӄӆӈӊӌӎӑӓӕӗәӛ<D399>?ӟӡӣӥӧөӫӭӯӱӳӵӹ" +
|
||||
"աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտր<EFBFBD>?ւփքօֆև"
|
||||
|
||||
WIKI_WORD_PATTERN = '[A-Z' + I18N_HIGHER_CASE_LETTERS + '][a-z' + I18N_LOWER_CASE_LETTERS + ']+[A-Z' + I18N_HIGHER_CASE_LETTERS + ']\w+'
|
||||
CAMEL_CASED_WORD_BORDER = /([a-z#{I18N_LOWER_CASE_LETTERS}])([A-Z#{I18N_HIGHER_CASE_LETTERS}])/u
|
||||
|
||||
def self.separate(wiki_word)
|
||||
wiki_word.gsub(CAMEL_CASED_WORD_BORDER, '\1 \2')
|
||||
end
|
||||
|
||||
end
|
134
rakefile.rb
134
rakefile.rb
|
@ -1,134 +0,0 @@
|
|||
require 'rake'
|
||||
require 'rake/clean'
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
require 'rake/packagetask'
|
||||
|
||||
$VERBOSE = nil
|
||||
|
||||
# Standard Rails tasks
|
||||
|
||||
desc 'Run all tests'
|
||||
task :default => [:test_units, :test_functional]
|
||||
|
||||
desc 'Require application environment.'
|
||||
task :environment do
|
||||
unless defined? RAILS_ROOT
|
||||
require File.dirname(__FILE__) + '/config/environment'
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Generate API documentatio, show coding stats'
|
||||
task :doc => [ :appdoc, :stats ]
|
||||
|
||||
desc 'Run the unit tests in test/unit'
|
||||
Rake::TestTask.new('test_units') { |t|
|
||||
t.libs << 'test'
|
||||
t.pattern = 'test/unit/**/*_test.rb'
|
||||
t.verbose = true
|
||||
}
|
||||
|
||||
desc 'Run the functional tests in test/functional'
|
||||
Rake::TestTask.new('test_functional') { |t|
|
||||
t.libs << 'test'
|
||||
t.pattern = 'test/functional/**/*_test.rb'
|
||||
t.verbose = true
|
||||
}
|
||||
|
||||
desc 'Generate documentation for the application'
|
||||
Rake::RDocTask.new('appdoc') { |rdoc|
|
||||
rdoc.rdoc_dir = 'doc/app'
|
||||
rdoc.title = 'Rails Application Documentation'
|
||||
rdoc.options << '--line-numbers --inline-source'
|
||||
rdoc.rdoc_files.include('doc/README_FOR_APP')
|
||||
rdoc.rdoc_files.include('app/**/*.rb')
|
||||
}
|
||||
|
||||
desc 'Generate documentation for the Rails framework'
|
||||
Rake::RDocTask.new("apidoc") { |rdoc|
|
||||
rdoc.rdoc_dir = 'doc/api'
|
||||
rdoc.title = 'Rails Framework Documentation'
|
||||
rdoc.options << '--line-numbers --inline-source'
|
||||
rdoc.rdoc_files.include('README')
|
||||
rdoc.rdoc_files.include('CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
|
||||
rdoc.rdoc_files.include('vendor/rails/activerecord/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
|
||||
rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/ChangeLog')
|
||||
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/**/*.rb')
|
||||
rdoc.rdoc_files.include('vendor/rails/activesupport/README')
|
||||
rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
|
||||
}
|
||||
|
||||
desc 'Report code statistics (KLOCs, etc) from the application'
|
||||
task :stats => [ :environment ] do
|
||||
require 'code_statistics'
|
||||
CodeStatistics.new(
|
||||
['Helpers', 'app/helpers'],
|
||||
['Controllers', 'app/controllers'],
|
||||
['Functionals', 'test/functional'],
|
||||
['Models', 'app/models'],
|
||||
['Units', 'test/unit'],
|
||||
['Miscellaneous (lib)', 'lib']
|
||||
).to_s
|
||||
end
|
||||
|
||||
# Additional tasks (not standard Rails)
|
||||
|
||||
CLEAN << 'pkg' << 'storage' << 'doc' << 'html'
|
||||
|
||||
begin
|
||||
require 'rubygems'
|
||||
require 'rake/gempackagetask'
|
||||
rescue Exception => e
|
||||
nil
|
||||
end
|
||||
|
||||
if defined? Rake::GemPackageTask
|
||||
gemspec = eval(File.read('instiki.gemspec'))
|
||||
Rake::GemPackageTask.new(gemspec) do |p|
|
||||
p.gem_spec = gemspec
|
||||
p.need_tar = true
|
||||
p.need_zip = true
|
||||
end
|
||||
|
||||
Rake::PackageTask.new('instiki', gemspec.version) do |p|
|
||||
p.need_tar = true
|
||||
p.need_zip = true
|
||||
# the list of glob expressions for files comes from instiki.gemspec
|
||||
p.package_files.include($__instiki_source_patterns)
|
||||
end
|
||||
|
||||
# Create a task to build the RDOC documentation tree.
|
||||
rd = Rake::RDocTask.new("rdoc") { |rdoc|
|
||||
rdoc.rdoc_dir = 'html'
|
||||
rdoc.title = 'Instiki -- The Wiki'
|
||||
rdoc.options << '--line-numbers --inline-source --main README'
|
||||
rdoc.rdoc_files.include(gemspec.files)
|
||||
rdoc.main = 'README'
|
||||
}
|
||||
else
|
||||
puts 'Warning: without Rubygems packaging tasks are not available'
|
||||
end
|
||||
|
||||
# Shorthand aliases
|
||||
desc 'Shorthand for test_units'
|
||||
task :tu => :test_units
|
||||
desc 'Shorthand for test_units'
|
||||
task :ut => :test_units
|
||||
|
||||
desc 'Shorthand for test_functional'
|
||||
task :tf => :test_functional
|
||||
desc 'Shorthand for test_functional'
|
||||
task :ft => :test_functional
|
23
script/console
Normal file
23
script/console
Normal file
|
@ -0,0 +1,23 @@
|
|||
#!/usr/local/bin/ruby
|
||||
irb = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
|
||||
|
||||
require 'optparse'
|
||||
options = { :sandbox => false, :irb => irb }
|
||||
OptionParser.new do |opt|
|
||||
opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |options[:sandbox]| }
|
||||
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |options[:irb]| }
|
||||
opt.parse!(ARGV)
|
||||
end
|
||||
|
||||
libs = " -r irb/completion"
|
||||
libs << " -r #{File.dirname(__FILE__)}/../config/environment"
|
||||
libs << " -r console_sandbox" if options[:sandbox]
|
||||
|
||||
ENV['RAILS_ENV'] = ARGV.first || 'development'
|
||||
if options[:sandbox]
|
||||
puts "Loading #{ENV['RAILS_ENV']} environment in sandbox."
|
||||
puts "Any modifications you make will be rolled back on exit."
|
||||
else
|
||||
puts "Loading #{ENV['RAILS_ENV']} environment."
|
||||
end
|
||||
exec "#{options[:irb]} #{libs} --prompt-mode simple"
|
|
@ -12,7 +12,7 @@ config = ActiveRecord::Base.configurations
|
|||
ENV['RAILS_ENV'] = target
|
||||
load APP_ROOT + 'config/environment.rb'
|
||||
puts "Creating tables for #{target}..."
|
||||
|
||||
|
||||
db_structure(config[target]['adapter']).split(/\s*;\s*/).each do |sql|
|
||||
ActiveRecord::Base.connection.execute(sql)
|
||||
end
|
||||
|
|
100
script/server
100
script/server
|
@ -1,93 +1,49 @@
|
|||
#!/usr/bin/ruby
|
||||
#!/usr/local/bin/ruby
|
||||
|
||||
require 'webrick'
|
||||
require 'optparse'
|
||||
require 'fileutils'
|
||||
|
||||
pwd = File.expand_path(File.dirname(__FILE__) + "/..")
|
||||
|
||||
OPTIONS = {
|
||||
# Overridable options
|
||||
:port => 2500,
|
||||
:ip => '0.0.0.0',
|
||||
:environment => 'production',
|
||||
:server_root => File.expand_path(File.dirname(__FILE__) + '/../public/'),
|
||||
:server_type => WEBrick::SimpleServer,
|
||||
:storage => "#{File.expand_path(FileUtils.pwd)}/storage",
|
||||
:port => 3000,
|
||||
:ip => "0.0.0.0",
|
||||
:environment => "development",
|
||||
:server_root => File.expand_path(File.dirname(__FILE__) + "/../public/"),
|
||||
:server_type => WEBrick::SimpleServer
|
||||
}
|
||||
|
||||
ARGV.options do |opts|
|
||||
script_name = File.basename($0)
|
||||
opts.banner = "Usage: ruby #{script_name} [options]"
|
||||
|
||||
opts.separator ''
|
||||
opts.separator ""
|
||||
|
||||
opts.on('-p', '--port=port', Integer,
|
||||
'Runs Instiki on the specified port.',
|
||||
'Default: 2500') { |OPTIONS[:port]| }
|
||||
opts.on('-b', '--binding=ip', String,
|
||||
'Binds Rails to the specified ip.',
|
||||
'Default: 0.0.0.0') { |OPTIONS[:ip]| }
|
||||
opts.on('-e', '--environment=name', String,
|
||||
'Specifies the environment to run this server under (test/development/production).',
|
||||
'Default: production') { |OPTIONS[:environment]| }
|
||||
opts.on('-d', '--daemon',
|
||||
'Make Instiki run as a Daemon (only works if fork is available -- meaning on *nix).'
|
||||
opts.on("-p", "--port=port", Integer,
|
||||
"Runs Rails on the specified port.",
|
||||
"Default: 3000") { |OPTIONS[:port]| }
|
||||
opts.on("-b", "--binding=ip", String,
|
||||
"Binds Rails to the specified ip.",
|
||||
"Default: 0.0.0.0") { |OPTIONS[:ip]| }
|
||||
opts.on("-e", "--environment=name", String,
|
||||
"Specifies the environment to run this server under (test/development/production).",
|
||||
"Default: development") { |OPTIONS[:environment]| }
|
||||
opts.on("-d", "--daemon",
|
||||
"Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
|
||||
) { OPTIONS[:server_type] = WEBrick::Daemon }
|
||||
opts.on('-s', '--simple', '--simple-server',
|
||||
'[deprecated] Forces Instiki not to run as a Daemon if fork is available.',
|
||||
'Since version 0.10.0 this option is ignored.'
|
||||
) { puts "Warning: -s (--simple) option is deprecated. See instiki --help for details." }
|
||||
opts.on('-t', '--storage=storage', String,
|
||||
'Makes Instiki use the specified directory for storage.',
|
||||
'Default: ./storage/[port]') { |OPTIONS[:storage]| }
|
||||
opts.on('-x', '--notex',
|
||||
'Blocks wiki exports to TeX and PDF, even when pdflatex is available.'
|
||||
) { |OPTIONS[:notex]| }
|
||||
opts.on('-v', '--verbose',
|
||||
'Enables debug-level logging'
|
||||
) { OPTIONS[:verbose] = true }
|
||||
|
||||
opts.separator ''
|
||||
opts.separator ""
|
||||
|
||||
opts.on('-h', '--help',
|
||||
'Show this help message.') { puts opts; exit }
|
||||
opts.on("-h", "--help",
|
||||
"Show this help message.") { puts opts; exit }
|
||||
|
||||
opts.parse!
|
||||
end
|
||||
|
||||
if OPTIONS[:environment] == 'production'
|
||||
storage_path = "#{OPTIONS[:storage]}/#{OPTIONS[:port]}"
|
||||
else
|
||||
storage_path = "#{OPTIONS[:storage]}/#{OPTIONS[:environment]}/#{OPTIONS[:port]}"
|
||||
end
|
||||
FileUtils.mkdir_p(storage_path)
|
||||
ENV["RAILS_ENV"] = OPTIONS[:environment]
|
||||
require File.dirname(__FILE__) + "/../config/environment"
|
||||
require 'webrick_server'
|
||||
|
||||
ENV['RAILS_ENV'] = OPTIONS[:environment]
|
||||
$instiki_debug_logging = OPTIONS[:verbose]
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
|
||||
WikiService.storage_path = storage_path
|
||||
OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
|
||||
|
||||
if OPTIONS[:notex]
|
||||
OPTIONS[:pdflatex] = false
|
||||
else
|
||||
begin
|
||||
OPTIONS[:pdflatex] = system "pdflatex -version"
|
||||
rescue Errno::ENOENT
|
||||
OPTIONS[:pdflatex] = false
|
||||
end
|
||||
end
|
||||
|
||||
if defined? INSTIKI_BATCH_JOB
|
||||
require 'application'
|
||||
else
|
||||
puts "=> Starting Instiki on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
|
||||
puts "=> Data files are stored in #{storage_path}"
|
||||
|
||||
require 'webrick_server'
|
||||
require_dependency 'application'
|
||||
|
||||
OPTIONS[:index_controller] = 'wiki'
|
||||
ApplicationController.wiki = WikiService.instance
|
||||
DispatchServlet.dispatch(OPTIONS)
|
||||
end
|
||||
puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
|
||||
puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
|
||||
DispatchServlet.dispatch(OPTIONS)
|
||||
|
|
56
test/fixtures/pages.yml
vendored
56
test/fixtures/pages.yml
vendored
|
@ -1,5 +1,55 @@
|
|||
home_page:
|
||||
id: 1
|
||||
created_at: 2004-08-01
|
||||
updated_at: 2005-08-01
|
||||
web_id: 1
|
||||
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
|
||||
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: HomePage
|
||||
|
||||
my_way:
|
||||
id: 2
|
||||
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: MyWay
|
||||
|
||||
smart_engine:
|
||||
id: 3
|
||||
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: SmartEngine
|
||||
|
||||
that_way:
|
||||
id: 4
|
||||
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: ThatWay
|
||||
|
||||
no_wiki_word:
|
||||
id: 5
|
||||
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: NoWikiWord
|
||||
|
||||
first_page:
|
||||
id: 6
|
||||
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
|
||||
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: FirstPage
|
||||
|
||||
oak:
|
||||
id: 7
|
||||
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: Oak
|
||||
|
||||
elephant:
|
||||
id: 8
|
||||
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
|
||||
web_id: 1
|
||||
name: Elephant
|
84
test/fixtures/revisions.yml
vendored
84
test/fixtures/revisions.yml
vendored
|
@ -1,6 +1,84 @@
|
|||
home_page_first_revision:
|
||||
id: 1
|
||||
created_at: 2004-08-01
|
||||
updated_at: 2005-08-01
|
||||
created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
|
||||
updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
|
||||
page_id: 1
|
||||
content: some text
|
||||
number: 1
|
||||
content: First revision of the HomePage end
|
||||
author: AnAuthor
|
||||
ip: 127.0.0.1
|
||||
|
||||
my_way_first_revision:
|
||||
id: 2
|
||||
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
|
||||
page_id: 2
|
||||
number: 1
|
||||
content: MyWay
|
||||
author: Me
|
||||
|
||||
smart_engine_first_revision:
|
||||
id: 3
|
||||
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
|
||||
page_id: 3
|
||||
number: 1
|
||||
content: SmartEngine
|
||||
author: Me
|
||||
|
||||
that_way_first_revision:
|
||||
id: 4
|
||||
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
|
||||
page_id: 4
|
||||
number: 1
|
||||
content: ThatWay
|
||||
author: Me
|
||||
|
||||
no_wiki_word_first_revision:
|
||||
id: 5
|
||||
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
|
||||
page_id: 5
|
||||
number: 1
|
||||
content: hey you
|
||||
author: Me
|
||||
|
||||
home_page_second_revision:
|
||||
id: 6
|
||||
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
|
||||
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
|
||||
page_id: 1
|
||||
number: 2
|
||||
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
|
||||
author: DavidHeinemeierHansson
|
||||
|
||||
first_page_first_revision:
|
||||
id: 7
|
||||
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
|
||||
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
|
||||
page_id: 6
|
||||
number: 1
|
||||
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
|
||||
author: DavidHeinemeierHansson
|
||||
|
||||
oak_first_revision:
|
||||
id: 8
|
||||
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
|
||||
page_id: 7
|
||||
number: 1
|
||||
content: "All about oak.\ncategory: trees"
|
||||
author: TreeHugger
|
||||
ip: 127.0.0.2
|
||||
|
||||
elephant_first_revision:
|
||||
id: 9
|
||||
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
|
||||
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
|
||||
page_id: 8
|
||||
number: 1
|
||||
content: "All about elephants.\ncategory: animals"
|
||||
author: Guest
|
||||
ip: 127.0.0.2
|
||||
|
||||
|
|
2
test/fixtures/system.yml
vendored
Normal file
2
test/fixtures/system.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
system:
|
||||
password: test_password
|
13
test/fixtures/webs.yml
vendored
13
test/fixtures/webs.yml
vendored
|
@ -2,5 +2,14 @@ test_wiki:
|
|||
id: 1
|
||||
created_at: 2004-08-01
|
||||
updated_at: 2005-08-01
|
||||
name: wiki
|
||||
address: wiki
|
||||
name: wiki1
|
||||
address: wiki1
|
||||
markup: textile
|
||||
|
||||
instiki:
|
||||
id: 2
|
||||
created_at: 2004-08-01
|
||||
updated_at: 2005-08-01
|
||||
name: Instiki
|
||||
address: instiki
|
||||
markup: textile
|
|
@ -1,70 +1,73 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
require 'admin_controller'
|
||||
|
||||
# Raise errors beyond the default web-based presentation
|
||||
class AdminController; def rescue_action(e) logger.error(e); raise e end; end
|
||||
|
||||
class AdminControllerTest < Test::Unit::TestCase
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
setup_test_wiki
|
||||
setup_controller_test
|
||||
@controller = AdminController.new
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
@wiki = Wiki.new
|
||||
@oak = pages(:oak)
|
||||
@elephant = pages(:elephant)
|
||||
@web = webs(:test_wiki)
|
||||
@home = @page = pages(:home_page)
|
||||
end
|
||||
|
||||
def tear_down
|
||||
tear_down_wiki
|
||||
end
|
||||
|
||||
|
||||
def test_create_system_form_displayed
|
||||
ApplicationController.wiki = WikiServiceWithNoPersistence.new
|
||||
use_blank_wiki
|
||||
process('create_system')
|
||||
assert_success
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_create_system_form_submitted
|
||||
ApplicationController.wiki = WikiServiceWithNoPersistence.new
|
||||
assert !ApplicationController.wiki.setup?
|
||||
use_blank_wiki
|
||||
assert !@wiki.setup?
|
||||
|
||||
process('create_system', 'password' => 'a_password', 'web_name' => 'My Wiki',
|
||||
'web_address' => 'my_wiki')
|
||||
|
||||
assert_redirected_to :web => 'my_wiki', :controller => 'wiki', :action => 'new',
|
||||
:id => 'HomePage'
|
||||
assert ApplicationController.wiki.setup?
|
||||
assert_equal 'a_password', ApplicationController.wiki.system[:password]
|
||||
assert_equal 1, ApplicationController.wiki.webs.size
|
||||
new_web = ApplicationController.wiki.webs['my_wiki']
|
||||
assert @wiki.setup?
|
||||
assert_equal 'a_password', @wiki.system[:password]
|
||||
assert_equal 1, @wiki.webs.size
|
||||
new_web = @wiki.webs['my_wiki']
|
||||
assert_equal 'My Wiki', new_web.name
|
||||
assert_equal 'my_wiki', new_web.address
|
||||
end
|
||||
|
||||
def test_create_system_form_submitted_and_wiki_already_initialized
|
||||
wiki_before = ApplicationController.wiki
|
||||
assert ApplicationController.wiki.setup?
|
||||
wiki_before = @wiki
|
||||
old_size = @wiki.webs.size
|
||||
assert @wiki.setup?
|
||||
|
||||
process 'create_system', 'password' => 'a_password', 'web_name' => 'My Wiki',
|
||||
'web_address' => 'my_wiki'
|
||||
|
||||
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
||||
assert_equal wiki_before, ApplicationController.wiki
|
||||
assert_redirected_to :web => @wiki.webs.keys.first, :action => 'show', :id => 'HomePage'
|
||||
assert_equal wiki_before, @wiki
|
||||
# and no new web should be created either
|
||||
assert_equal 1, ApplicationController.wiki.webs.size
|
||||
assert_equal old_size, @wiki.webs.size
|
||||
assert_flash_has :error
|
||||
end
|
||||
|
||||
def test_create_system_no_form_and_wiki_already_initialized
|
||||
assert @wiki.setup?
|
||||
process('create_system')
|
||||
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
||||
assert_redirected_to :web => @wiki.webs.keys.first, :action => 'show', :id => 'HomePage'
|
||||
assert_flash_has :error
|
||||
end
|
||||
|
||||
|
||||
def test_create_web
|
||||
@wiki.system[:password] = 'pswd'
|
||||
@wiki.system.update_attribute(:password, 'pswd')
|
||||
|
||||
process 'create_web', 'system_password' => 'pswd', 'name' => 'Wiki Two', 'address' => 'wiki2'
|
||||
|
||||
|
@ -76,7 +79,7 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_create_web_default_password
|
||||
@wiki.system[:password] = nil
|
||||
@wiki.system.update_attribute(:password, nil)
|
||||
|
||||
process 'create_web', 'system_password' => 'instiki', 'name' => 'Wiki Two', 'address' => 'wiki2'
|
||||
|
||||
|
@ -84,7 +87,7 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_create_web_failed_authentication
|
||||
@wiki.system[:password] = 'pswd'
|
||||
@wiki.system.update_attribute(:password, 'pswd')
|
||||
|
||||
process 'create_web', 'system_password' => 'wrong', 'name' => 'Wiki Two', 'address' => 'wiki2'
|
||||
|
||||
|
@ -93,20 +96,20 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_create_web_no_form_submitted
|
||||
@wiki.system[:password] = 'pswd'
|
||||
@wiki.system.update_attribute(:password, 'pswd')
|
||||
process 'create_web'
|
||||
assert_success
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
|
||||
def test_edit_web_no_form
|
||||
process 'edit_web', 'web' => 'wiki1'
|
||||
# this action simply renders a form
|
||||
assert_success
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_edit_web_form_submitted
|
||||
@wiki.system[:password] = 'pswd'
|
||||
@wiki.system.update_attribute(:password, 'pswd')
|
||||
|
||||
process('edit_web', 'system_password' => 'pswd',
|
||||
'web' => 'wiki1', 'address' => 'renamed_wiki1', 'name' => 'Renamed Wiki1',
|
||||
|
@ -116,21 +119,22 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
'max_upload_size' => '300')
|
||||
|
||||
assert_redirected_to :web => 'renamed_wiki1', :action => 'show', :id => 'HomePage'
|
||||
@web = Web.find(@web.id)
|
||||
assert_equal 'renamed_wiki1', @web.address
|
||||
assert_equal 'Renamed Wiki1', @web.name
|
||||
assert_equal :markdown, @web.markup
|
||||
assert_equal 'blue', @web.color
|
||||
assert @web.safe_mode
|
||||
assert @web.safe_mode?
|
||||
assert_equal 'new_password', @web.password
|
||||
assert @web.published
|
||||
assert @web.brackets_only
|
||||
assert @web.count_pages
|
||||
assert @web.allow_uploads
|
||||
assert @web.published?
|
||||
assert @web.brackets_only?
|
||||
assert @web.count_pages?
|
||||
assert @web.allow_uploads?
|
||||
assert_equal 300, @web.max_upload_size
|
||||
end
|
||||
|
||||
def test_edit_web_opposite_values
|
||||
@wiki.system[:password] = 'pswd'
|
||||
@wiki.system.update_attribute(:password, 'pswd')
|
||||
|
||||
process('edit_web', 'system_password' => 'pswd',
|
||||
'web' => 'wiki1', 'address' => 'renamed_wiki1', 'name' => 'Renamed Wiki1',
|
||||
|
@ -140,11 +144,12 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
# and should become false
|
||||
|
||||
assert_redirected_to :web => 'renamed_wiki1', :action => 'show', :id => 'HomePage'
|
||||
assert !@web.safe_mode
|
||||
assert !@web.published
|
||||
assert !@web.brackets_only
|
||||
assert !@web.count_pages
|
||||
assert !@web.allow_uploads
|
||||
@web = Web.find(@web.id)
|
||||
assert !@web.safe_mode?
|
||||
assert !@web.published?
|
||||
assert !@web.brackets_only?
|
||||
assert !@web.count_pages?
|
||||
assert !@web.allow_uploads?
|
||||
end
|
||||
|
||||
def test_edit_web_wrong_password
|
||||
|
@ -154,12 +159,12 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
'password' => 'new_password')
|
||||
|
||||
#returns to the same form
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert @response.has_template_object?('error')
|
||||
end
|
||||
|
||||
def test_edit_web_rename_to_already_existing_web_name
|
||||
@wiki.system[:password] = 'pswd'
|
||||
@wiki.system.update_attribute(:password, 'pswd')
|
||||
|
||||
@wiki.create_web('Another', 'another')
|
||||
process('edit_web', 'system_password' => 'pswd',
|
||||
|
@ -168,7 +173,7 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
'password' => 'new_password')
|
||||
|
||||
#returns to the same form
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert @response.has_template_object?('error')
|
||||
end
|
||||
|
||||
|
@ -179,15 +184,15 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
'password' => 'new_password')
|
||||
|
||||
#returns to the same form
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert @response.has_template_object?('error')
|
||||
end
|
||||
|
||||
|
||||
def test_remove_orphaned_pages
|
||||
setup_wiki_with_three_pages
|
||||
@wiki.system[:password] = 'pswd'
|
||||
orhan_page_linking_to_oak = @wiki.write_page('wiki1', 'Pine',
|
||||
@wiki.system.update_attribute(:password, 'pswd')
|
||||
page_order = [@home, pages(:my_way), @oak, pages(:smart_engine), pages(:that_way)]
|
||||
orphan_page_linking_to_oak = @wiki.write_page('wiki1', 'Pine',
|
||||
"Refers to [[Oak]].\n" +
|
||||
"category: trees",
|
||||
Time.now, Author.new('TreeHugger', '127.0.0.2'))
|
||||
|
@ -195,25 +200,28 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
|
||||
|
||||
assert_redirected_to :controller => 'wiki', :web => 'wiki1', :action => 'list'
|
||||
assert_equal [@home, @oak], @web.select.sort,
|
||||
@web.pages(true)
|
||||
assert_equal page_order, @web.select.sort,
|
||||
"Pages are not as expected: #{@web.select.sort.map {|p| p.name}.inspect}"
|
||||
|
||||
|
||||
# Oak is now orphan, second pass should remove it
|
||||
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
|
||||
assert_redirected_to :controller => 'wiki', :web => 'wiki1', :action => 'list'
|
||||
assert_equal [@home], @web.select.sort,
|
||||
@web.pages(true)
|
||||
page_order.delete(@oak)
|
||||
assert_equal page_order, @web.select.sort,
|
||||
"Pages are not as expected: #{@web.select.sort.map {|p| p.name}.inspect}"
|
||||
|
||||
# third pass does not destroy HomePage
|
||||
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
|
||||
assert_redirected_to :action => 'list'
|
||||
assert_equal [@home], @web.select.sort,
|
||||
@web.pages(true)
|
||||
assert_equal page_order, @web.select.sort,
|
||||
"Pages are not as expected: #{@web.select.sort.map {|p| p.name}.inspect}"
|
||||
end
|
||||
|
||||
def test_remove_orphaned_pages_empty_or_wrong_password
|
||||
setup_wiki_with_three_pages
|
||||
@wiki.system[:password] = 'pswd'
|
||||
|
||||
process('remove_orphaned_pages', 'web' => 'wiki1')
|
||||
|
@ -224,5 +232,4 @@ class AdminControllerTest < Test::Unit::TestCase
|
|||
assert_redirected_to(:controller => 'admin', :action => 'edit_web', :web => 'wiki1')
|
||||
assert @response.flash[:error]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -8,24 +8,23 @@ require 'rexml/document'
|
|||
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
|
||||
|
||||
class ApplicationTest < Test::Unit::TestCase
|
||||
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
setup_test_wiki
|
||||
setup_controller_test(WikiController)
|
||||
@controller = WikiController.new
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
@wiki = Wiki.new
|
||||
end
|
||||
|
||||
def tear_down
|
||||
tear_down_wiki
|
||||
end
|
||||
|
||||
|
||||
def test_utf8_header
|
||||
r = process('show', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||
assert_equal 'text/html; charset=UTF-8', r.headers['Content-Type']
|
||||
get :show, :web => 'wiki1', :id => 'HomePage'
|
||||
assert_equal 'text/html; charset=UTF-8', @response.headers['Content-Type']
|
||||
end
|
||||
|
||||
def test_connect_to_model_unknown_wiki
|
||||
r = process('show', 'web' => 'unknown_wiki', 'id' => 'HomePage')
|
||||
assert_equal 404, r.response_code
|
||||
get :show, :web => 'unknown_wiki', :id => 'HomePage'
|
||||
assert_response :missing
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require 'file_controller'
|
||||
|
@ -8,24 +8,26 @@ require 'fileutils'
|
|||
class FileController; def rescue_action(e) logger.error(e); raise e end; end
|
||||
|
||||
class FileControllerTest < Test::Unit::TestCase
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
FILE_AREA = RAILS_ROOT + '/storage/test/wiki1'
|
||||
Wiki.storage_path += "test/"
|
||||
FILE_AREA = Wiki.storage_path + 'wiki1'
|
||||
FileUtils.mkdir_p(FILE_AREA) unless File.directory?(FILE_AREA)
|
||||
FileUtils.rm(Dir["#{FILE_AREA}/*"])
|
||||
|
||||
def setup
|
||||
setup_test_wiki
|
||||
setup_controller_test
|
||||
end
|
||||
|
||||
def tear_down
|
||||
tear_down_wiki
|
||||
@controller = FileController.new
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
@wiki = Wiki.new
|
||||
@web = webs(:test_wiki)
|
||||
@home = @page = pages(:home_page)
|
||||
end
|
||||
|
||||
def test_file
|
||||
process 'file', 'web' => 'wiki1', 'id' => 'foo.tgz'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_rendered_file 'file/file'
|
||||
end
|
||||
|
||||
|
@ -34,7 +36,7 @@ class FileControllerTest < Test::Unit::TestCase
|
|||
|
||||
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.txt'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal "aaa\nbbb\n", r.binary_content
|
||||
assert_equal 'text/plain', r.headers['Content-Type']
|
||||
end
|
||||
|
@ -44,7 +46,7 @@ class FileControllerTest < Test::Unit::TestCase
|
|||
|
||||
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.pdf'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal "aaa\nbbb\n", r.binary_content
|
||||
assert_equal 'application/pdf', r.headers['Content-Type']
|
||||
end
|
||||
|
@ -54,14 +56,14 @@ class FileControllerTest < Test::Unit::TestCase
|
|||
|
||||
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails.gif'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal File.size("#{FILE_AREA}/rails.gif"), r.binary_content.size
|
||||
end
|
||||
|
||||
def test_pic_unknown_pic
|
||||
r = process 'pic', 'web' => 'wiki1', 'id' => 'non-existant.gif'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_rendered_file 'file/file'
|
||||
end
|
||||
|
||||
|
@ -74,7 +76,7 @@ class FileControllerTest < Test::Unit::TestCase
|
|||
|
||||
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
|
||||
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif'
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_rendered_file 'file/file'
|
||||
|
||||
# User uploads the picture
|
||||
|
@ -98,7 +100,7 @@ class FileControllerTest < Test::Unit::TestCase
|
|||
|
||||
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
|
||||
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt'
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_rendered_file 'file/file'
|
||||
|
||||
# User uploads the picture
|
||||
|
@ -109,17 +111,18 @@ class FileControllerTest < Test::Unit::TestCase
|
|||
assert_equal(file, File.read("#{RAILS_ROOT}/storage/test/wiki1/instiki-e2e.txt"))
|
||||
|
||||
# this should refresh the page display content (cached)
|
||||
@home = Page.find(@home.id)
|
||||
assert_equal "<p><a class=\"existingWikiWord\" href=\"../file/instiki-e2e.txt\">" +
|
||||
"instiki-e2e.txt</a></p>",
|
||||
@home.display_content
|
||||
end
|
||||
|
||||
def test_uploads_blocking
|
||||
@web.allow_uploads = true
|
||||
set_web_property :allow_uploads, true
|
||||
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
|
||||
assert_success
|
||||
assert_response :success
|
||||
|
||||
@web.allow_uploads = false
|
||||
set_web_property :allow_uploads, false
|
||||
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
|
||||
assert_equal '403 Forbidden', r.headers['Status']
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
# Uncomment the line below to enable pdflatex tests; don't forget to comment them again
|
||||
# commiting to SVN
|
||||
# $INSTIKI_TEST_PDFLATEX = true
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
require 'wiki_controller'
|
||||
require 'rexml/document'
|
||||
require 'tempfile'
|
||||
|
@ -14,63 +14,60 @@ require 'zip/zipfilesystem'
|
|||
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
|
||||
|
||||
class WikiControllerTest < Test::Unit::TestCase
|
||||
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
setup_test_wiki
|
||||
setup_controller_test
|
||||
@controller = WikiController.new
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
@wiki = Wiki.new
|
||||
@web = webs(:test_wiki)
|
||||
@home = @page = pages(:home_page)
|
||||
@oak = pages(:oak)
|
||||
@elephant = pages(:elephant)
|
||||
end
|
||||
|
||||
def tear_down
|
||||
tear_down_wiki
|
||||
end
|
||||
|
||||
|
||||
def test_authenticate
|
||||
@web.password = 'pswd'
|
||||
set_web_property :password, 'pswd'
|
||||
|
||||
r = process('authenticate', 'web' => 'wiki1', 'password' => 'pswd')
|
||||
get :authenticate, :web => 'wiki1', :password => 'pswd'
|
||||
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
||||
assert_equal ['pswd'], r.cookies['web_address']
|
||||
assert_equal ['pswd'], @response.cookies['web_address']
|
||||
end
|
||||
|
||||
def test_authenticate_wrong_password
|
||||
@web.password = 'pswd'
|
||||
set_web_property :password, 'pswd'
|
||||
|
||||
r = process('authenticate', 'web' => 'wiki1', 'password' => 'wrong password')
|
||||
assert_redirected_to :action => 'login', :web => 'wiki1'
|
||||
assert_nil r.cookies['web_address']
|
||||
end
|
||||
|
||||
|
||||
def test_authors
|
||||
setup_wiki_with_three_pages
|
||||
@wiki.write_page('wiki1', 'BreakSortingOrder',
|
||||
"This page breaks the accidentally correct sorting order of authors",
|
||||
Time.now, Author.new('BreakingTheOrder', '127.0.0.2'))
|
||||
|
||||
r = process('authors', 'web' => 'wiki1')
|
||||
|
||||
assert_success
|
||||
assert_equal ['AnAuthor', 'BreakingTheOrder', 'Guest', 'TreeHugger'],
|
||||
assert_response :success
|
||||
assert_equal %w(AnAuthor BreakingTheOrder DavidHeinemeierHansson Guest Me TreeHugger),
|
||||
r.template_objects['authors']
|
||||
end
|
||||
|
||||
|
||||
def test_cancel_edit
|
||||
setup_wiki_with_three_pages
|
||||
@oak.lock(Time.now, 'Locky')
|
||||
assert @oak.locked?(Time.now)
|
||||
|
||||
r = process('cancel_edit', 'web' => 'wiki1', 'id' => 'Oak')
|
||||
|
||||
assert_redirected_to :action => 'show', :id => 'Oak'
|
||||
assert !@oak.locked?(Time.now)
|
||||
assert !Page.find(@oak.id).locked?(Time.now)
|
||||
end
|
||||
|
||||
|
||||
def test_edit
|
||||
r = process 'edit', 'web' => 'wiki1', 'id' => 'HomePage'
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal @wiki.read_page('wiki1', 'HomePage'), r.template_objects['page']
|
||||
end
|
||||
|
||||
|
@ -83,7 +80,8 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
def test_edit_page_break_lock
|
||||
@home.lock(Time.now, 'Locky')
|
||||
process 'edit', 'web' => 'wiki1', 'id' => 'HomePage', 'break_lock' => 'y'
|
||||
assert_success
|
||||
assert_response :success
|
||||
@home = Page.find(@home.id)
|
||||
assert @home.locked?(Time.now)
|
||||
end
|
||||
|
||||
|
@ -99,19 +97,17 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
Time.now, Author.new('Special', '127.0.0.3'))
|
||||
|
||||
r = process 'edit', 'web' => 'wiki1', 'id' => 'With : Special /> symbols'
|
||||
assert_success
|
||||
assert_response :success
|
||||
xml = REXML::Document.new(r.body)
|
||||
form = REXML::XPath.first(xml, '//form')
|
||||
assert_equal '/wiki1/save/With+%3A+Special+%2F%3E+symbols', form.attributes['action']
|
||||
end
|
||||
|
||||
|
||||
def test_export_html
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
@home.rollback(1, Time.now, 'Rick') # much simpler regex statement to match
|
||||
r = process 'export_html', 'web' => 'wiki1'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal 'application/zip', r.headers['Content-Type']
|
||||
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
|
||||
r.headers['Content-Disposition']
|
||||
|
@ -124,7 +120,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
begin
|
||||
File.open(@tempfile_path, 'wb') { |f| f.write(content); @exported_file = f.path }
|
||||
Zip::ZipFile.open(@exported_file) do |zip|
|
||||
assert_equal %w(Elephant.html HomePage.html Oak.html index.html), zip.dir.entries('.').sort
|
||||
assert_equal %w(Elephant.html FirstPage.html HomePage.html MyWay.html NoWikiWord.html Oak.html SmartEngine.html ThatWay.html index.html), zip.dir.entries('.').sort
|
||||
assert_match /.*<html .*All about elephants.*<\/html>/,
|
||||
zip.file.read('Elephant.html').gsub(/\s+/, ' ')
|
||||
assert_match /.*<html .*All about oak.*<\/html>/,
|
||||
|
@ -138,12 +134,10 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_export_html_no_layout
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
def test_export_html_no_layout
|
||||
r = process 'export_html', 'web' => 'wiki1', 'layout' => 'no'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal 'application/zip', r.headers['Content-Type']
|
||||
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
|
||||
r.headers['Content-Disposition']
|
||||
|
@ -155,7 +149,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
def test_export_markup
|
||||
r = process 'export_markup', 'web' => 'wiki1'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal 'application/zip', r.headers['Content-Type']
|
||||
assert_match /attachment; filename="wiki1-textile-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
|
||||
r.headers['Content-Disposition']
|
||||
|
@ -168,7 +162,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
def test_export_pdf
|
||||
r = process 'export_pdf', 'web' => 'wiki1'
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal 'application/pdf', r.headers['Content-Type']
|
||||
assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.pdf"/,
|
||||
r.headers['Content-Disposition']
|
||||
|
@ -183,13 +177,10 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
puts ' $INSTIKI_TEST_PDFLATEX to enable them.'
|
||||
end
|
||||
|
||||
|
||||
def test_export_tex
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
def test_export_tex
|
||||
r = process 'export_tex', 'web' => 'wiki1'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal 'application/octet-stream', r.headers['Content-Type']
|
||||
assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.tex"/,
|
||||
r.headers['Content-Disposition']
|
||||
|
@ -202,6 +193,8 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_index
|
||||
# delete extra web fixture
|
||||
webs(:instiki).destroy
|
||||
process('index')
|
||||
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
||||
end
|
||||
|
@ -219,41 +212,39 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_index_wiki_not_initialized
|
||||
ApplicationController.wiki = WikiServiceWithNoPersistence.new
|
||||
use_blank_wiki
|
||||
process('index')
|
||||
assert_redirected_to :controller => 'admin', :action => 'create_system'
|
||||
end
|
||||
|
||||
|
||||
def test_list
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process('list', 'web' => 'wiki1')
|
||||
|
||||
assert_equal ['animals', 'trees'], r.template_objects['categories']
|
||||
assert_nil r.template_objects['category']
|
||||
assert_equal [@elephant, @home, @oak], r.template_objects['pages_in_category']
|
||||
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category']
|
||||
end
|
||||
|
||||
|
||||
def test_locked
|
||||
@home.lock(Time.now, 'Locky')
|
||||
r = process('locked', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal @home, r.template_objects['page']
|
||||
end
|
||||
|
||||
|
||||
def test_login
|
||||
r = process 'login', 'web' => 'wiki1'
|
||||
assert_success
|
||||
assert_response :success
|
||||
# this action goes straight to the templates
|
||||
end
|
||||
|
||||
|
||||
def test_new
|
||||
r = process('new', 'id' => 'NewPage', 'web' => 'wiki1')
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal 'AnonymousCoward', r.template_objects['author']
|
||||
assert_equal 'NewPage', r.template_objects['page_name']
|
||||
end
|
||||
|
@ -264,7 +255,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
def test_pdf
|
||||
assert RedClothForTex.available?, 'Cannot do test_pdf when pdflatex is not available'
|
||||
r = process('pdf', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||
assert_success
|
||||
assert_response :success
|
||||
|
||||
content = r.binary_content
|
||||
|
||||
|
@ -282,23 +273,23 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
def test_print
|
||||
r = process('print', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal :show, r.template_objects['link_mode']
|
||||
end
|
||||
|
||||
|
||||
def test_published
|
||||
@web.published = true
|
||||
set_web_property :published, true
|
||||
|
||||
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal @home, r.template_objects['page']
|
||||
end
|
||||
|
||||
|
||||
def test_published_web_not_published
|
||||
@web.published = false
|
||||
set_web_property :published, false
|
||||
|
||||
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||
|
||||
|
@ -308,11 +299,11 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
def test_recently_revised
|
||||
r = process('recently_revised', 'web' => 'wiki1')
|
||||
assert_success
|
||||
assert_response :success
|
||||
|
||||
assert_equal [], r.template_objects['categories']
|
||||
assert_equal %w(animals trees), r.template_objects['categories']
|
||||
assert_nil r.template_objects['category']
|
||||
assert_equal [@home], r.template_objects['pages_in_category']
|
||||
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category']
|
||||
assert_equal 'the web', r.template_objects['set_name']
|
||||
end
|
||||
|
||||
|
@ -323,37 +314,33 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
Time.now, Author.new('AnotherAuthor', '127.0.0.2'))
|
||||
|
||||
r = process('recently_revised', 'web' => 'wiki1')
|
||||
assert_success
|
||||
assert_response :success
|
||||
|
||||
assert_equal ['categorized'], r.template_objects['categories']
|
||||
assert_equal %w(animals categorized trees), r.template_objects['categories']
|
||||
# no category is specified in params
|
||||
assert_nil r.template_objects['category']
|
||||
assert_equal [@home, page2], r.template_objects['pages_in_category'],
|
||||
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, page2, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
|
||||
"Pages are not as expected: " +
|
||||
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
|
||||
assert_equal 'the web', r.template_objects['set_name']
|
||||
end
|
||||
|
||||
def test_recently_revised_with_categorized_page_multiple_categories
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process('recently_revised', 'web' => 'wiki1')
|
||||
assert_success
|
||||
assert_response :success
|
||||
|
||||
assert_equal ['animals', 'trees'], r.template_objects['categories']
|
||||
# no category is specified in params
|
||||
assert_nil r.template_objects['category']
|
||||
assert_equal [@elephant, @home, @oak], r.template_objects['pages_in_category'],
|
||||
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
|
||||
"Pages are not as expected: " +
|
||||
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
|
||||
assert_equal 'the web', r.template_objects['set_name']
|
||||
end
|
||||
|
||||
def test_recently_revised_with_specified_category
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process('recently_revised', 'web' => 'wiki1', 'category' => 'animals')
|
||||
assert_success
|
||||
assert_response :success
|
||||
|
||||
assert_equal ['animals', 'trees'], r.template_objects['categories']
|
||||
# no category is specified in params
|
||||
|
@ -366,7 +353,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
def test_revision
|
||||
r = process 'revision', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '0'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal @home, r.template_objects['page']
|
||||
assert_equal @home.revisions[0], r.template_objects['revision']
|
||||
end
|
||||
|
@ -377,27 +364,24 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
# its assigns the same as or revision
|
||||
r = process 'rollback', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '0'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal @home, r.template_objects['page']
|
||||
assert_equal @home.revisions[0], r.template_objects['revision']
|
||||
end
|
||||
|
||||
def test_rss_with_content
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process 'rss_with_content', 'web' => 'wiki1'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal [@home, @oak, @elephant], pages,
|
||||
assert_equal [@elephant, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages,
|
||||
"Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
|
||||
assert !r.template_objects['hide_description']
|
||||
end
|
||||
|
||||
def test_rss_with_content_when_blocked
|
||||
setup_wiki_with_three_pages
|
||||
@web.password = 'aaa'
|
||||
@web.published = false
|
||||
@web.update_attributes(:password => 'aaa', :published => false)
|
||||
@web = Web.find(@web.id)
|
||||
|
||||
r = process 'rss_with_content', 'web' => 'wiki1'
|
||||
|
||||
|
@ -406,7 +390,6 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
|
||||
def test_rss_with_headlines
|
||||
setup_wiki_with_three_pages
|
||||
@title_with_spaces = @wiki.write_page('wiki1', 'Title With Spaces',
|
||||
'About spaces', 1.hour.ago, Author.new('TreeHugger', '127.0.0.2'))
|
||||
|
||||
|
@ -415,19 +398,24 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal [@home, @oak, @elephant, @title_with_spaces], pages,
|
||||
"Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
|
||||
assert_equal [@elephant, @title_with_spaces, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages, "Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
|
||||
assert r.template_objects['hide_description']
|
||||
|
||||
xml = REXML::Document.new(r.body)
|
||||
|
||||
expected_page_links =
|
||||
['http://localhost:8080/wiki1/show/HomePage',
|
||||
['http://localhost:8080/wiki1/show/Elephant',
|
||||
'http://localhost:8080/wiki1/show/Title+With+Spaces',
|
||||
'http://localhost:8080/wiki1/show/Oak',
|
||||
'http://localhost:8080/wiki1/show/Elephant',
|
||||
'http://localhost:8080/wiki1/show/Title+With+Spaces']
|
||||
'http://localhost:8080/wiki1/show/NoWikiWord',
|
||||
'http://localhost:8080/wiki1/show/ThatWay',
|
||||
'http://localhost:8080/wiki1/show/SmartEngine',
|
||||
'http://localhost:8080/wiki1/show/MyWay',
|
||||
'http://localhost:8080/wiki1/show/FirstPage',
|
||||
'http://localhost:8080/wiki1/show/HomePage',
|
||||
]
|
||||
|
||||
assert_template_xpath_match '/rss/channel/link',
|
||||
'http://localhost:8080/wiki1/show/HomePage'
|
||||
|
@ -436,22 +424,26 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_rss_switch_links_to_published
|
||||
setup_wiki_with_three_pages
|
||||
@web.password = 'aaa'
|
||||
@web.published = true
|
||||
@web.update_attributes(:password => 'aaa', :published => true)
|
||||
@web = Web.find(@web.id)
|
||||
|
||||
@request.host = 'foo.bar.info'
|
||||
@request.port = 80
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
xml = REXML::Document.new(r.body)
|
||||
|
||||
expected_page_links =
|
||||
['http://foo.bar.info/wiki1/published/HomePage',
|
||||
['http://foo.bar.info/wiki1/published/Elephant',
|
||||
'http://foo.bar.info/wiki1/published/Oak',
|
||||
'http://foo.bar.info/wiki1/published/Elephant']
|
||||
'http://foo.bar.info/wiki1/published/NoWikiWord',
|
||||
'http://foo.bar.info/wiki1/published/ThatWay',
|
||||
'http://foo.bar.info/wiki1/published/SmartEngine',
|
||||
'http://foo.bar.info/wiki1/published/MyWay',
|
||||
'http://foo.bar.info/wiki1/published/FirstPage',
|
||||
'http://foo.bar.info/wiki1/published/HomePage']
|
||||
|
||||
assert_template_xpath_match '/rss/channel/link',
|
||||
'http://foo.bar.info/wiki1/published/HomePage'
|
||||
|
@ -463,45 +455,43 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
setup_wiki_with_30_pages
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1'
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal 15, pages.size, 15
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => '5'
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal 5, pages.size
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => '25'
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal 25, pages.size
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => 'all'
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal 31, pages.size
|
||||
assert_equal 38, pages.size
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-16'
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal 16, pages.size
|
||||
assert_equal 23, pages.size
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1', 'end' => '1976-10-16'
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal 15, pages.size
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-01', 'end' => '1976-10-06'
|
||||
assert_success
|
||||
assert_response :success
|
||||
pages = r.template_objects['pages_by_revision']
|
||||
assert_equal 5, pages.size
|
||||
end
|
||||
|
||||
def test_rss_title_with_ampersand
|
||||
# was ticket:143
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
# was ticket:143
|
||||
@wiki.write_page('wiki1', 'Title&With&Ampersands',
|
||||
'About spaces', 1.hour.ago, Author.new('NitPicker', '127.0.0.3'))
|
||||
|
||||
|
@ -511,15 +501,12 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
assert r.body.include?('<title>Title&With&Ampersands</title>')
|
||||
end
|
||||
|
||||
def test_rss_timestamp
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
def test_rss_timestamp
|
||||
new_page = @wiki.write_page('wiki1', 'PageCreatedAtTheBeginningOfCtime',
|
||||
'Created on 1 Jan 1970 at 0:00:00 Z', Time.at(0), Author.new('NitPicker', '127.0.0.3'))
|
||||
|
||||
r = process 'rss_with_headlines', 'web' => 'wiki1'
|
||||
|
||||
assert_template_xpath_match '/rss/channel/item/pubDate[4]', "Thu, 01 Jan 1970 00:00:00 Z"
|
||||
assert_template_xpath_match '/rss/channel/item/pubDate[9]', "Thu, 01 Jan 1970 00:00:00 Z"
|
||||
end
|
||||
|
||||
def test_save
|
||||
|
@ -535,6 +522,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
def test_save_new_revision_of_existing_page
|
||||
@home.lock(Time.now, 'Batman')
|
||||
current_revisions = @home.revisions.size
|
||||
|
||||
r = process 'save', 'web' => 'wiki1', 'id' => 'HomePage', 'content' => 'Revised HomePage',
|
||||
'author' => 'Batman'
|
||||
|
@ -542,8 +530,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
||||
assert_equal ['Batman'], r.cookies['author'].value
|
||||
home_page = @wiki.read_page('wiki1', 'HomePage')
|
||||
assert_equal [home_page], @web.pages.values
|
||||
assert_equal 2, home_page.revisions.size
|
||||
assert_equal current_revisions+1, home_page.revisions.size
|
||||
assert_equal 'Revised HomePage', home_page.content
|
||||
assert_equal 'Batman', home_page.author
|
||||
assert !home_page.locked?(Time.now)
|
||||
|
@ -563,57 +550,47 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
revisions_after = @home.revisions.size
|
||||
assert_equal revisions_before, revisions_after
|
||||
@home = Page.find(@home.id)
|
||||
assert !@home.locked?(Time.now), 'HomePage should be unlocked if an edit was unsuccessful'
|
||||
end
|
||||
|
||||
|
||||
def test_search
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process 'search', 'web' => 'wiki1', 'query' => '\s[A-Z]ak'
|
||||
|
||||
assert_redirected_to :action => 'show', :id => 'Oak'
|
||||
end
|
||||
|
||||
def test_search_multiple_results
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process 'search', 'web' => 'wiki1', 'query' => 'All about'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal 'All about', r.template_objects['query']
|
||||
assert_equal [@elephant, @oak], r.template_objects['results']
|
||||
assert_equal [], r.template_objects['title_results']
|
||||
end
|
||||
|
||||
def test_search_by_content_and_title
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process 'search', 'web' => 'wiki1', 'query' => '(Oak|Elephant)'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal '(Oak|Elephant)', r.template_objects['query']
|
||||
assert_equal [@elephant, @oak], r.template_objects['results']
|
||||
assert_equal [@elephant, @oak], r.template_objects['title_results']
|
||||
end
|
||||
|
||||
def test_search_zero_results
|
||||
setup_wiki_with_three_pages
|
||||
|
||||
r = process 'search', 'web' => 'wiki1', 'query' => 'non-existant text'
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_equal [], r.template_objects['results']
|
||||
assert_equal [], r.template_objects['title_results']
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
def test_show_page
|
||||
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
|
||||
assert_success
|
||||
assert_match /First revision of the <a.*HomePage.*<\/a> end/, r.body
|
||||
r = process('show', 'id' => 'Oak', 'web' => 'wiki1')
|
||||
assert_response :success
|
||||
assert_tag :content => /All about oak/
|
||||
end
|
||||
|
||||
def test_show_page_with_multiple_revisions
|
||||
|
@ -622,7 +599,7 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
|
||||
|
||||
assert_success
|
||||
assert_response :success
|
||||
assert_match /Second revision of the <a.*HomePage.*<\/a> end/, r.body
|
||||
end
|
||||
|
||||
|
@ -633,24 +610,25 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
def test_show_no_page
|
||||
r = process('show', 'id' => '', 'web' => 'wiki1')
|
||||
assert_equal 404, r.response_code
|
||||
assert_response :missing
|
||||
|
||||
r = process('show', 'web' => 'wiki1')
|
||||
assert_equal 404, r.response_code
|
||||
assert_response :missing
|
||||
end
|
||||
|
||||
|
||||
def test_tex
|
||||
r = process('tex', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||
assert_success
|
||||
assert_response :success
|
||||
|
||||
assert_equal "\\documentclass[12pt,titlepage]{article}\n\n\\usepackage[danish]{babel} " +
|
||||
"%danske tekster\n\\usepackage[OT1]{fontenc} %rigtige danske bogstaver...\n" +
|
||||
"\\usepackage{a4}\n\\usepackage{graphicx}\n\\usepackage{ucs}\n\\usepackage[utf8x]" +
|
||||
"{inputenc}\n\\input epsf \n\n%----------------------------------------------------" +
|
||||
"---------------\n\n\\begin{document}\n\n\\sloppy\n\n%-----------------------------" +
|
||||
"--------------------------------------\n\n\\section*{HomePage}\n\nFirst revision of " +
|
||||
"the HomePage end\n\n\\end{document}", r.body
|
||||
"--------------------------------------\n\n\\section*{HomePage}\n\nHisWay would be " +
|
||||
"MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that " +
|
||||
"SmartEngineGUI\n\n\\end{document}", r.body
|
||||
end
|
||||
|
||||
|
||||
|
@ -659,8 +637,8 @@ class WikiControllerTest < Test::Unit::TestCase
|
|||
|
||||
r = process('web_list')
|
||||
|
||||
assert_success
|
||||
assert_equal [another_wiki, @web], r.template_objects['webs']
|
||||
assert_response :success
|
||||
assert_equal [another_wiki, webs(:instiki), @web], r.template_objects['webs']
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -10,17 +10,97 @@ require 'active_record/fixtures'
|
|||
require 'action_controller/test_process'
|
||||
require 'action_web_service/test_invoke'
|
||||
require 'breakpoint'
|
||||
require 'wiki_content'
|
||||
|
||||
# Uncomment these and hang on, because the tests will be FAST
|
||||
#Test::Unit::TestCase.pre_loaded_fixtures = false
|
||||
#Test::Unit::TestCase.use_transactional_fixtures = true
|
||||
|
||||
Test::Unit::TestCase.use_instantiated_fixtures = false
|
||||
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
||||
|
||||
class Test::Unit::TestCase
|
||||
# Turn these on to use transactional fixtures with table_name(:fixture_name) instantiation of fixtures
|
||||
# self.use_transactional_fixtures = true
|
||||
# self.use_instantiated_fixtures = false
|
||||
|
||||
def create_fixtures(*table_names)
|
||||
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
|
||||
end
|
||||
|
||||
# Add more helper methods to be used by all tests here...
|
||||
end
|
||||
def set_web_property(property, value)
|
||||
@web.update_attribute(property, value)
|
||||
@page = Page.find(@page.id)
|
||||
@wiki.webs[@web.name] = @web
|
||||
end
|
||||
|
||||
def setup_wiki_with_30_pages
|
||||
ActiveRecord::Base.silence do
|
||||
(1..30).each do |i|
|
||||
@wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
|
||||
Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
|
||||
end
|
||||
end
|
||||
@web = Web.find(@web.id)
|
||||
end
|
||||
|
||||
def use_blank_wiki
|
||||
Revision.destroy_all
|
||||
Page.destroy_all
|
||||
Web.destroy_all
|
||||
end
|
||||
end
|
||||
|
||||
# This module is to be included in unit tests that involve matching chunks.
|
||||
# It provides a easy way to test whether a chunk matches a particular string
|
||||
# and any the values of any fields that should be set after a match.
|
||||
class ContentStub < String
|
||||
include ChunkManager
|
||||
def initialize(str)
|
||||
super
|
||||
init_chunk_manager
|
||||
end
|
||||
def page_link(*); end
|
||||
end
|
||||
|
||||
module ChunkMatch
|
||||
|
||||
# Asserts a number of tests for the given type and text.
|
||||
def match(chunk_type, test_text, expected_chunk_state)
|
||||
if chunk_type.respond_to? :pattern
|
||||
assert_match(chunk_type.pattern, test_text)
|
||||
end
|
||||
|
||||
content = ContentStub.new(test_text)
|
||||
chunk_type.apply_to(content)
|
||||
|
||||
# Test if requested parts are correct.
|
||||
expected_chunk_state.each_pair do |a_method, expected_value|
|
||||
assert content.chunks.last.kind_of?(chunk_type)
|
||||
assert_respond_to(content.chunks.last, a_method)
|
||||
assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
|
||||
"Wrong #{a_method} value")
|
||||
end
|
||||
end
|
||||
|
||||
# Asserts that test_text doesn't match the chunk_type
|
||||
def no_match(chunk_type, test_text)
|
||||
if chunk_type.respond_to? :pattern
|
||||
assert_no_match(chunk_type.pattern, test_text)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
|
||||
module Test
|
||||
module Unit
|
||||
module Assertions
|
||||
unless method_defined? :__assert_success_before_override_by_instiki
|
||||
alias :__assert_success_before_override_by_instiki :assert_success
|
||||
end
|
||||
def assert_success
|
||||
__assert_success_before_override_by_instiki
|
||||
if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
|
||||
else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
require 'diff'
|
||||
|
||||
include Diff
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require 'fileutils'
|
||||
|
@ -67,4 +67,4 @@ class FileYardTest < Test::Unit::TestCase
|
|||
"#{RAILS_ROOT}/storage/test/instiki"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,78 @@
|
|||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class PageTest < Test::Unit::TestCase
|
||||
|
||||
fixtures 'webs', 'pages', 'revisions'
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
@page = pages(:first_page)
|
||||
end
|
||||
|
||||
def test_lock
|
||||
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
|
||||
|
||||
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
|
||||
|
||||
assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
|
||||
assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
|
||||
|
||||
@page.unlock
|
||||
|
||||
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
|
||||
end
|
||||
|
||||
def test_lock_duration
|
||||
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
|
||||
|
||||
assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
|
||||
end
|
||||
|
||||
def test_plain_name
|
||||
assert_equal "First Page", @page.plain_name
|
||||
end
|
||||
|
||||
def test_revise
|
||||
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
|
||||
assert_equal 2, @page.revisions(true).length, 'Should have two revisions'
|
||||
assert_equal 'MarianneSyhler', @page.current_revision(true).author.to_s, 'Mary should be the author now'
|
||||
assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
|
||||
end
|
||||
|
||||
def test_revise_continous_revision
|
||||
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
|
||||
assert_equal 2, @page.revisions(true).length
|
||||
|
||||
@page.current_revision(true)
|
||||
@page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
|
||||
assert_equal 2, @page.revisions(true).length
|
||||
assert_equal 'HisWay would be MyWay in kinda update', @page.revisions.last.content
|
||||
assert_equal Time.local(2004, 4, 4, 16, 57), @page.revisions.last.created_at
|
||||
|
||||
@page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
|
||||
assert_equal 3, @page.revisions(true).length
|
||||
assert_equal 'HisWay would be MyWay in the house', @page.revisions.last.content
|
||||
|
||||
@page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
|
||||
assert_equal 4, @page.revisions(true).length
|
||||
end
|
||||
|
||||
def test_revise_content_unchanged
|
||||
last_revision_before = @page.current_revision
|
||||
revisions_number_before = @page.revisions.size
|
||||
|
||||
assert_raises(Instiki::ValidationError) {
|
||||
@page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
|
||||
}
|
||||
|
||||
assert_equal last_revision_before, @page.current_revision(true)
|
||||
assert_equal revisions_number_before, @page.revisions.size
|
||||
end
|
||||
|
||||
def test_rollback
|
||||
@page.revise("spot two", Time.now, "David")
|
||||
@page.revise("spot three", Time.now + 2000, "David")
|
||||
assert_equal 3, @page.revisions(true).length, "Should have three revisions"
|
||||
@page.current_revision(true)
|
||||
@page.rollback(1, Time.now)
|
||||
assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require 'redcloth_for_tex'
|
||||
|
@ -66,4 +66,4 @@ EOL
|
|||
def test_subsection_depth
|
||||
assert_equal "\\subsubsection*{Hello}", RedClothForTex.new("h4. Hello").to_tex
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,315 @@
|
|||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class RevisionTest < Test::Unit::TestCase
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
fixtures 'webs', 'pages', 'revisions'
|
||||
def setup
|
||||
@wiki = Wiki.new
|
||||
@web = webs(:test_wiki)
|
||||
@page = pages(:home_page)
|
||||
@revision = revisions(:home_page_second_revision)
|
||||
end
|
||||
|
||||
def test_wiki_words
|
||||
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
|
||||
|
||||
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
|
||||
assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
|
||||
end
|
||||
|
||||
def test_existing_pages
|
||||
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
|
||||
end
|
||||
|
||||
def test_unexisting_pages
|
||||
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
|
||||
end
|
||||
|
||||
def test_content_with_wiki_links
|
||||
assert_equal '<p><span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||
'would be <a class="existingWikiWord" href="../show/MyWay">My Way</a> in kinda ' +
|
||||
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
|
||||
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere—see ' +
|
||||
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
|
||||
'<span class="newWikiWord">Smart Engine GUI' +
|
||||
'<a href="../show/SmartEngineGUI">?</a></span></p>',
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_markdown
|
||||
set_web_property :markup, :markdown
|
||||
|
||||
assert_markup_parsed_as(
|
||||
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
|
||||
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
|
||||
"My Headline\n===========\n\nthat SmartEngineGUI")
|
||||
|
||||
code_block = [
|
||||
'This is a code block:',
|
||||
'',
|
||||
' def a_method(arg)',
|
||||
' return ThatWay',
|
||||
'',
|
||||
'Nice!'
|
||||
].join("\n")
|
||||
|
||||
assert_markup_parsed_as(
|
||||
%{<p>This is a code block:</p>\n\n<pre><code>def a_method(arg)\n} +
|
||||
%{return ThatWay\n</code></pre>\n\n<p>Nice!</p>},
|
||||
code_block)
|
||||
end
|
||||
|
||||
def test_markdown_hyperlink_with_slash
|
||||
# in response to a bug, see http://dev.instiki.org/attachment/ticket/177
|
||||
set_web_property :markup, :markdown
|
||||
|
||||
assert_markup_parsed_as(
|
||||
'<p><a href="http://example/with/slash">text</a></p>',
|
||||
'[text](http://example/with/slash)')
|
||||
end
|
||||
|
||||
def test_mixed_formatting
|
||||
textile_and_markdown = [
|
||||
'Markdown heading',
|
||||
'================',
|
||||
'',
|
||||
'h2. Textile heading',
|
||||
'',
|
||||
'*some* **text** _with_ -styles-',
|
||||
'',
|
||||
'* list 1',
|
||||
'* list 2'
|
||||
].join("\n")
|
||||
|
||||
set_web_property :markup, :markdown
|
||||
assert_markup_parsed_as(
|
||||
"<h1>Markdown heading</h1>\n\n" +
|
||||
"<p>h2. Textile heading</p>\n\n" +
|
||||
"<p><em>some</em> <strong>text</strong> <em>with</em> -styles-</p>\n\n" +
|
||||
"<ul>\n<li>list 1</li>\n<li>list 2</li>\n</ul>",
|
||||
textile_and_markdown)
|
||||
|
||||
set_web_property :markup, :textile
|
||||
assert_markup_parsed_as(
|
||||
"<p>Markdown heading<br />================</p>\n\n\n\t<h2>Textile heading</h2>" +
|
||||
"\n\n\n\t<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>" +
|
||||
"\n\n\n\t<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
|
||||
textile_and_markdown)
|
||||
|
||||
set_web_property :markup, :mixed
|
||||
assert_markup_parsed_as(
|
||||
"<h1>Markdown heading</h1>\n\n\n\t<h2>Textile heading</h2>\n\n\n\t" +
|
||||
"<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>\n\n\n\t" +
|
||||
"<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
|
||||
textile_and_markdown)
|
||||
end
|
||||
|
||||
def test_rdoc
|
||||
set_web_property :markup, :rdoc
|
||||
|
||||
@revision = Revision.new(:page => @page, :content => '+hello+ that SmartEngineGUI',
|
||||
:author => Author.new('DavidHeinemeierHansson'))
|
||||
|
||||
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
|
||||
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
|
||||
end
|
||||
|
||||
def test_content_with_auto_links
|
||||
assert_markup_parsed_as(
|
||||
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
|
||||
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
|
||||
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
|
||||
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
|
||||
|
||||
end
|
||||
|
||||
def test_content_with_aliased_links
|
||||
assert_markup_parsed_as(
|
||||
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
|
||||
'</a> go by any other name?</p>',
|
||||
'Would a [[SmartEngine|clever motor]] go by any other name?')
|
||||
end
|
||||
|
||||
def test_content_with_wikiword_in_em
|
||||
assert_markup_parsed_as(
|
||||
'<p><em>should we go <a class="existingWikiWord" href="../show/ThatWay">' +
|
||||
'That Way</a> or <span class="newWikiWord">This Way<a href="../show/ThisWay">?</a>' +
|
||||
'</span> </em></p>',
|
||||
'_should we go ThatWay or ThisWay _')
|
||||
end
|
||||
|
||||
def test_content_with_wikiword_in_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
|
||||
'That is some <em style="WikiWord">Stylish Emphasis</em>')
|
||||
end
|
||||
|
||||
def test_content_with_escaped_wikiword
|
||||
# there should be no wiki link
|
||||
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
|
||||
end
|
||||
|
||||
def test_content_with_pre_blocks
|
||||
assert_markup_parsed_as(
|
||||
'<p>A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre></p>',
|
||||
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
|
||||
end
|
||||
|
||||
def test_content_with_autolink_in_parentheses
|
||||
assert_markup_parsed_as(
|
||||
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
|
||||
'http://www.w3c.org</a>) sets web standards</p>',
|
||||
'The W3C body (http://www.w3c.org) sets web standards')
|
||||
end
|
||||
|
||||
def test_content_with_link_in_parentheses
|
||||
assert_markup_parsed_as(
|
||||
'<p>(<a href="http://wiki.org/wiki.cgi?WhatIsWiki">What is a wiki?</a>)</p>',
|
||||
'("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
|
||||
end
|
||||
|
||||
def test_content_with_image_link
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is a Textile image link.</p>',
|
||||
'This !http://hobix.com/sample.jpg! is a Textile image link.')
|
||||
end
|
||||
|
||||
def test_content_with_inlined_img_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.</p>',
|
||||
'This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.')
|
||||
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.</p>',
|
||||
'This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.')
|
||||
end
|
||||
|
||||
def test_nowiki_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
|
||||
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
|
||||
'or <nowiki>http://www.thislink.com</nowiki>.')
|
||||
end
|
||||
|
||||
def test_multiline_nowiki_tag
|
||||
assert_markup_parsed_as(
|
||||
"<p>Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
|
||||
'<span class="newWikiWord">this<a href="../show/this">?</a></span></p>',
|
||||
"Do not <nowiki>mark \n up [[this text]] \n" +
|
||||
"and http://this.url.com </nowiki> but markup [[this]]")
|
||||
end
|
||||
|
||||
def test_content_with_bracketted_wiki_word
|
||||
set_web_property :brackets_only, true
|
||||
assert_markup_parsed_as(
|
||||
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
|
||||
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
|
||||
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
|
||||
end
|
||||
|
||||
def test_content_for_export
|
||||
assert_equal '<p><span class="newWikiWord">His Way</span> would be ' +
|
||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> in kinda ' +
|
||||
'<a class="existingWikiWord" href="ThatWay.html">That Way</a> in ' +
|
||||
'<span class="newWikiWord">His Way</span> though ' +
|
||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere—see ' +
|
||||
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
|
||||
'<span class="newWikiWord">Smart Engine GUI</span></p>',
|
||||
@revision.display_content_for_export
|
||||
end
|
||||
|
||||
def test_double_replacing
|
||||
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
|
||||
assert_equal '<p><span class="newWikiWord">Version History' +
|
||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
|
||||
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
|
||||
'</span></p>',
|
||||
@revision.display_content
|
||||
|
||||
@revision.clear_display_cache
|
||||
|
||||
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
|
||||
assert_equal "<p>f<br /><span class=\"newWikiWord\">Version History" +
|
||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
|
||||
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
|
||||
"</span></p>",
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_difficult_wiki_words
|
||||
@revision.content = "[[It's just awesome GUI!]]"
|
||||
assert_equal "<p><span class=\"newWikiWord\">It's just awesome GUI!" +
|
||||
"<a href=\"../show/It%27s+just+awesome+GUI%21\">?</a></span></p>",
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_revisions_diff
|
||||
Revision.create(:page => @page, :content => 'What a blue and lovely morning', :author => Author.new('DavidHeinemeierHansson'))
|
||||
Revision.create(:page => @page, :content => 'What a red and lovely morning today', :author => Author.new('DavidHeinemeierHansson'))
|
||||
|
||||
assert_equal "<p>What a <del class=\"diffmod\">blue </del><ins class=\"diffmod\">red " +
|
||||
"</ins>and lovely <del class=\"diffmod\">morning</del><ins class=\"diffmod\">morning " +
|
||||
"today</ins></p>", @page.revisions.last.display_diff
|
||||
end
|
||||
|
||||
def test_link_to_file
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
|
||||
'[[doc.pdf:file]]')
|
||||
end
|
||||
|
||||
def test_link_to_pic
|
||||
FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1"
|
||||
FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"])
|
||||
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
|
||||
assert_markup_parsed_as(
|
||||
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
|
||||
'[[square.jpg|Square:pic]]')
|
||||
assert_markup_parsed_as(
|
||||
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
|
||||
'[[square.jpg:pic]]')
|
||||
end
|
||||
|
||||
def test_link_to_non_existant_pic
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
|
||||
'</span></p>',
|
||||
'[[NonExistant.jpg|NonExistant:pic]]')
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
|
||||
'</span></p>',
|
||||
'[[NonExistant.jpg:pic]]')
|
||||
end
|
||||
|
||||
def test_wiki_link_with_colon
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">With:Colon<a href="../show/With%3AColon">?</a></span></p>',
|
||||
'[[With:Colon]]')
|
||||
end
|
||||
|
||||
# TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
|
||||
# also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
|
||||
def test_list_with_tildas
|
||||
list_with_tildas = <<-EOL
|
||||
* "a":~b
|
||||
* c~ d
|
||||
EOL
|
||||
|
||||
assert_markup_parsed_as(
|
||||
"<ul>\n\t<li><a href=\"~b\">a</a></li>\n\t\t<li>c~ d</li>\n\t</ul>",
|
||||
list_with_tildas)
|
||||
end
|
||||
|
||||
def test_textile_image_in_mixed_wiki
|
||||
set_web_property :markup, :mixed
|
||||
assert_markup_parsed_as(
|
||||
"<p><img src=\"http://google.com\" alt=\"\" />\nss</p>",
|
||||
"!http://google.com!\r\nss")
|
||||
end
|
||||
|
||||
def assert_markup_parsed_as(expected_output, input)
|
||||
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
|
||||
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require 'chunks/uri'
|
||||
|
|
|
@ -1,7 +1,158 @@
|
|||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class WebTest < Test::Unit::TestCase
|
||||
|
||||
fixtures 'webs', 'pages', 'revisions'
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
@web = webs(:instiki)
|
||||
end
|
||||
|
||||
def test_wiki_word_linking
|
||||
@web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated',
|
||||
Time.now, 'DavidHeinemeierHansson')
|
||||
|
||||
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
|
||||
'<a href="../show/EverBeenHated">?</a></span></p>',
|
||||
@web.page("SecondPage").display_content)
|
||||
|
||||
@web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
|
||||
'DavidHeinemeierHansson')
|
||||
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
|
||||
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
|
||||
@web.page("SecondPage").display_content)
|
||||
end
|
||||
|
||||
def test_pages_by_revision
|
||||
add_sample_pages
|
||||
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
|
||||
end
|
||||
|
||||
def test_pages_by_match
|
||||
add_sample_pages
|
||||
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
|
||||
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
|
||||
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
|
||||
end
|
||||
|
||||
def test_references
|
||||
add_sample_pages
|
||||
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
|
||||
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
|
||||
end
|
||||
|
||||
def test_delete
|
||||
add_sample_pages
|
||||
assert_equal 2, @web.pages.length
|
||||
@web.remove_pages([ @web.page('EverBeenInLove') ])
|
||||
assert_equal 1, @web.pages(true).length
|
||||
end
|
||||
|
||||
def test_make_link
|
||||
add_sample_pages
|
||||
|
||||
existing_page_wiki_url =
|
||||
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
|
||||
existing_page_published_url =
|
||||
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
|
||||
existing_page_static_url =
|
||||
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
|
||||
new_page_wiki_url =
|
||||
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
|
||||
new_page_published_url =
|
||||
new_page_static_url =
|
||||
'<span class="newWikiWord">Unknown Word</span>'
|
||||
|
||||
# no options
|
||||
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
|
||||
|
||||
# :mode => :export
|
||||
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
|
||||
|
||||
# :mode => :publish
|
||||
assert_equal existing_page_published_url,
|
||||
@web.make_link('EverBeenInLove', nil, :mode => :publish)
|
||||
|
||||
# new page, no options
|
||||
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
|
||||
|
||||
# new page, :mode => :export
|
||||
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
|
||||
|
||||
# new page, :mode => :publish
|
||||
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
|
||||
|
||||
# Escaping special characters in the name
|
||||
assert_equal(
|
||||
'<span class="newWikiWord">Smith & Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
|
||||
@web.make_link('Smith & Wesson'))
|
||||
|
||||
# optionally using text as the link text
|
||||
assert_equal(
|
||||
existing_page_published_url.sub(/>Ever Been In Love</, ">Haven't you ever been in love?<"),
|
||||
@web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
|
||||
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123')
|
||||
|
||||
assert_equal 'Wiki2', web.name
|
||||
assert_equal 'wiki2', web.address
|
||||
assert_equal '123', web.password
|
||||
|
||||
# new web should be set for maximum features enabled
|
||||
assert_equal :textile, web.markup
|
||||
assert_equal '008B26', web.color
|
||||
assert !web.safe_mode?
|
||||
assert_equal([], web.pages)
|
||||
assert web.allow_uploads?
|
||||
assert_nil web.additional_style
|
||||
assert !web.published?
|
||||
assert !web.brackets_only?
|
||||
assert !web.count_pages?
|
||||
assert_equal 100, web.max_upload_size
|
||||
end
|
||||
|
||||
def test_initialize_invalid_name
|
||||
assert_raises(Instiki::ValidationError) {
|
||||
Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123')
|
||||
}
|
||||
end
|
||||
|
||||
def test_new_page_linked_from_mother_page
|
||||
# this was a bug in revision 204
|
||||
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
|
||||
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
|
||||
@web.add_page('AnotherPage', 'This is \AnotherPage',
|
||||
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
|
||||
|
||||
@web.pages(true)
|
||||
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
|
||||
end
|
||||
|
||||
def test_orphaned_pages
|
||||
add_sample_pages
|
||||
home = @web.add_page('HomePage',
|
||||
'This is a home page, it should not be an orphan',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
|
||||
author = @web.add_page('AlexeyVerkhovsky',
|
||||
'This is an author page, it should not be an orphan',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
|
||||
self_linked = @web.add_page('SelfLinked',
|
||||
'I am me SelfLinked and link to EverBeenInLove',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
|
||||
|
||||
# page that links to itself, and nobody else links to it must be an orphan
|
||||
assert_equal ['EverBeenHated', 'SelfLinked'],
|
||||
@web.select.orphaned_pages.collect{ |page| page.name }.sort
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_sample_pages
|
||||
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
|
||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
||||
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
|
||||
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/env ruby -w
|
||||
#!/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
require 'wiki_words'
|
||||
|
||||
class WikiWordsTest < Test::Unit::TestCase
|
||||
|
|
Loading…
Reference in a new issue