194 lines
7.8 KiB
Ruby
194 lines
7.8 KiB
Ruby
require 'spec_helper'
|
|
require_dependency 'jobs/base'
|
|
|
|
describe Jobs::Exporter do
|
|
before do
|
|
Jobs::Exporter.any_instance.stubs(:log).returns(true)
|
|
Jobs::Exporter.any_instance.stubs(:create_tar_file).returns(true)
|
|
Export::JsonEncoder.any_instance.stubs(:tmp_directory).returns( File.join(Rails.root, 'tmp', 'exporter_spec') )
|
|
Discourse.stubs(:enable_maintenance_mode).returns(true)
|
|
Discourse.stubs(:disable_maintenance_mode).returns(true)
|
|
end
|
|
|
|
describe "execute" do
|
|
context 'when no export or import is running' do
|
|
before do
|
|
@testIO = StringIO.new
|
|
Export::JsonEncoder.any_instance.stubs(:json_output_stream).returns(@testIO)
|
|
Jobs::Exporter.any_instance.stubs(:ordered_models_for_export).returns([])
|
|
Export.stubs(:is_export_running?).returns(false)
|
|
Export.stubs(:is_import_running?).returns(false)
|
|
@exporter_args = {}
|
|
end
|
|
|
|
it "should indicate that an export is running" do
|
|
seq = sequence('call sequence')
|
|
Export.expects(:set_export_started).in_sequence(seq).at_least_once
|
|
Export.expects(:set_export_is_not_running).in_sequence(seq).at_least_once
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
end
|
|
|
|
it "should put the site in maintenance mode when it starts" do
|
|
encoder = stub_everything
|
|
Export::JsonEncoder.stubs(:new).returns(encoder)
|
|
seq = sequence('export-sequence')
|
|
Discourse.expects(:enable_maintenance_mode).in_sequence(seq).at_least_once
|
|
encoder.expects(:write_schema_info).in_sequence(seq).at_least_once
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
end
|
|
|
|
it "should take the site out of maintenance mode when it ends" do
|
|
encoder = stub_everything
|
|
Export::JsonEncoder.stubs(:new).returns(encoder)
|
|
seq = sequence('export-sequence')
|
|
encoder.expects(:write_schema_info).in_sequence(seq).at_least_once
|
|
Discourse.expects(:disable_maintenance_mode).in_sequence(seq).at_least_once
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
end
|
|
|
|
describe "without specifying a format" do
|
|
it "should use json as the default" do
|
|
Export::JsonEncoder.expects(:new).returns( stub_everything )
|
|
Jobs::Exporter.new.execute( @exporter_args.reject { |key, val| key == :format } )
|
|
end
|
|
end
|
|
|
|
describe "specifying an invalid format" do
|
|
it "should raise an exception and not flag that an export has started" do
|
|
Jobs::Exporter.expects(:set_export_started).never
|
|
expect {
|
|
Jobs::Exporter.new.execute( @exporter_args.merge( format: :interpretive_dance ) )
|
|
}.to raise_error(Export::FormatInvalidError)
|
|
end
|
|
end
|
|
|
|
context "using json format" do
|
|
before do
|
|
@exporter_args = {format: :json}
|
|
end
|
|
|
|
it "should export metadata" do
|
|
version = '201212121212'
|
|
encoder = stub_everything
|
|
encoder.expects(:write_schema_info).with do |arg|
|
|
arg[:source].should == 'discourse'
|
|
arg[:version].should == version
|
|
end
|
|
Export::JsonEncoder.stubs(:new).returns(encoder)
|
|
Export.stubs(:current_schema_version).returns(version)
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
end
|
|
|
|
describe "exporting tables" do
|
|
before do
|
|
# Create some real database records
|
|
@user1, @user2 = Fabricate(:user), Fabricate(:user)
|
|
@topic1 = Fabricate(:topic, user: @user1)
|
|
@topic2 = Fabricate(:topic, user: @user2)
|
|
@topic3 = Fabricate(:topic, user: @user1)
|
|
@post1 = Fabricate(:post, topic: @topic1, user: @user1)
|
|
@post1 = Fabricate(:post, topic: @topic3, user: @user1)
|
|
@reply1 = Fabricate(:basic_reply, user: @user2, topic: @topic3)
|
|
@reply1.save_reply_relationships
|
|
@reply2 = Fabricate(:basic_reply, user: @user1, topic: @topic1)
|
|
@reply2.save_reply_relationships
|
|
@reply3 = Fabricate(:basic_reply, user: @user1, topic: @topic3)
|
|
@reply3.save_reply_relationships
|
|
end
|
|
|
|
it "should export all rows from the topics table in ascending id order" do
|
|
Jobs::Exporter.any_instance.stubs(:ordered_models_for_export).returns([Topic])
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
json = JSON.parse( @testIO.string )
|
|
json.should have_key('topics')
|
|
json['topics'].should have_key('rows')
|
|
json['topics']['rows'].should have(3).rows
|
|
json['topics']['rows'][0][0].to_i.should == @topic1.id
|
|
json['topics']['rows'][1][0].to_i.should == @topic2.id
|
|
json['topics']['rows'][2][0].to_i.should == @topic3.id
|
|
end
|
|
|
|
it "should export all rows from the post_replies table in ascending order by post_id, reply_id" do
|
|
# because post_replies doesn't have an id column, so order by one of its indexes
|
|
Jobs::Exporter.any_instance.stubs(:ordered_models_for_export).returns([PostReply])
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
json = JSON.parse( @testIO.string )
|
|
json.should have_key('post_replies')
|
|
json['post_replies'].should have_key('rows')
|
|
json['post_replies']['rows'].should have(3).rows
|
|
json['post_replies']['rows'][0][1].to_i.should == @reply2.id
|
|
json['post_replies']['rows'][1][1].to_i.should == @reply1.id
|
|
json['post_replies']['rows'][2][1].to_i.should == @reply3.id
|
|
end
|
|
|
|
it "should export column names for each table" do
|
|
Jobs::Exporter.any_instance.stubs(:ordered_models_for_export).returns([Topic, TopicUser, PostReply])
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
json = JSON.parse( @testIO.string )
|
|
json['topics'].should have_key('fields')
|
|
json['topic_users'].should have_key('fields')
|
|
json['post_replies'].should have_key('fields')
|
|
json['topics']['fields'].should == Topic.columns.map(&:name)
|
|
json['topic_users']['fields'].should == TopicUser.columns.map(&:name)
|
|
json['post_replies']['fields'].should == PostReply.columns.map(&:name)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when it finishes successfully" do
|
|
context "and no user was given" do
|
|
it "should not send a notification to anyone" do
|
|
expect {
|
|
Jobs::Exporter.new.execute( @exporter_args )
|
|
}.to_not change { Notification.count }
|
|
end
|
|
end
|
|
|
|
context "and a user was given" do
|
|
before do
|
|
@user = Fabricate(:user)
|
|
@admin = Fabricate(:admin)
|
|
end
|
|
|
|
it "should send a notification to the user who started the export" do
|
|
|
|
ActiveRecord::Base.observers.enable :all
|
|
expect {
|
|
Jobs::Exporter.new.execute( @exporter_args.merge( user_id: @user.id ) )
|
|
}.to change { Notification.count }.by(1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when an export is already running' do
|
|
before do
|
|
Export.expects(:is_export_running?).returns(true)
|
|
end
|
|
|
|
it "should not start an export and raise an exception" do
|
|
Export.expects(:set_export_started).never
|
|
Jobs::Exporter.any_instance.expects(:start_export).never
|
|
expect {
|
|
Jobs::Exporter.new.execute({})
|
|
}.to raise_error(Export::ExportInProgressError)
|
|
end
|
|
end
|
|
|
|
context 'when an import is running' do
|
|
before do
|
|
Import.expects(:is_import_running?).returns(true)
|
|
end
|
|
|
|
it "should not start an export and raise an exception" do
|
|
Export.expects(:set_export_started).never
|
|
Jobs::Exporter.any_instance.expects(:start_export).never
|
|
expect {
|
|
Jobs::Exporter.new.execute({})
|
|
}.to raise_error(Import::ImportInProgressError)
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|