From a0e7869980e9d497d325fddc7d4f5a3feea56738 Mon Sep 17 00:00:00 2001 From: yasushiito Date: Sun, 16 Sep 2012 15:38:47 +0900 Subject: [PATCH] t#29400:itr3? --- app/controllers/application_controller.rb | 8 + app/controllers/home_controller.rb | 49 +- app/controllers/original_pictures_controller.rb | 19 +- app/controllers/pictures_controller.rb | 4 +- app/controllers/resource_pictures_controller.rb | 56 +- .../speech_balloon_templates_controller.rb | 11 +- app/controllers/system_pictures_controller.rb | 111 +-- app/models/author.rb | 28 +- app/models/original_picture.rb | 36 +- app/models/picture.rb | 103 ++- app/models/resource_picture.rb | 225 +++--- app/models/speech_balloon_template.rb | 116 ++- app/models/story.rb | 160 ++-- app/models/system_picture.rb | 107 ++- app/views/home/ground_color.html.erb | 19 + app/views/home/ground_picture.html.erb | 19 + app/views/home/panel_color.html.erb | 19 + app/views/system_pictures/new.html.erb | 4 + config/environment.rb | 2 + lib/pettan_imager.rb | 119 +++ lib/test/pettan_imager_spec.rb | 338 +++++++++ lib/test/test.png | Bin 0 -> 643 bytes spec/StandardA.gif | Bin 0 -> 1832 bytes .../controllers/ground_pictures_controller_spec.rb | 4 + spec/controllers/home_controller_spec.rb | 330 ++++++++- .../original_pictures_controller_spec.rb | 45 +- spec/controllers/panels_controller_spec.rb | 4 + spec/controllers/pictures_controller_spec.rb | 6 +- .../resource_pictures_controller_spec.rb | 609 ++++++++++++++-- .../speech_balloon_templates_controller_spec.rb | 38 +- spec/controllers/system_controller_spec.rb | 1 - .../controllers/system_pictures_controller_spec.rb | 433 +++++++++++ spec/models/comic_spec.rb | 10 +- spec/models/license_group_spec.rb | 2 + spec/models/original_picture_spec.rb | 318 +++++--- spec/models/picture_spec.rb | 586 +++++++-------- spec/models/resource_picture_spec.rb | 808 +++++++++++---------- spec/models/speech_balloon_template_spec.rb | 552 ++++++-------- spec/models/story_spec.rb | 286 ++++++-- spec/models/system_picture_spec.rb | 401 +++++++--- spec/support/imager_test.rb | 136 ++++ .../plugins/pettan_importer/lib/pettan_importer.rb | 4 +- 42 files changed, 4163 insertions(+), 1963 deletions(-) create mode 100644 app/views/home/ground_color.html.erb create mode 100644 app/views/home/ground_picture.html.erb create mode 100644 app/views/home/panel_color.html.erb create mode 100644 app/views/system_pictures/new.html.erb create mode 100644 lib/pettan_imager.rb create mode 100644 lib/test/pettan_imager_spec.rb create mode 100644 lib/test/test.png create mode 100644 spec/StandardA.gif create mode 100644 spec/support/imager_test.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 125b159b..b7496a23 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -36,6 +36,14 @@ class ApplicationController < ActionController::Base end end + def set_image(file) + if file.respond_to?(:read) + file.read + else + Base64.decode64(file.to_s.gsub(' ', '+')) #rubyのバグ?+でデコードされるべきキャラがスペースになる + end + end + =begin rescue_from ActiveRecord::RecordNotFound, :with => :render_404 diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 45644bb0..baf93000 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -2,7 +2,7 @@ class HomeController < ApplicationController layout 'test' if Pettanr::TestLayout before_filter :authenticate_user!, :only => [ :index, :show, :profile, :configure, :create_token, :delete_token, :step2, :save_step2, :step3, :save_step3, - :comic, :panel, :picture, :panel_picture + :comic, :panel, :picture, :panel_picture, :panel_color, :ground_picture, :ground_color ] before_filter :authenticate_artist, :only => [:picture] @@ -71,29 +71,29 @@ class HomeController < ApplicationController def comic @page = Author.page params[:page] @page_size = Author.comic_page_size params[:page_size] - @comics = Comic.mylist(@author, {}, @page, @page_size) + @comics = Comic.mylist(@author, @page, @page_size) respond_to do |format| format.html # index.html.erb - format.json { render json: @comics } + format.json { render json: @comics.to_json(Comic.list_json_opt) } end end def panel @page = Author.page params[:page] @page_size = Author.panel_page_size params[:page_size] - @panels = Panel.mylist(@author, {}, @page, @page_size) + @panels = Panel.mylist(@author, @page, @page_size) respond_to do |format| format.html # index.html.erb - format.json { render json: @panels } + format.json { render json: @panels.to_json(Panel.list_json_opt) } end end def picture @page = OriginalPicture.page params[:page] @page_size = OriginalPicture.page_size params[:page_size] - @original_pictures = OriginalPicture.list(@artist.id, {}, @page, @page_size) + @original_pictures = OriginalPicture.mylist(@artist.id, @page, @page_size) respond_to do |format| format.html # index.html.erb @@ -104,11 +104,44 @@ class HomeController < ApplicationController def panel_picture @page = Author.page params[:page] @page_size = Author.panel_picture_page_size params[:page_size] - @panel_pictures = PanelPicture.mylist(@author, {}, @page, @page_size) + @panel_pictures = PanelPicture.mylist(@author, @page, @page_size) respond_to do |format| format.html # index.html.erb - format.json { render json: @panel_pictures } + format.json { render json: @panel_pictures.to_json(PanelPicture.list_json_opt) } + end + end + + def panel_color + @page = Author.page params[:page] + @page_size = Author.panel_page_size params[:page_size] + @panel_colors = PanelColor.mylist(@author, @page, @page_size) + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @panel_colors.to_json(PanelColor.list_json_opt) } + end + end + + def ground_picture + @page = Author.page params[:page] + @page_size = Author.panel_page_size params[:page_size] + @ground_pictures = GroundPicture.mylist(@author, @page, @page_size) + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @ground_pictures.to_json(GroundPicture.list_json_opt) } + end + end + + def ground_color + @page = Author.page params[:page] + @page_size = Author.panel_page_size params[:page_size] + @ground_colors = GroundColor.mylist(@author, @page, @page_size) + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @ground_colors.to_json(GroundColor.list_json_opt) } end end diff --git a/app/controllers/original_pictures_controller.rb b/app/controllers/original_pictures_controller.rb index ca3bc02b..1896730c 100644 --- a/app/controllers/original_pictures_controller.rb +++ b/app/controllers/original_pictures_controller.rb @@ -5,18 +5,6 @@ class OriginalPicturesController < ApplicationController before_filter :authenticate_admin!, :only => [:list, :browse] before_filter :authenticate_artist, :only => [:index, :show, :history, :new, :edit, :create, :update, :destroy] - private - - def set_image(file) - if file.respond_to?(:read) - file.read - else - Base64.decode64(file.to_s.gsub(' ', '+')) #rubyのバグ?+でデコードされるべきキャラがスペースになる - end - end - - public - # GET /original_pictures # GET /original_pictures.json def index @@ -102,12 +90,13 @@ class OriginalPicturesController < ApplicationController # POST /original_pictures # POST /original_pictures.json def create - @picture_data = set_image params[:original_picture][:file] + @imager = PettanImager.load set_image params[:original_picture][:file] @original_picture = OriginalPicture.new - @original_picture.supply_default @artist + @original_picture.supply_default + @original_picture.overwrite @artist respond_to do |format| - if @original_picture.store(@picture_data, @artist) + if @original_picture.store(@imager) format.html { redirect_to @original_picture, notice: 'Original picture was successfully created.' } format.json { render json: @original_picture.to_json(OriginalPicture.show_json_opt), status: :created, location: @original_picture } else diff --git a/app/controllers/pictures_controller.rb b/app/controllers/pictures_controller.rb index 4ebe33a3..4fe261a5 100644 --- a/app/controllers/pictures_controller.rb +++ b/app/controllers/pictures_controller.rb @@ -3,7 +3,7 @@ class PicturesController < ApplicationController before_filter :authenticate_user!, :only => [:show, :credit] def show - @picture = Picture.show(params[:id]) + @picture = Picture.show(params[:id], @author) respond_to do |format| opt = {:type => @picture.mime_type, :disposition=>"inline"} @@ -16,7 +16,7 @@ class PicturesController < ApplicationController end def credit - @picture = Picture.show(params[:id]) + @picture = Picture.show(params[:id], @author) respond_to do |format| format.html { render :layout => false } # show.html.erb diff --git a/app/controllers/resource_pictures_controller.rb b/app/controllers/resource_pictures_controller.rb index b630cdd2..8d31b6d5 100644 --- a/app/controllers/resource_pictures_controller.rb +++ b/app/controllers/resource_pictures_controller.rb @@ -2,13 +2,14 @@ class ResourcePicturesController < ApplicationController layout 'test' if Pettanr::TestLayout before_filter :authenticate_user!, :only => [:index, :show, :credit, :new, :create, :update] before_filter :authenticate_admin!, :only => [:list, :browse] + before_filter :authenticate_artist, :only => [:new, :create] # GET /resource_pictures # GET /resource_pictures.json def index @page = ResourcePicture.page params[:page] @page_size = ResourcePicture.page_size params[:page_size] - @resource_pictures = ResourcePicture.list({}, @page, @page_size) + @resource_pictures = ResourcePicture.list(@page, @page_size) respond_to do |format| format.html # index.html.erb @@ -19,7 +20,7 @@ class ResourcePicturesController < ApplicationController # GET /resource_pictures/1 # GET /resource_pictures/1.json def show - @resource_picture = ResourcePicture.show(params[:id]) + @resource_picture = ResourcePicture.show(params[:id], @author) respond_to do |format| opt = {:type => @resource_picture.mime_type, :disposition=>"inline"} @@ -27,24 +28,31 @@ class ResourcePicturesController < ApplicationController format.gif { send_data(@resource_picture.restore(params[:subdir]), opt ) } format.jpeg { send_data(@resource_picture.restore(params[:subdir]), opt ) } format.html # show.html.erb - format.json { render :json => @resource_picture.to_json(ResourcePicture.list_json_opt)} + format.json { render :json => @resource_picture.to_json(ResourcePicture.show_json_opt)} end end def credit - @resource_picture = ResourcePicture.show(params[:id]) + @resource_picture = ResourcePicture.show(params[:id], @author) respond_to do |format| format.html { render :layout => false } # show.html.erb - format.json { render :json => @resource_picture.to_json(ResourcePicture.list_json_opt)} + format.json { render :json => @resource_picture.to_json(ResourcePicture.show_json_opt)} end end def new - @original_picture = OriginalPicture.show params[:original_picture_id], @artist + @original_picture = OriginalPicture.edit params[:original_picture_id], @artist + @imager = PettanImager.load @original_picture.restore @original_picture_license_group = OriginalPictureLicenseGroup.new params[:original_picture_license_group] @license_group = LicenseGroup.show @original_picture_license_group.license_group_id - @resource_picture = @original_picture.resource_picture || ResourcePicture.new(params[:resource_picture]) + @resource_picture = @original_picture.resource_picture + unless @resource_picture + @resource_picture = ResourcePicture.new + @resource_picture.supply_default + end + @resource_picture.attributes = params[:resource_picture] + @resource_picture.overwrite @original_picture @license = @resource_picture.license respond_to do |format| @@ -54,38 +62,26 @@ class ResourcePicturesController < ApplicationController end def create - @original_picture = OriginalPicture.show params[:original_picture_id], @artist - @original_picture_license_group = OriginalPictureLicenseGroup.new params[:original_picture_license_group] - @license_group = LicenseGroup.show @original_picture_license_group.license_group_id - @resource_picture = ResourcePicture.new(params[:resource_picture]) - @license = @resource_picture.license - - respond_to do |format| - if @resource_picture.store - format.html { redirect_to @resource_picture } - format.js { render json: @resource_picture, status: :created, location: @resource_picture } - else - format.html { render action: "new" } - format.js { render action: "new" } - end - end - end - - def update - @original_picture = OriginalPicture.show params[:original_picture_id], @artist + @original_picture = OriginalPicture.edit params[:original_picture_id], @artist + @imager = PettanImager.load @original_picture.restore @original_picture_license_group = OriginalPictureLicenseGroup.new params[:original_picture_license_group] @license_group = LicenseGroup.show @original_picture_license_group.license_group_id @resource_picture = @original_picture.resource_picture - @resource_picture.attributes = params[:resource_picture] + unless @resource_picture + @resource_picture = ResourcePicture.new + @resource_picture.supply_default + end + @resource_picture.attributes = params[:resource_picture] + @resource_picture.overwrite @original_picture @license = @resource_picture.license respond_to do |format| - if @resource_picture.store + if @resource_picture.store(@imager) format.html { redirect_to @resource_picture } - format.js { render json: @resource_picture, status: :created, location: @resource_picture } + format.json { render json: @resource_picture.to_json(ResourcePicture.show_json_opt), status: :created, location: @resource_picture } else format.html { render action: "new" } - format.js { render action: "new" } + format.json { render json: @resource_picture.errors, status: :unprocessable_entity } end end end diff --git a/app/controllers/speech_balloon_templates_controller.rb b/app/controllers/speech_balloon_templates_controller.rb index c95f03bd..1cbe2b8f 100644 --- a/app/controllers/speech_balloon_templates_controller.rb +++ b/app/controllers/speech_balloon_templates_controller.rb @@ -9,19 +9,19 @@ class SpeechBalloonTemplatesController < ApplicationController respond_to do |format| format.html # index.html.erb - format.json { render json: @speech_balloon_templates } + format.json { render json: @speech_balloon_templates.to_json(SpeechBalloonTemplate.list_json_opt) } end end # GET /speech_balloon_templates/1 # GET /speech_balloon_templates/1.json def show - @speech_balloon_template = SpeechBalloonTemplate.show(params[:id]) + @speech_balloon_template = SpeechBalloonTemplate.show(params[:id], @author) respond_to do |format| format.html # show.html.erb format.json { - render :json => @speech_balloon_template.to_json() + render :json => @speech_balloon_template.to_json(SpeechBalloonTemplate.show_json_opt) } format.jsonp { render :json => "callback(" + @speech_balloon_template.to_json() + ")" @@ -47,11 +47,6 @@ class SpeechBalloonTemplatesController < ApplicationController end end - # POST /speech_balloon_templates - # POST /speech_balloon_templates.json - def create - end - # DELETE /speech_balloon_templates/1 # DELETE /speech_balloon_templates/1.json def destroy diff --git a/app/controllers/system_pictures_controller.rb b/app/controllers/system_pictures_controller.rb index 884d33cb..e43e6723 100644 --- a/app/controllers/system_pictures_controller.rb +++ b/app/controllers/system_pictures_controller.rb @@ -1,60 +1,33 @@ class SystemPicturesController < ApplicationController + layout 'test' if Pettanr::TestLayout before_filter :authenticate_user!, :only => [:index, :show] - before_filter :authenticate_admin!, :only => [:list, :browse, :create, :update, :destroy] + before_filter :authenticate_admin!, :only => [:list, :browse, :new, :create] - private - - def set_image(prm) - img = nil - if (f = prm[:system_picture][:file]).respond_to?(:read) - if f.size > 1000000 - @system_picture.width = 0 - @system_picture.height = 0 - @system_picture.ext = 'none' - @system_picture.filesize = 1.megabytes - else - img = Magick::Image.from_blob(f.read).shift - @system_picture.width = img.columns - @system_picture.height = img.rows - @system_picture.ext = img.format.downcase - @system_picture.filesize = f.size - end - else - dat = Base64.decode64(prm[:system_picture][:file].to_s.gsub(' ', '+')) #rubyのバグ?+でデコードされるべきキャラがスペースになる - img = Magick::Image.from_blob(dat).shift - @system_picture.width = img.columns - @system_picture.height = img.rows - @system_picture.ext = img.format.downcase - @system_picture.filesize = 1000 - end - img - end - - public - # GET /system_pictures # GET /system_pictures.json def index - @system_pictures = SystemPicture.all + @page = SystemPicture.page params[:page] + @page_size = SystemPicture.page_size params[:page_size] + @system_pictures = SystemPicture.list(@page, @page_size) respond_to do |format| format.html # index.html.erb - format.json { render json: @system_pictures } + format.json { render json: @system_pictures.to_json(SystemPicture.list_json_opt) } end end # GET /system_pictures/1 # GET /system_pictures/1.json def show - @system_picture = SystemPicture.find(params[:id]) - + @system_picture = SystemPicture.show(params[:id], @author) + respond_to do |format| opt = {:type => @system_picture.mime_type, :disposition=>"inline"} format.png { send_data(@system_picture.restore, opt ) } format.gif { send_data(@system_picture.restore, opt ) } format.jpeg { send_data(@system_picture.restore, opt ) } format.html # show.html.erb - format.json { render json: @system_picture} + format.json { render json: @system_picture.to_json(SystemPicture.show_json_opt)} end end @@ -76,67 +49,27 @@ class SystemPicturesController < ApplicationController end end - - # POST /system_pictures - # POST /system_pictures.json - def create - @system_picture = SystemPicture.new - img = set_image params - + def new respond_to do |format| - SystemPicture.transaction do - if @system_picture.save - if @system_picture.store(img) - format.html { redirect_to @system_picture, notice: 'system picture was successfully created.' } - format.json { render json: @system_picture, status: :created, location: @system_picture } - else - format.html { redirect_to @system_picture, notice: 'Failed! system picture was NOT created.' } - format.json { render json: @system_picture.errors, status: :unprocessable_entity } - end - else - format.html { render action: "new" } - format.json { render json: @system_picture.errors, status: :unprocessable_entity } - end - end + format.html # new.html.erb end end - # PUT /system_pictures/1 - # PUT /system_pictures/1.json - def update - @system_picture = SystemPicture.find(params[:id]) - img = set_image params + # POST /system_pictures + # POST /system_pictures.json + def create + @imager = PettanImager.load set_image params[:system_picture][:file] respond_to do |format| - SystemPicture.transaction do - if @system_picture.save - if @system_picture.store(img) - format.html { redirect_to @system_picture, notice: 'System picture was successfully updated.' } - format.json { head :ok } - else - format.html { redirect_to @system_picture, notice: 'Failed! System picture was NOT created.' } - format.json { render json: @system_picture.errors, status: :unprocessable_entity } - end - else - format.html { render action: "edit" } - format.json { render json: @system_picture.errors, status: :unprocessable_entity } - end + @system_picture = SystemPicture.store @imager + if @system_picture + format.html { redirect_to @system_picture, notice: 'system picture was successfully created.' } + format.json { render json: @system_picture.to_json(SystemPicture.show_json_opt), status: :created, location: @system_picture } + else + format.html { render action: "new" } + format.json { render json: {}, status: :unprocessable_entity } end end end - # DELETE /system_pictures/1 - # DELETE /system_pictures/1.json - def destroy - @system_picture = SystemPicture.find(params[:id]) - SystemPicture.transaction do - @system_picture.destroy - - end - - respond_to do |format| - format.html { redirect_to system_pictures_url } - format.json { head :ok } - end - end end diff --git a/app/models/author.rb b/app/models/author.rb index e9fca20b..db3f0956 100644 --- a/app/models/author.rb +++ b/app/models/author.rb @@ -92,11 +92,11 @@ class Author < ActiveRecord::Base end def self.default_comic_page_size - 30 + 25 end def self.comic_max_page_size - 200 + 100 end def self.comic_page_size prm = self.default_comic_page_size @@ -107,11 +107,11 @@ class Author < ActiveRecord::Base end def self.default_story_page_size - 30 + 25 end def self.story_max_page_size - 200 + 100 end def self.story_page_size prm = self.default_story_page_size @@ -122,11 +122,11 @@ class Author < ActiveRecord::Base end def self.default_panel_page_size - 30 + 25 end def self.panel_max_page_size - 200 + 100 end def self.panel_page_size prm = self.default_panel_page_size @@ -137,11 +137,11 @@ class Author < ActiveRecord::Base end def self.default_panel_picture_page_size - 30 + 25 end def self.panel_picture_max_page_size - 200 + 100 end def self.panel_picture_page_size prm = self.default_panel_picture_page_size @@ -152,11 +152,11 @@ class Author < ActiveRecord::Base end def self.default_ground_picture_page_size - 30 + 25 end def self.ground_picture_max_page_size - 200 + 100 end def self.ground_picture_page_size prm = self.default_ground_picture_page_size @@ -167,11 +167,11 @@ class Author < ActiveRecord::Base end def self.default_ground_color_page_size - 30 + 25 end def self.ground_color_max_page_size - 200 + 100 end def self.ground_color_page_size prm = self.default_ground_color_page_size @@ -182,11 +182,11 @@ class Author < ActiveRecord::Base end def self.default_panel_color_page_size - 30 + 25 end def self.panel_color_max_page_size - 200 + 100 end def self.panel_color_page_size prm = self.default_panel_color_page_size diff --git a/app/models/original_picture.rb b/app/models/original_picture.rb index 307418c5..bd776a68 100644 --- a/app/models/original_picture.rb +++ b/app/models/original_picture.rb @@ -28,16 +28,12 @@ class OriginalPicture < ActiveRecord::Base self.own?(ar) end - def dext - self.ext.downcase - end - def filename - "#{self.id}.#{self.dext}" + "#{self.id}.#{self.ext}" end def mime_type - "image/#{self.dext}" + "image/#{self.ext}" end def url @@ -119,28 +115,16 @@ class OriginalPicture < ActiveRecord::Base self.resource_picture.destroy end - def data_to_mgk picture_data - begin - mgk = Magick::Image.from_blob(picture_data).shift - rescue - self.errors.add :base, 'magick failed' + def store(imager) + unless imager + self.errors.add :base, 'illegal picture data' return false end - mgk - end - - def store(picture_data, art) - mgk = data_to_mgk picture_data - return false unless mgk res = false - self.attributes = {:ext => mgk.format.downcase, :width => mgk.columns, :height => mgk.rows, - :filesize => mgk.filesize, :artist_id => art.id - } - self.md5 = Digest::MD5.hexdigest(picture_data) - self.overwrite art + self.attributes = {:ext => imager.ext, :width => imager.width, :height => imager.height, :filesize => imager.filesize, :md5 => imager.md5} OriginalPicture.transaction do if res = self.save - if res = PictureIO.original_picture_io.put(picture_data, self.filename) + if res = PictureIO.original_picture_io.put(imager.binary, self.filename) res = true else self.errors.add :base, 'original picture io does not work' @@ -155,4 +139,10 @@ class OriginalPicture < ActiveRecord::Base PictureIO.original_picture_io.get self.filename, subdir end + def self.export ar + l = LicenseGroup.list + op = OriginalPicture.list ar.id + {:license_groups => l, :original_pictures => op} + end + end diff --git a/app/models/picture.rb b/app/models/picture.rb index 38305a19..9701cf8f 100644 --- a/app/models/picture.rb +++ b/app/models/picture.rb @@ -11,18 +11,33 @@ class Picture < ActiveRecord::Base validates :width, :presence => true, :numericality => true, :natural_number => true validates :height, :presence => true, :numericality => true, :natural_number => true validates :filesize, :presence => true, :numericality => {:greater_than => 0, :less_than_or_equal_to => 2000000}, :natural_number => true - validates :md5, :presence => true, :length => {:maximum => 32} + validates :md5, :presence => true, :length => {:minimum => 32, :maximum => 32} validates :license_id, :presence => true, :numericality => true, :existence => true validates :artist_id, :presence => true, :numericality => true, :existence => true validates :artist_name, :presence => true validates :classname, :presence => true, :length => {:maximum => 50} - def dext - self.ext.downcase + def supply_default + end + + def overwrite rp + attr = {:revision => self.new_revision,:width => rp.width, :height => rp.height, :ext => rp.ext, :filesize => rp.filesize, + :original_picture_id => rp.original_picture_id, :license_id => rp.license_id, :artist_id => rp.artist_id, + :md5 => rp.md5, :artist_name => rp.artist_name, :classname => rp.classname, :credit => rp.credit, :settings => rp.settings + } + self.attributes = attr + end + + def own? author + return false + end + + def visible? author + true end def filename - "#{self.id}.#{self.dext}" + "#{self.id}.#{self.ext}" end def gifname @@ -30,23 +45,15 @@ class Picture < ActiveRecord::Base end def mime_type - "image/#{self.dext}" - end - - def dext - self.ext.downcase + "image/#{self.ext}" end def url '/pictures/' + filename end - def self.list_by_md5 md5, opid - r = Picture.find :all, :conditions => ['pictures.md5 = ? and pictures.original_picture_id <> ?', md5, opid], :order => 'pictures.updated_at desc' - end - - def self.exist_by_md5 md5, opid - Picture.list_by_md5(md5, opid).empty? ? false : true + def new_revision + Picture.maximum(:revision, :conditions => ['original_picture_id = ?', self.original_picture_id]).to_i + 1 end def head? @@ -54,58 +61,36 @@ class Picture < ActiveRecord::Base r ? true : false end - def new_revision - Picture.maximum(:revision, :conditions => ['original_picture_id = ?', self.original_picture_id]).to_i + 1 - end - - def v(rimg) - rimg.flip.to_blob - end - - def h(rimg) - rimg.flop.to_blob - end - - def vh(rimg) - rimg.flip.flop.to_blob + def to_gif? + self.ext == 'png' and self.flag_gif_convert >= 0 end - def to_gif? - self.dext == 'png' and self.flag_gif_convert >= 0 + def subdirs + flag_reverse < 0 ? [''] : ['', 'v', 'h', 'vh'] end - def self.png_to_gif(data) - res = nil - begin - mgk = Magick::Image.from_blob(data).shift - mgk.format = 'gif' - res = mgk - rescue - res = false - end - res + def self.list_by_md5 md5, opid + r = Picture.find :all, :conditions => ['pictures.md5 = ? and pictures.original_picture_id <> ?', md5, opid], :order => 'pictures.updated_at desc' end - def subdirs - flag_reverse < 0 ? [''] : ['', 'v', 'h', 'vh'] + def self.exist_by_md5 md5, opid + Picture.list_by_md5(md5, opid).empty? ? false : true end - def copy_data(rp) - attr = {:width => rp.width, :height => rp.height, :ext => rp.ext, :filesize => rp.filesize, - :original_picture_id => rp.original_picture_id, :license_id => rp.license_id, :artist_id => rp.artist_id, - :md5 => rp.md5, :artist_name => rp.artist_name, :classname => rp.classname, :credit => rp.credit, :settings => rp.settings - } - self.attributes = attr + def self.show rid, au + opt = {} + r = Picture.find(rid, opt) + raise ActiveRecord::Forbidden unless r.visible?(au) + r end - def store(mgk) + def store(imager) res = false - self.revision = self.new_revision if res = self.save - if res = self.store_picture(mgk, self.filename) + if res = self.store_picture(imager, self.filename) if self.to_gif? - if gifmgk = Picture.png_to_gif(mgk.to_blob) - res = self.store_picture(gifmgk, self.gifname) + if gifimager = imager.to_gif + res = self.store_picture(gifimager, self.gifname) else res = false end @@ -115,10 +100,10 @@ class Picture < ActiveRecord::Base res end - def store_picture(mgk, fn) + def store_picture(imager, fn) res = false subdirs.each do |d| - picdata = d.empty? ? mgk.to_blob : self.__send__(d, mgk) + picdata = d.empty? ? imager.binary : imager.__send__(d) res = PictureIO.picture_io.put(picdata, fn, d) break unless res end @@ -129,12 +114,6 @@ class Picture < ActiveRecord::Base PictureIO.picture_io.get self.filename, subdir end - def self.show pid - r = Picture.find(pid) -# raise ActiveRecord::Forbidden unless c.visible?(au) - r - end - def credit_template "#{self.classname.tableize}/attributes/credit" end diff --git a/app/models/resource_picture.rb b/app/models/resource_picture.rb index 9c1514f3..94c43c18 100644 --- a/app/models/resource_picture.rb +++ b/app/models/resource_picture.rb @@ -10,6 +10,7 @@ class ResourcePicture < ActiveRecord::Base validates :width, :presence => true, :numericality => true, :natural_number => true validates :height, :presence => true, :numericality => true, :natural_number => true validates :filesize, :presence => true, :numericality => {:greater_than => 0, :less_than_or_equal_to => 2000000}, :natural_number => true + validates :md5, :presence => true, :length => {:minimum => 32, :maximum => 32} validates :artist_id, :presence => true, :numericality => true, :existence => true validates :license_id, :presence => true, :numericality => true, :existence => true validates :original_picture_id, :presence => true, :numericality => true, :existence => true @@ -27,38 +28,26 @@ class ResourcePicture < ActiveRecord::Base end end - def self.resize(data, dw, dh) - Magick::Image.from_blob(data).shift.resize(dw, dh) + def supply_default end - #サイズの調整(limw,limhに必ず収まるように合わせる) - def self.fix_size_both(limw, limh, w, h) - wr = if w > limw - limw*100/w - else - 100 - end - hr = if h > limh - limh*100/h - else - 100 - end - res = if wr < hr - #幅の方が圧縮率が高い - [w*wr/100, h*wr/100] - else - #高さの方が圧縮率が高い - [w*hr/100, h*hr/100] - end - res + def overwrite op + attr = {:width => op.width, :height => op.height, :ext => op.ext, :filesize => op.filesize, + :original_picture_id => op.id, :artist_id => op.artist_id, :md5 => op.md5 + } + self.attributes = attr + end + + def own? author + return false end - def dext - self.ext.downcase + def visible? author + true end def filename - "#{self.id}.#{self.dext}" + "#{self.id}.#{self.ext}" end def gifname @@ -66,14 +55,18 @@ class ResourcePicture < ActiveRecord::Base end def mime_type - "image/#{self.dext}" + "image/#{self.ext}" end def url subdir = nil '/resource_pictures/' + (subdir.to_s.empty? ? '' : subdir.to_s + '/' ) + filename end - def thumbnail(rimg) + def to_gif? + self.ext == 'png' and self.flag_gif_convert >= 0 + end + + def thumbnail(imager) tw, th = ResourcePicture.fix_size_both(MagicNumber['thumbnail_width'], MagicNumber['thumbnail_height'], rimg.columns, rimg.rows) ResourcePicture.resize(rimg.to_blob, tw, th).to_blob end @@ -83,78 +76,92 @@ class ResourcePicture < ActiveRecord::Base {:src => self.url, :width => tw, :height => th} end - def copy_data(op) - attr = {:width => op.width, :height => op.height, :ext => op.ext, :filesize => op.filesize, - :original_picture_id => op.id, :artist_id => op.artist_id, :md5 => op.md5 - } - self.attributes = attr + def self.default_page_size + 25 end - def data_to_mgk picture_data - begin - mgk = Magick::Image.from_blob(picture_data).shift - rescue - self.errors.add :base, 'magick failed' - return false - end - mgk + def self.max_page_size + 100 end - def op_mgk - d = self.original_picture.restore - return false unless d - self.data_to_mgk d + def self.page prm = nil + page = prm.to_i + page = 1 if page < 1 + page end - def new_picture mgk - pc = Picture.new - pc.copy_data self - pc.store mgk - pc + def self.page_size prm = self.default_page_size + page_size = prm.to_i + page_size = self.max_page_size if page_size > self.max_page_size + page_size = self.default_page_size if page_size < 1 + page_size end + def self.list page = 1, page_size = self.default_page_size + opt = {} + opt.merge!(self.list_opt) + opt.merge!({:limit => page_size, :offset => (page -1) * page_size}) if page_size > 0 + opt.merge!({:order => 'updated_at desc'}) + ResourcePicture.find(:all, opt) + end - def to_gif? - self.dext == 'png' and self.flag_gif_convert >= 0 + def self.list_opt + {:include => {:license => {}, :artist => {}, :picture => {}} } end - def self.png_to_gif(data) - res = nil - begin - mgk = Magick::Image.from_blob(data).shift - mgk.format = 'gif' - res = mgk - rescue - res = false - end - res + def self.list_json_opt + {:include => {:license => {}, :artist => {}, :picture => {}} } + end + + def self.show rid, au + opt = {} + opt.merge!(self.show_opt) + r = ResourcePicture.find(rid, opt) + raise ActiveRecord::Forbidden unless r.visible?(au) + r end - def store + def self.show_opt + {:include => {:license => {}, :artist => {}, :picture => {}} } + end + + def self.show_json_opt + {:include => {:license => {}, :artist => {}, :picture => {}} } + end + + def new_picture imager + pc = Picture.new + pc.supply_default + pc.overwrite self + r = pc.store imager + return pc if r + self.errors.add :base, 'picture does not create' + pc.errors.full_messages.join("\n") + false + end + + def store imager + return false unless imager res = false - self.copy_data self.original_picture - mgk = self.op_mgk - return false unless mgk - OriginalPicture.transaction do - pc = self.new_picture mgk - if res = pc.valid? + self.overwrite self.original_picture + ResourcePicture.transaction do + pc = self.new_picture imager + if pc self.picture_id = pc.id if res = self.save - res = self.store_picture_with_gif(mgk) + res = self.store_picture_with_gif(imager) end else - self.errors.add :base, 'picture does not create' end raise ActiveRecord::Rollback unless res end res end - def store_picture_with_gif(mgk) - if res = self.store_picture(mgk, self.filename) + def store_picture_with_gif(imager) + if res = self.store_picture(imager, self.filename) if self.to_gif? - if gifmgk = ResourcePicture.png_to_gif(mgk.to_blob) - res = self.store_picture(gifmgk, self.gifname) + if gifimager = imager.to_gif + res = self.store_picture(gifimager, self.gifname) else self.errors.add :base, 'picture data can not conv to gif' res = false @@ -166,77 +173,19 @@ class ResourcePicture < ActiveRecord::Base res end - def store_picture(mgk, fn) + def store_picture(imager, fn) res = false - tdata = self.flag_thumbnail >= 0 ? thumbnail(mgk) : mgk.to_blob - fdata = mgk.to_blob - return false unless PictureIO.resource_picture_io.put(tdata, fn) - PictureIO.resource_picture_io.put(fdata, fn, 'full') + thumbnail_imager = self.flag_thumbnail >= 0 ? imager.to_thumbnail : imager + return false unless thumbnail_imager + return false unless PictureIO.resource_picture_io.put(thumbnail_imager.binary, fn) + return false unless PictureIO.resource_picture_io.put(imager.binary, fn, 'full') + true end def restore(subdir = nil) PictureIO.resource_picture_io.get self.filename, subdir end - def self.default_page_size - 25 - end - - def self.max_page_size - 100 - end - - def self.page prm = nil - page = prm.to_i - page = 1 if page < 1 - page - end - - def self.page_size prm = self.default_page_size - page_size = prm.to_i - page_size = self.max_page_size if page_size > self.max_page_size - page_size = self.default_page_size if page_size < 1 - page_size - end - - def self.offset cnt, prm = nil - offset = prm.to_i - offset = cnt - 1 if offset >= cnt - offset = cnt - offset.abs if offset < 0 - offset = 0 if offset < 0 - offset - end - - def self.list opt = {}, page = 1, page_size = self.default_page_size - opt.merge!(self.list_opt) unless opt[:include] - opt.merge!({:order => 'updated_at desc', :limit => page_size, :offset => (page -1) * page_size}) - ResourcePicture.find(:all, opt) - end - - def self.list_opt - {:include => [:license, :artist]} - end - - def self.list_json_opt - {:include => [:license, :artist]} - end - - def self.show rid, opt = {} - r = ResourcePicture.find(rid, :include => self.show_include_opt(opt)) -# raise ActiveRecord::Forbidden unless c.visible?(au) - r - end - - def self.show_include_opt opt = {} - res = [:license, :artist] - res.push(opt[:include]) if opt[:include] - res - end - - def self.show_json_include_opt - {:include => [:license, :artist]} - end - def self.visible_count ResourcePicture.count end diff --git a/app/models/speech_balloon_template.rb b/app/models/speech_balloon_template.rb index 710e99f1..96902193 100644 --- a/app/models/speech_balloon_template.rb +++ b/app/models/speech_balloon_template.rb @@ -1,3 +1,4 @@ +#フキダシテンプレート class SpeechBalloonTemplate < ActiveRecord::Base has_many :speech_balloons @@ -7,92 +8,71 @@ class SpeechBalloonTemplate < ActiveRecord::Base validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0} validates :settings, :presence => true - before_create :supply_t - - def supply_t - m = SpeechBalloonTemplate.maximum(:t) - t = m.blank? ? -1 : m.to_i - self.t = t + 1 + def supply_default end - def pic_rehash hash - res = true - (hash["templates"] || {}).each do |n, v| - d = (v["balloon"] || {})["system_picture"] - next nil if d.blank? - sp = SystemPicture.store Base64.decode64(d.to_s) - unless sp - res = false - break - end - v["balloon"]["system_picture_id"] = sp.id - v["balloon"].delete "system_picture" - end - res + def overwrite + self.t = SpeechBalloonTemplate.count.to_i end - def store hash - res = nil - SpeechBalloonTemplate.transaction do - res = pic_rehash hash - if res - data = {:classname => hash["classname"], :caption => hash["caption"], :settings => hash.to_s} - self.attributes = data - res = self.save - end - raise ActiveRecord::Rollback unless res - end - res + def visible? author + true end - def self.store name, hash - st = SpeechBalloonTemplate.find_by_name name - st = SpeechBalloonTemplate.new(:name => name) unless st - st.store hash - st + def self.list + opt = {} + opt.merge!(self.list_opt) + opt.merge!({:order => 'speech_balloon_templates.t asc'}) + SpeechBalloonTemplate.find(:all, opt) end - def self.list - SpeechBalloonTemplate.find(:all) + def self.list_opt + {} end - def self.show rid - r = SpeechBalloonTemplate.find(rid) - r + def self.list_json_opt + {} end - def self.parse(data) - res = data - begin - res = JSON.parse(data) if data.is_a?(String) - rescue - return false - end + def self.show rid, au + opt = {} + opt.merge!(self.show_opt) + res = SpeechBalloonTemplate.find(rid, opt) + raise ActiveRecord::Forbidden unless res.visible?(au) res end - def self.import(data) - d = SpeechBalloonTemplate.parse(data) - return false unless d - res = [] - SpeechBalloonTemplate.transaction do - d.each do |name, hash| - st = SpeechBalloonTemplate.store name, hash - res.push(st) unless st.valid? - end - raise ActiveRecord::Rollback unless res.empty? - end - res + def self.show_opt + {} end - def self.import_file(filename) - t = nil - begin - t = File.open(filename, 'r').read - rescue - return false + def self.show_json_opt + {} + end + + def self.templates_json_from attr + #templatesのballoonがフキダシ画像を持っているはずなので置換しておく + #templates => {hoge => {balloon => system_picture}} + (attr["templates"] || {}).each do |n, v| + res = replace_system_picture(v["balloon"] || {}) + return nil if res == false #置換なしでnil 失敗でfalse end - SpeechBalloonTemplate.import t + (attr["templates"] || {}).to_json.to_s + end + + def self.store name, attr + #settingsにはHashデータが丸っと文字列化されて入る + attr["settings"] = SpeechBalloonTemplate.templates_json_from(attr) + #templatesデータがあるとフキダシテンプレート生成で邪魔するので削除しておく + attr.delete "templates" + r = SpeechBalloonTemplate.modify_object name, attr + r.overwrite + r.save + r + end + + def self.import filename + SpeechBalloonTemplate.import_file(filename) {|name, attr| SpeechBalloonTemplate.store(name, attr)} end end diff --git a/app/models/story.rb b/app/models/story.rb index fc7e8b71..df03c85f 100644 --- a/app/models/story.rb +++ b/app/models/story.rb @@ -19,7 +19,6 @@ class Story < ActiveRecord::Base end def own? author - return false unless author self.author_id == author.id end @@ -29,6 +28,77 @@ class Story < ActiveRecord::Base res end + def self.default_panel_size + 30 + end + + def self.max_panel_size + 200 + end + + def self.offset cnt, prm = nil + offset = prm.to_i + offset = cnt - 1 if offset >= cnt + offset = cnt - offset.abs if offset < 0 + offset = 0 if offset < 0 + offset + end + + def self.panel_count cnt, prm = self.default_panel_size + count = prm.to_i + count = self.max_panel_size if count > self.max_panel_size + count = self.default_panel_size if count < 1 + count + end + + def self.list comic, author, offset = 0, limit = Story.default_panel_size + opt = {} + opt.merge!(Story.list_opt) + opt.merge!({:offset => offset, :limit => limit}) if limit > 0 + opt.merge!({:conditions => ['stories.comic_id = ? and comics.visible > 0 and panels.publish > 0', comic.id], :order => 'stories.t'}) + Story.find(:all, opt) + end + + def self.list_opt + {:include => { + :author => {}, + :comic => { + :author => {} + }, + :panel => { + :author => {}, + :panel_pictures => {:picture => {:artist => {}, :license => {}}}, + :speech_balloons =>{:balloons => {}, :speeches => {}} + } + }} + end + + def self.list_json_opt + {:include => { + :author => {}, + :comic => { + :author => {} + }, + :panel => { + :author => {}, + :panel_pictures => {:picture => {:artist => {}, :license => {}}}, + :speech_balloons =>{:balloons => {}, :speeches => {}} + } + }} + end + + def self.mylist au, page = 1, page_size = Author.default_story_page_size + opt = {} + opt.merge!(Story.list_opt) + opt.merge!({:limit => page_size, :offset => (page -1) * page_size}) if page_size > 0 + opt.merge!({:conditions => ['stories.author_id = ?', au.id], :order => 'stories.updated_at desc'}) + Story.find(:all, opt) + end + + def to_json_list + self.to_json( :include => {:author => {}, :panels => {:methods => :panel_element}}) + end + def self.new_t comic_id r = Story.max_t(comic_id) r.blank? ? 0 : r.to_i + 1 @@ -128,93 +198,5 @@ class Story < ActiveRecord::Base end end - def self.default_page_size - 25 - end - - def self.max_page_size - 100 - end - - def self.page prm = nil - page = prm.to_i - page = 1 if page < 1 - page - end - - def self.page_size prm = self.default_page_size - page_size = prm.to_i - page_size = self.max_page_size if page_size > self.max_page_size - page_size = self.default_page_size if page_size < 1 - page_size - end - - def self.default_panel_size - 30 - end - - def self.max_panel_size - 200 - end - - def self.offset cnt, prm = nil - offset = prm.to_i - offset = cnt - 1 if offset >= cnt - offset = cnt - offset.abs if offset < 0 - offset = 0 if offset < 0 - offset - end - - def self.panel_count cnt, prm = self.default_panel_size - count = prm.to_i - count = self.max_panel_size if count > self.max_panel_size - count = self.default_panel_size if count < 1 - count - end - - def self.list comic, author, offset = 0, limit = Story.default_panel_size - opt = self.list_opt - opt.merge!({:conditions => ['stories.comic_id = ? and panels.publish > 0', comic.id], :order => 'stories.t', :offset => offset, :limit => limit}) - Story.find(:all, opt) - end - - def self.list_opt - {:include => { - :author => {}, - :comic => { - :author => {} - }, - :panel => { - :author => {}, - :panel_pictures => {:picture => {:artist => {}, :license => {}}}, - :speech_balloons =>{:balloons => {}, :speeches => {}} - } - }} - end - - def self.list_json_opt - {:include => { - :author => {}, - :comic => { - :author => {} - }, - :panel => { - :author => {}, - :panel_pictures => {:picture => {:artist => {}, :license => {}}}, - :speech_balloons =>{:balloons => {}, :speeches => {}} - } - }} - end - - def self.mylist au, opt = {}, page = 1, story_page_size = Author.default_story_page_size - opt.merge!(self.list_opt) unless opt[:include] - opt.merge!({:conditions => ['stories.author_id = ?', au.id], :order => 'stories.updated_at desc', :limit => page_size, :offset => (page -1) * story_page_size}) - Story.find(:all, opt) - end - - def to_json_list - self.to_json( :include => {:author => {}, :panels => {:methods => :panel_element}}) - end - end diff --git a/app/models/system_picture.rb b/app/models/system_picture.rb index ccfe6af2..b0d85324 100644 --- a/app/models/system_picture.rb +++ b/app/models/system_picture.rb @@ -7,7 +7,7 @@ class SystemPicture < ActiveRecord::Base validates :width, :presence => true, :numericality => true, :natural_number => true validates :height, :presence => true, :numericality => true, :natural_number => true validates :filesize, :presence => true, :numericality => {:greater_than => 0, :less_than_or_equal_to => 2000000}, :natural_number => true - validates :md5, :presence => true, :length => {:maximum => 32} + validates :md5, :presence => true, :length => {:minimum => 32, :maximum => 32} before_destroy :destroy_with_file @@ -15,53 +15,108 @@ class SystemPicture < ActiveRecord::Base PictureIO.system_picture_io.delete self.filename end - def dext - self.ext.downcase + def supply_default + end + + def overwrite + end + + def own? ad + true + end + + def visible? ad + true end def filename - "#{self.id}.#{self.dext}" + "#{self.id}.#{self.ext}" end def mime_type - "image/#{self.dext}" + "image/#{self.ext}" end def url '/system_pictures/' + filename end - def data_to_mgk picture_data - begin - mgk = Magick::Image.from_blob(picture_data).shift - rescue - self.errors.add :base, 'magick failed' - return false - end - mgk + def self.default_page_size + 25 end - def store(picture_data) - mgk = data_to_mgk picture_data - return false unless mgk + def self.max_page_size + 100 + end + + def self.page prm = nil + page = prm.to_i + page = 1 if page < 1 + page + end + + def self.page_size prm = self.default_page_size + page_size = prm.to_i + page_size = self.max_page_size if page_size > self.max_page_size + page_size = self.default_page_size if page_size < 1 + page_size + end + + def self.list page = 1, page_size = self.default_page_size + opt = {} + opt.merge!(self.list_opt) + opt.merge!({:limit => page_size, :offset => (page -1) * page_size}) if page_size > 0 + opt.merge!({:order => 'system_pictures.updated_at desc'}) + SystemPicture.find(:all, opt) + end + + def self.list_opt + {} + end + + def self.list_json_opt + {} + end + + def self.show sid, ad + opt = {} + opt.merge!(self.show_opt) + res = SystemPicture.find(sid, opt) + raise ActiveRecord::Forbidden unless res.visible?(ad) + res + end + + def self.show_opt + {} + end + + def self.show_json_opt + {} + end + + def store(imager) + unless imager + self.errors.add :base, 'illegal picture data' + return false + end res = false - self.attributes = {:ext => mgk.format.downcase, :width => mgk.columns, :height => mgk.rows, - :filesize => mgk.filesize - } - self.md5 = Digest::MD5.hexdigest(picture_data) SystemPicture.transaction do if res = self.save - res = PictureIO.system_picture_io.put(picture_data, self.filename) + if res = PictureIO.system_picture_io.put(imager.binary, self.filename) + res = true + else + self.errors.add :base, 'system picture io does not work' + raise ActiveRecord::Rollback + end end end res end - def self.store(picture_data) - md5 = Digest::MD5.hexdigest(picture_data) - sp = SystemPicture.find_by_md5(md5) - sp = SystemPicture.new() unless sp - res = sp.store picture_data + def self.store(imager) + attr = {:ext => imager.ext, :width => imager.width, :height => imager.height, :filesize => imager.filesize, :md5 => imager.md5} + sp = SystemPicture.modify_object(imager.md5, attr, 'md5') + res = sp.store imager res ? sp : nil end diff --git a/app/views/home/ground_color.html.erb b/app/views/home/ground_color.html.erb new file mode 100644 index 00000000..fed3158d --- /dev/null +++ b/app/views/home/ground_color.html.erb @@ -0,0 +1,19 @@ +

Listing Ground Colors

+ + + + + + + + + +<% @ground_colors.each do |gc| %> + + + + + + +<% end -%> +
idpanel_idcolor_idz
<%= gc.id %><%= link_to gc.panel_id, panel_path(gc.panel_id) %><%= link_to gc.color_id, color_path(gc.color_id) %><%= gc.z %>
diff --git a/app/views/home/ground_picture.html.erb b/app/views/home/ground_picture.html.erb new file mode 100644 index 00000000..32f741c6 --- /dev/null +++ b/app/views/home/ground_picture.html.erb @@ -0,0 +1,19 @@ +

Listing Ground Pictures

+ + + + + + + + + +<% @ground_pictures.each do |gp| %> + + + + + + +<% end -%> +
idpanel_idpicture_idz
<%= gp.id %><%= link_to gp.panel_id, panel_path(gp.panel_id) %><%= link_to gp.picture_id, color_path(gp.picture_id) %><%= gp.z %>
diff --git a/app/views/home/panel_color.html.erb b/app/views/home/panel_color.html.erb new file mode 100644 index 00000000..e6a9fa21 --- /dev/null +++ b/app/views/home/panel_color.html.erb @@ -0,0 +1,19 @@ +

Listing Panel Colors

+ + + + + + + + + +<% @panel_colors.each do |pc| %> + + + + + + +<% end -%> +
idpanel_idcodez
<%= pc.id %><%= link_to pc.panel_id, panel_path(pc.panel_id) %><%= pc.code %>*****<%= pc.z %>
diff --git a/app/views/system_pictures/new.html.erb b/app/views/system_pictures/new.html.erb new file mode 100644 index 00000000..d4c99f66 --- /dev/null +++ b/app/views/system_pictures/new.html.erb @@ -0,0 +1,4 @@ +<%= form_tag( {:controller => 'system_pictures',:action => "create"} , { :multipart => true }) do %> + <%= file_field_tag "system_picture[file]" %> + <%= submit_tag 'upload' -%> +<% end -%> diff --git a/config/environment.rb b/config/environment.rb index aa0ff2ef..89544d5b 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -5,3 +5,5 @@ require 'RMagick' # Initialize the rails application Pettanr::Application.initialize! require 'picture_io' +require 'pettan_imager' + diff --git a/lib/pettan_imager.rb b/lib/pettan_imager.rb new file mode 100644 index 00000000..26cbfd49 --- /dev/null +++ b/lib/pettan_imager.rb @@ -0,0 +1,119 @@ +#画像処理 +require 'digest/md5' +require 'RMagick' +class PettanImager + @@tmb_w = 50 + @@tmb_h = 50 + + def self.tmb_w + @@tmb_w + end + + def self.tmb_w=(v) + @@tmb_w = v + end + + def self.tmb_h + @@tmb_h + end + + def self.tmb_h=(v) + @@tmb_h = v + end + + def initialize bindata + @binary = bindata + @lib =Magick::Image.from_blob(@binary).shift + end + + def self.load bindata + r = nil + begin + r = PettanImager.new bindata + rescue + r = false + end + r + end + + def binary + @binary + end + + def lib + @lib + end + + def width + @lib.columns + end + + def height + @lib.rows + end + + def filesize + @lib.filesize + end + + def ext + @lib.format.downcase + end + + def md5 + Digest::MD5.hexdigest(@lib.to_blob) + end + + def v + @lib.flip.to_blob + end + + def h + @lib.flop.to_blob + end + + def vh + @lib.flip.flop.to_blob + end + + def to_gif + @lib.format = 'gif' + PettanImager.load @lib.to_blob + end + + def to_thumbnail + PettanImager.load(@lib.resize(*thumbnail_size).to_blob) + end + + def thumbnail_size + PettanImager.fix_size_both PettanImager.tmb_w, PettanImager.tmb_h, self.width, self.height + end + + #ただサイズ計算したいとき + def self.thumbnail_size w, h + PettanImager.fix_size_both PettanImager.tmb_w, PettanImager.tmb_h, w, h + end + + #サイズの調整(limw,limhに必ず収まるように合わせる) + def self.fix_size_both(limw, limh, w, h) + wr = if w > limw + limw*100/w + else + 100 + end + hr = if h > limh + limh*100/h + else + 100 + end + res = if wr < hr + #幅の方が圧縮率が高い + [w*wr/100, h*wr/100] + else + #高さの方が圧縮率が高い + [w*hr/100, h*hr/100] + end + res + end + +end diff --git a/lib/test/pettan_imager_spec.rb b/lib/test/pettan_imager_spec.rb new file mode 100644 index 00000000..8afa1647 --- /dev/null +++ b/lib/test/pettan_imager_spec.rb @@ -0,0 +1,338 @@ +# -*- encoding: utf-8 -*- +#画像処理 +require 'pettan_imager' + +describe PettanImager do + before do + @f = File.dirname(__FILE__) + '/test.png' + @d = File.open(@f, 'rb').read + end + + describe 'クラス変数に於いて' do + context 'サムネイル幅のとき' do + it 'デフォルトは50' do + r = PettanImager.tmb_w + r.should eq 50 + end + it 'セットできる' do + PettanImager.tmb_w = 64 + r = PettanImager.tmb_w + r.should eq 64 + end + end + context 'サムネイル高さのとき' do + it 'デフォルトは50' do + r = PettanImager.tmb_h + r.should eq 50 + end + it 'セットできる' do + PettanImager.tmb_h = 64 + r = PettanImager.tmb_h + r.should eq 64 + end + end + end + + describe 'バイナリデータの読み込みに於いて' do + context 'つつがなく終わるとき' do + it 'インスタンス化している' do + r = PettanImager.load @d + r.is_a?(PettanImager).should be_true + end + it 'バイナリデータを控えている' do + r = PettanImager.load @d + r.binary.should eq @d + end + it 'ライブラリを準備している' do + r = PettanImager.load @d + r.lib.should_not be_nil + end + end + context 'ロードに失敗したとき' do + it 'falseを返す' do + r = PettanImager.load 'error data' + r.should be_false + end + end + end + describe 'バイナリデータの出力に於いて' do + before do + @i = PettanImager.load @d + end + context 'つつがなく終わるとき' do + it '控えバイナリデータを返す' do + r = @i.binary + r.should eq @d + end + end + end + describe '幅の算出に於いて' do + before do + @i = PettanImager.load @d + Magick::Image.any_instance.stub(:width).with(any_args).and_return(100) + end + context 'つつがなく終わるとき' do + it 'ライブラリに幅の取得を依頼している' do + Magick::Image.any_instance.should_receive(:columns).with(any_args).exactly(1) + r = @i.width + end + it 'データを返す' do + r = @i.width + r.should eq 100 + end + end + end + describe '高さの算出に於いて' do + before do + @i = PettanImager.load @d + Magick::Image.any_instance.stub(:height).with(any_args).and_return(200) + end + context 'つつがなく終わるとき' do + it 'ライブラリに高さの取得を依頼している' do + Magick::Image.any_instance.should_receive(:rows).with(any_args).exactly(1) + r = @i.height + end + it 'データを返す' do + r = @i.height + r.should eq 50 + end + end + end + describe 'ファイルサイズの算出に於いて' do + before do + @i = PettanImager.load @d + Magick::Image.any_instance.stub(:filesize).with(any_args).and_return(1500) + end + context 'つつがなく終わるとき' do + it 'ライブラリにファイルサイズの取得を依頼している' do + Magick::Image.any_instance.should_receive(:filesize).with(any_args).exactly(1) + r = @i.filesize + end + it 'データを返す' do + r = @i.filesize + r.should eq 1500 + end + end + end + describe '画像フォーマットの算出に於いて' do + before do + @i = PettanImager.load @d + Magick::Image.any_instance.stub(:format).with(any_args).and_return('PNG') + end + context 'つつがなく終わるとき' do + it 'ライブラリに画像フォーマットの取得を依頼している' do + Magick::Image.any_instance.should_receive(:format).with(any_args).exactly(1) + r = @i.ext + end + it 'データを小文字で返す' do + r = @i.ext + r.should eq 'png' + end + end + end + describe 'MD5の算出に於いて' do + before do + @i = PettanImager.load @d + end + context 'つつがなく終わるとき' do + it 'バイナリデータをDigest::MD5に変換依頼している' do + Digest::MD5.stub(:hexdigest).with(any_args).and_return('a'*32) + Digest::MD5.should_receive(:hexdigest).with(any_args).exactly(1) + r = @i.md5 + end + it 'MD5を返す' do + r = @i.md5 + r.size.should eq 32 + end + end + end + describe '左右反転に於いて' do + before do + @i = PettanImager.load @d + @mflip = Magick::Image.from_blob(@d).shift + Magick::Image.any_instance.stub(:flip).with(any_args).and_return(@mflip) + end + context 'つつがなく終わるとき' do + it 'ライブラリに左右反転を依頼している' do + Magick::Image.any_instance.should_receive(:flip).with(any_args).exactly(1) + r = @i.v + end + it 'ライブラリに反転したバイナリデータの取得を依頼している' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@d) + Magick::Image.any_instance.should_receive(:to_blob).with(any_args).exactly(1) + r = @i.v + end + it 'バイナリデータを返す' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@mflip.to_blob) + r = @i.v + r.should eq @mflip.to_blob + end + end + end + describe '上下反転に於いて' do + before do + @i = PettanImager.load @d + @mflop = Magick::Image.from_blob(@d).shift + Magick::Image.any_instance.stub(:flop).with(any_args).and_return(@mflop) + end + context 'つつがなく終わるとき' do + it 'ライブラリに上下反転を依頼している' do + Magick::Image.any_instance.should_receive(:flop).with(any_args).exactly(1) + r = @i.h + end + it 'ライブラリに反転したバイナリデータの取得を依頼している' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@d) + Magick::Image.any_instance.should_receive(:to_blob).with(any_args).exactly(1) + r = @i.h + end + it 'バイナリデータを返す' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@mflop.to_blob) + r = @i.h + r.should eq @mflop.to_blob + end + end + end + describe '上下左右反転に於いて' do + before do + @i = PettanImager.load @d + @mflip = Magick::Image.from_blob(@d).shift + @mflop = Magick::Image.from_blob(@d).shift + Magick::Image.any_instance.stub(:flip).with(any_args).and_return(@mflip) + Magick::Image.any_instance.stub(:flop).with(any_args).and_return(@mflop) + end + context 'つつがなく終わるとき' do + it 'ライブラリに上下左右反転を依頼している' do + Magick::Image.any_instance.should_receive(:flip).with(any_args).exactly(1) + Magick::Image.any_instance.should_receive(:flop).with(any_args).exactly(1) + r = @i.vh + end + it 'ライブラリに反転したバイナリデータの取得を依頼している' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@d) + Magick::Image.any_instance.should_receive(:to_blob).with(any_args).exactly(1) + r = @i.vh + end + it 'バイナリデータを返す' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@mflop.to_blob) + r = @i.vh + r.should eq @mflop.to_blob + end + end + end + describe 'Gif変換に於いて' do + before do + @i = PettanImager.load @d + end + context 'つつがなく終わるとき' do + it 'ライブラリにGif変換を依頼している' do + Magick::Image.any_instance.should_receive(:format=).with(any_args).exactly(1) + r = @i.to_gif + end + it 'ライブラリにGif変換したバイナリデータの取得を依頼している' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@d) + Magick::Image.any_instance.should_receive(:to_blob).with(any_args).exactly(1) + r = @i.to_gif + end + it 'バイナリデータから画像処理オブジェクトを興している' do + PettanImager.stub(:load).with(any_args).and_return(PettanImager.load(@d)) + PettanImager.should_receive(:load).with(any_args).exactly(1) + r = @i.to_gif + end + it '画像処理オブジェクトを返す' do + r = @i.to_gif + r.is_a?(PettanImager).should be_true + end + end + end + describe 'サムネイル化に於いて' do + before do + @i = PettanImager.load @d + @rs = Magick::Image.from_blob(@d).shift + Magick::Image.any_instance.stub(:resize).with(any_args).and_return(@rs) + end + context 'つつがなく終わるとき' do + it 'ライブラリにサムネイル化を依頼している' do + Magick::Image.any_instance.should_receive(:resize).with(any_args).exactly(1) + r = @i.to_thumbnail + end + it 'ライブラリにサムネイル化したバイナリデータの取得を依頼している' do + Magick::Image.any_instance.stub(:to_blob).with(any_args).and_return(@d) + Magick::Image.any_instance.should_receive(:to_blob).with(any_args).exactly(1) + r = @i.to_thumbnail + end + it 'バイナリデータから画像処理オブジェクトを興す' do + PettanImager.stub(:load).with(any_args).and_return(PettanImager.load(@d)) + PettanImager.should_receive(:load).with(any_args).exactly(1) + r = @i.to_thumbnail + end + it '画像処理オブジェクトを返す' do + r = @i.to_thumbnail + r.is_a?(PettanImager).should be_true + end + end + end + describe 'サムネイルサイズの算出に於いて' do + before do + @i = PettanImager.load @d + end + context 'つつがなく終わるとき' do + it '自身に幅の取得を依頼している' do + PettanImager.any_instance.stub(:width).with(any_args).and_return(64) + PettanImager.any_instance.should_receive(:width).with(any_args).exactly(1) + r = @i.to_thumbnail + end + it '自身に高さの取得を依頼している' do + PettanImager.any_instance.stub(:height).with(any_args).and_return(64) + PettanImager.any_instance.should_receive(:height).with(any_args).exactly(1) + r = @i.to_thumbnail + end + it '幅と高さの配列で返す' do + r = @i.thumbnail_size + r.is_a?(Array).should be_true + r.size.should eq 2 + end + end + end + + describe 'サムネイルサイズの調整に於いて' do + before do + PettanImager.tmb_w=100 + PettanImager.tmb_h=200 + end + context 'サムネイルサイズより小さいとき' do + it 'そのまま返す' do + r = PettanImager.thumbnail_size 100, 200 + r.should eq [100, 200] + end + it 'そのまま返す' do + r = PettanImager.thumbnail_size 99, 199 + r.should eq [99, 199] + end + end + context '幅が200%のとき' do + it '幅がサイズに収まるように50%にして返す' do + r = PettanImager.thumbnail_size 200, 200 + r.should eq [100, 100] + end + end + context '高さが200%のとき' do + it '高さがサイズに収まるように50%にして返す' do + r = PettanImager.thumbnail_size 100, 400 + r.should eq [50, 200] + end + end + context '幅が400%と高さが200%のとき' do + it '幅がサイズに収まるように25%にして返す' do + r = PettanImager.thumbnail_size 400, 400 + r.should eq [100, 100] + end + end + context '幅が200%と高さが400%のとき' do + it '高さがサイズに収まるように25%にして返す' do + r = PettanImager.thumbnail_size 200, 800 + r.should eq [50, 200] + end + end + end + +end + diff --git a/lib/test/test.png b/lib/test/test.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef05400ad8a9ccb6edd92a2ee9b554fe78cff9c GIT binary patch literal 643 zcmV-}0(||6P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0vJg|K~!i%?VC-K zf-n?>xew)zW4Lk84P1Ex-Ldl$y7Lb1EN?Q$m;pl)^72Cx^1!KT%Z()mOqKP1{@^VL*f9-QUU2|cf^Pr|uy}G7%7U_>tj!w? zYzP~|hOl9R3jhnScp~G!D(kwh=3o1Jnak^1@mss&EBb)1Q!P)hzB~#IFS9y)J1ogp z06TPL%$^C$obdfHPO-ffnxS$0bY;<57Si}yu*^|cwl!{-9WnNBg%dYTznyWG9A4eX zW0slX3a~sETs5cL=#Iy+aV22CK^Clu5|zY?IFTKe0-@tssZ0n&Y0A(`uMSBw&4!Ba zXLs^j%Tj_HmU4u#B*}rB*W*i;Bv=%^$?mIRsZ%#WD7g*pu+oZFgcMk|kR8&_MaHZw zlIvD7i70VrmU3kRESHYlHqR*&%&_b=&g3=CUAw!D5{riwH=F2YOMx=OddkcSG@Y)c zOO?82u^0L1H_?1mURJocVNEPXPgJgVg2nV(A|+9Uy-C0*xNJT}uy1T2a ztb>DtqNAglnworkeD(G9$;!%-l9P*zjQaZe@bK{c{rxm8EM#J0baQh&H#Ti-YX$=X zBpMeiB_dHyO{HGaxJ!KL{676(BTG z5i1i!6E7cvAT1&hH8m0r7a)NgEdqN}6Cejd03H+s9UwD56ebQ4C~FJ@Fbfbu1q}-T z2$vHo3lhgaDm^eYkSY!{5f+d_0v>@L5h@TQBqQo0={+hE;ywo@RSP}{5dfPeJ{>g= z9x_Nc(1F4LAC|=F^RU8!xCK9GtXQDI2R#HU+z@EsLqiM;8PXJR;e%BQ0ssh<=)tlj z%MvIFD7X;F!M7+CQpCHEM$(V}2|Nl^;78z~gdYZcr0C(}#SZ{JAi@YHzz2^XAVTt5 zf#K%?786bY@}M9c1ea*hLQrP{fsYLIpi~e5iGlJCDPY@0U_;HYo4@3_- zIQTIlh6kDreq?ANK%p>E2nwru8RPvy!lGcp zN>BJ8fP29M4kCE@h@8QN5Y|_J#0bQ~1b~%jVKTrFV?lz?pi2PY0Vwj5yAB#;=z!=z z1_dyp&iJH2hL6FPD}k69bwY;^0%-WSltIIgObu*?kP0K5VBmp0tfikI7Nme3XaEF| z!EjGZkirKZEP%)l1o(yjf(i$?fI$k-VJ;jnLk)EF@WBN=1Q1ySDGV_| z1Rr#OPyzq|fPw)77=S{71n@9OAPAfQ9cUz|Fky~rR5=7wEI{zUCR#io!vRYM5&;RN zu|z@&9dIy$l~u|x;hIVez(JVu5O7wR+ud^$n^@>~nG!Y7S(1ZgvIKyB5b=pcRTsR1 z!~|{yvH}Z(U_fS}C7hrNoQhIW0hqxoF~cAqq%a5zGdx)u2@LqqXs1-X5LFW-3Btew zfCw^Xp$U!v<_WM)0cIRa46uSA9K?Z|ARgGs>j?b#7c3O78OH=if_xx^Zi6WBU}+GP zAkK!1H8i=L5_5i?L43yhM1s)W{L{)-xAj5xySTF-=g%Y5GtM)SC zUJOkv7>Kp5ExBu<;bOFB!bVh;oDwqlC`bZCd^(5+CEQsi2^jdWBF0GYBLEYv3i3!1 z{0suaw-9bd2g^s?6>1U_#1lxOM07le2A7sOLaQ6|OoV>qB2mJU4WvZC)t(9Mg9R@T zT$)Ti9OZNoDHpKBvVx{9LDHZRU@FmL3(>-19DAI$pa}G!Dq15b5O&-`$S}7BQ5#Y7 z-D#VEvr8i=*)-210OG>GNr;SW2bgEBx!r-puy{-J`T+9S0&u{AYD?5MNCXp5;QH&Y z%b-fX33$!__uN0TJU|C4@WzBa$P$}`fPyTO-3csc<#elqF+l;Pg6yS4QiJ5ZcWAA` z&9dJMTzo_VOE$m6C&-?p)(D?)I>ZYJwD11=@W(H|{4cn&2ACbRKq3Jsq)|l7%<s13+9rfJgvZ)qoG!4U%Z2ywy`8gURDKmZ16zzC73 zVsu1!KmoY)1QY~706qkOJ#29tcbV{rV7!~yP~fATT>%9pP*n*?U=J1u4|qfjqa5k9 zGXenrq6Qe00sv0n5)zz%BrNz@0G9N{IT}(@BQ$_pJ|H|PRDb|{3=Op0;sJ7%j*vw> zWEfX4LJFXU0~(sb1HzS#6kK3Vz8S&{j)h50YVveLfPgqwKm!O+u?Y_#zziC2fH_$p zE|4mQ9{ z5imdl543;>G!TsjG(Z9r@xTLF-~tl}Km;8i=M8>fDnS(!oMDVi2*~+?6R3j(0#LvL zQo*@FbN~S@kbnXNkPeuXKm+9TKu-MmO@KzwKLg!B4My;!5{v)Igc%q>4mQ9699Ru&Q1uK6f<#pS Wq$8?W1;7jPsRIfiK&TH50suRyWZBOE literal 0 HcmV?d00001 diff --git a/spec/controllers/ground_pictures_controller_spec.rb b/spec/controllers/ground_pictures_controller_spec.rb index e150928a..9f1c7982 100644 --- a/spec/controllers/ground_pictures_controller_spec.rb +++ b/spec/controllers/ground_pictures_controller_spec.rb @@ -73,6 +73,10 @@ describe GroundPicturesController do get :index, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it 'コマの画像背景モデルにjson一覧出力オプションを問い合わせている' do + GroundPicture.should_receive(:list_json_opt).exactly(1) + get :index, :format => :json + end it 'データがリスト構造になっている' do get :index, :format => :json json = JSON.parse response.body diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index 94eb8015..2809d269 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -11,6 +11,7 @@ describe HomeController do @user = FactoryGirl.create( :user_yas) @author = @user.author @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @color = FactoryGirl.create :color @op = FactoryGirl.create :original_picture, :artist_id => @artist.id @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id @@ -73,6 +74,10 @@ describe HomeController do get :comic, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it 'コミックモデルにjson一覧出力オプションを問い合わせている' do + Comic.should_receive(:list_json_opt).exactly(1) + get :comic, :format => :json + end it 'データがリスト構造になっている' do get :comic, :format => :json json = JSON.parse response.body @@ -82,6 +87,7 @@ describe HomeController do get :comic, :format => :json json = JSON.parse response.body json.first.has_key?("title").should be_true + json.first.has_key?("visible").should be_true end end end @@ -168,6 +174,10 @@ describe HomeController do get :panel, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it 'コマモデルにjson一覧出力オプションを問い合わせている' do + Panel.should_receive(:list_json_opt).exactly(1) + get :panel, :format => :json + end it 'データがリスト構造になっている' do get :panel, :format => :json json = JSON.parse response.body @@ -264,6 +274,10 @@ describe HomeController do get :panel_picture, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it 'コマ絵モデルにjson一覧出力オプションを問い合わせている' do + PanelPicture.should_receive(:list_json_opt).exactly(1) + get :panel_picture, :format => :json + end it 'データがリスト構造になっている' do get :panel_picture, :format => :json json = JSON.parse response.body @@ -273,6 +287,8 @@ describe HomeController do get :panel_picture, :format => :json json = JSON.parse response.body json.first.has_key?("link").should be_true + json.first.has_key?("x").should be_true + json.first.has_key?("y").should be_true end end end @@ -306,7 +322,7 @@ describe HomeController do describe '自分の原画一覧表示に於いて' do before do sign_in @user - OriginalPicture.stub(:list).and_return([@op, @op, @op]) + OriginalPicture.stub(:mylist).and_return([@op, @op, @op]) end context 'パラメータpageについて' do it '@pageに値が入る' do @@ -341,7 +357,7 @@ describe HomeController do end it '原画モデルに一覧を問い合わせている' do #原画は他人が使えないので「自分の」リストはない - OriginalPicture.should_receive(:list).exactly(1) + OriginalPicture.should_receive(:mylist).exactly(1) get :picture end it '@original_picturesにリストを取得している' do @@ -359,6 +375,10 @@ describe HomeController do get :picture, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it '原画モデルにjson一覧出力オプションを問い合わせている' do + OriginalPicture.should_receive(:list_json_opt).exactly(1) + get :picture, :format => :json + end it 'データがリスト構造になっている' do get :picture, :format => :json json = JSON.parse response.body @@ -368,6 +388,9 @@ describe HomeController do get :picture, :format => :json json = JSON.parse response.body json.first.has_key?("ext").should be_true + json.first.has_key?("md5").should be_true + json.first.has_key?("artist_id").should be_true + json.first.has_key?("width").should be_true end end end @@ -420,4 +443,307 @@ describe HomeController do end end + describe '自分のコマの色背景一覧表示に於いて' do + before do + @pc = FactoryGirl.create :panel_color, :panel_id => @panel.id + sign_in @user + PanelColor.stub(:mylist).and_return([@pc, @pc, @pc]) + end + context 'パラメータpageについて' do + it '@pageに値が入る' do + get :panel_color, :page => 5 + assigns(:page).should eq 5 + end + it '省略されると@pageに1値が入る' do + get :panel_color + assigns(:page).should eq 1 + end + it '与えられたpage_sizeがセットされている' do + get :panel_color, :page_size => 15 + assigns(:page_size).should eq 15 + end + it '省略されると@page_sizeにデフォルト値が入る' do + get :panel_color + assigns(:page_size).should eq PanelColor.default_page_size + end + it '最大を超えると@page_sizeにデフォルト最大値が入る' do + get :panel_color, :page_size => 1500 + assigns(:page_size).should eq PanelColor.max_page_size + end + it '不正な値が入ると@page_sizeにデフォルト最大値が入る' do + get :panel_color, :page_size => 0 + assigns(:page_size).should eq PanelColor.default_page_size + end + end + context 'つつがなく終わるとき' do + it 'ステータスコード200 OKを返す' do + get :panel_color + response.should be_success + end + it 'コマの色背景モデルに一覧を問い合わせている' do + PanelColor.should_receive(:mylist).exactly(1) + get :panel_color + end + it '@panel_colorsにリストを取得している' do + get :panel_color + assigns(:panel_colors).should have_at_least(3).items + end + context 'html形式' do + it 'panel_colorテンプレートを描画する' do + get :panel_color + response.should render_template("panel_color") + end + end + context 'json形式' do + it 'jsonデータを返す' do + get :panel_color, :format => :json + lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) + end + it 'コマの色背景モデルにjson一覧出力オプションを問い合わせている' do + PanelColor.should_receive(:list_json_opt).exactly(1) + get :panel_color, :format => :json + end + it 'データがリスト構造になっている' do + get :panel_color, :format => :json + json = JSON.parse response.body + json.should have_at_least(3).items + end + it 'リストの先頭くらいはコマの色背景っぽいものであって欲しい' do + get :panel_color, :format => :json + json = JSON.parse response.body + json.first.has_key?("panel_id").should be_true + json.first.has_key?("code").should be_true + json.first.has_key?("z").should be_true + end + end + end + context '作家権限がないとき' do + before do + sign_out @user + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :panel_color + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + get :panel_color + response.should redirect_to '/users/sign_in' + end + end + context 'json形式' do + it 'ステータスコード401 Unauthorizedを返す' do + get :panel_color, :format => :json + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + get :panel_color, :format => :json + response.message.should match(/Unauthorized/) + end + end + end + end + + describe '自分のコマの画像背景一覧表示に於いて' do + before do + @gp = FactoryGirl.create :ground_picture, :panel_id => @panel.id, :picture_id => @p.id + sign_in @user + GroundPicture.stub(:mylist).and_return([@gp, @gp, @gp]) + end + context 'パラメータpageについて' do + it '@pageに値が入る' do + get :ground_picture, :page => 5 + assigns(:page).should eq 5 + end + it '省略されると@pageに1値が入る' do + get :ground_picture + assigns(:page).should eq 1 + end + it '与えられたpage_sizeがセットされている' do + get :ground_picture, :page_size => 15 + assigns(:page_size).should eq 15 + end + it '省略されると@page_sizeにデフォルト値が入る' do + get :ground_picture + assigns(:page_size).should eq GroundPicture.default_page_size + end + it '最大を超えると@page_sizeにデフォルト最大値が入る' do + get :ground_picture, :page_size => 1500 + assigns(:page_size).should eq GroundPicture.max_page_size + end + it '不正な値が入ると@page_sizeにデフォルト最大値が入る' do + get :ground_picture, :page_size => 0 + assigns(:page_size).should eq GroundPicture.default_page_size + end + end + context 'つつがなく終わるとき' do + it 'ステータスコード200 OKを返す' do + get :ground_picture + response.should be_success + end + it 'コマの画像背景モデルに一覧を問い合わせている' do + GroundPicture.should_receive(:mylist).exactly(1) + get :ground_picture + end + it '@ground_picturesにリストを取得している' do + get :ground_picture + assigns(:ground_pictures).should have_at_least(3).items + end + context 'html形式' do + it 'ground_pictureテンプレートを描画する' do + get :ground_picture + response.should render_template("ground_picture") + end + end + context 'json形式' do + it 'jsonデータを返す' do + get :ground_picture, :format => :json + lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) + end + it 'コマの画像背景モデルにjson一覧出力オプションを問い合わせている' do + GroundPicture.should_receive(:list_json_opt).exactly(1) + get :ground_picture, :format => :json + end + it 'データがリスト構造になっている' do + get :ground_picture, :format => :json + json = JSON.parse response.body + json.should have_at_least(3).items + end + it 'リストの先頭くらいはコマの画像背景っぽいものであって欲しい' do + get :ground_picture, :format => :json + json = JSON.parse response.body + json.first.has_key?("panel_id").should be_true + json.first.has_key?("picture_id").should be_true + json.first.has_key?("z").should be_true + end + end + end + context '作家権限がないとき' do + before do + sign_out @user + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :ground_picture + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + get :ground_picture + response.should redirect_to '/users/sign_in' + end + end + context 'json形式' do + it 'ステータスコード401 Unauthorizedを返す' do + get :ground_picture, :format => :json + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + get :ground_picture, :format => :json + response.message.should match(/Unauthorized/) + end + end + end + end + + describe '自分の間接背景一覧表示に於いて' do + before do + @gc = FactoryGirl.create :ground_color + sign_in @user + GroundColor.stub(:mylist).and_return([@gc, @gc, @gc]) + end + context 'パラメータpageについて' do + it '@pageに値が入る' do + get :ground_color, :page => 5 + assigns(:page).should eq 5 + end + it '省略されると@pageに1値が入る' do + get :ground_color + assigns(:page).should eq 1 + end + it '与えられたpage_sizeがセットされている' do + get :ground_color, :page_size => 15 + assigns(:page_size).should eq 15 + end + it '省略されると@page_sizeにデフォルト値が入る' do + get :ground_color + assigns(:page_size).should eq GroundColor.default_page_size + end + it '最大を超えると@page_sizeにデフォルト最大値が入る' do + get :ground_color, :page_size => 1500 + assigns(:page_size).should eq GroundColor.max_page_size + end + it '不正な値が入ると@page_sizeにデフォルト最大値が入る' do + get :ground_color, :page_size => 0 + assigns(:page_size).should eq GroundColor.default_page_size + end + end + context 'つつがなく終わるとき' do + it 'ステータスコード200 OKを返す' do + get :ground_color + response.should be_success + end + it '間接背景モデルに一覧を問い合わせている' do + GroundColor.should_receive(:mylist).exactly(1) + get :ground_color + end + it '@ground_colorsにリストを取得している' do + get :ground_color + assigns(:ground_colors).should have_at_least(3).items + end + context 'html形式' do + it 'ground_colorテンプレートを描画する' do + get :ground_color + response.should render_template("ground_color") + end + end + context 'json形式' do + it 'jsonデータを返す' do + get :ground_color, :format => :json + lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) + end + it '間接背景モデルにjson一覧出力オプションを問い合わせている' do + GroundColor.should_receive(:list_json_opt).exactly(1) + get :ground_color, :format => :json + end + it 'データがリスト構造になっている' do + get :ground_color, :format => :json + json = JSON.parse response.body + json.should have_at_least(3).items + end + it 'リストの先頭くらいは間接背景っぽいものであって欲しい' do + get :ground_color, :format => :json + json = JSON.parse response.body + json.first.has_key?("panel_id").should be_true + json.first.has_key?("color_id").should be_true + json.first.has_key?("z").should be_true + end + end + end + context '作家権限がないとき' do + before do + sign_out @user + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :ground_color + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + get :ground_color + response.should redirect_to '/users/sign_in' + end + end + context 'json形式' do + it 'ステータスコード401 Unauthorizedを返す' do + get :ground_color, :format => :json + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + get :ground_color, :format => :json + response.message.should match(/Unauthorized/) + end + end + end + end + end diff --git a/spec/controllers/original_pictures_controller_spec.rb b/spec/controllers/original_pictures_controller_spec.rb index 5bc98f5d..16543a0a 100644 --- a/spec/controllers/original_pictures_controller_spec.rb +++ b/spec/controllers/original_pictures_controller_spec.rb @@ -167,16 +167,27 @@ describe OriginalPicturesController do get :show, :id => @pic.id, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it '原画モデルにjson単体出力オプションを問い合わせている' do + OriginalPicture.should_receive(:show_json_opt).exactly(1) + get :show, :id => @pic.id, :format => :json + end it 'データがアレになっている' do get :show, :id => @pic.id, :format => :json json = JSON.parse response.body json["ext"].should match(/png/) + json["md5"].should be_true + json["artist_id"].should be_true + json["width"].should be_true end end #画像送信では、send_dataにスタブをおいてテストしたいが、ここに噛ませると #renderが働かず、エラーとなってしまう。そこで、原画のファイル取得部分に #スタブをおいてsend_dataがデータを返す体裁でテストする。 context 'png形式' do + before do + OriginalPicture.any_instance.stub(:mime_type).and_return('image/png') + OriginalPicture.any_instance.stub(:restore).and_return('aaa') + end it '画像モデルに画像データを問い合わせる' do OriginalPicture.any_instance.should_receive(:restore).exactly(1) get :show, :id => @pic.id, :format => :png @@ -186,12 +197,15 @@ describe OriginalPicturesController do get :show, :id => @pic.id, :format => :png end it '画像を送信する' do - OriginalPicture.any_instance.stub(:restore).and_return('aaa') get :show, :id => @pic.id, :format => :png response.body.should eq 'aaa' end end context 'gif形式' do + before do + OriginalPicture.any_instance.stub(:mime_type).and_return('image/gif') + OriginalPicture.any_instance.stub(:restore).and_return('bbb') + end it '画像モデルに画像データを問い合わせる' do OriginalPicture.any_instance.should_receive(:restore).exactly(1) get :show, :id => @pic.id, :format => :gif @@ -201,12 +215,15 @@ describe OriginalPicturesController do get :show, :id => @pic.id, :format => :gif end it '画像を送信する' do - OriginalPicture.any_instance.stub(:restore).and_return('bbb') get :show, :id => @pic.id, :format => :gif response.body.should eq 'bbb' end end context 'jpeg形式' do + before do + OriginalPicture.any_instance.stub(:mime_type).and_return('image/jpeg') + OriginalPicture.any_instance.stub(:restore).and_return('ccc') + end it '画像モデルに画像データを問い合わせる' do OriginalPicture.any_instance.should_receive(:restore).exactly(1) get :show, :id => @pic.id, :format => :jpeg @@ -216,7 +233,6 @@ describe OriginalPicturesController do get :show, :id => @pic.id, :format => :jpeg end it '画像を送信する' do - OriginalPicture.any_instance.stub(:restore).and_return('ccc') get :show, :id => @pic.id, :format => :jpeg response.body.should eq 'ccc' end @@ -415,10 +431,6 @@ describe OriginalPicturesController do sign_in @user end context 'つつがなく終わるとき' do - it 'ステータスコード200 OKを返す' do - get :new - response.should be_success - end it '@original_pictureに新規データを用意している' do get :new assigns(:original_picture).should be_a_new(OriginalPicture) @@ -428,18 +440,25 @@ describe OriginalPicturesController do get :new end context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :new + response.should be_success + end it 'ページテンプレートnewを描画する' do get :new response.should render_template("new") end end context 'js形式' do + it 'ステータスコード200 OKを返す' do + get :new, :format => :js + response.should be_success + end it '部分テンプレートnew.jsを描画する' do get :new, :format => :js response.should render_template("new") end end - end context 'json形式' do it 'jsonデータを返す' do get :new, :format => :json @@ -450,6 +469,7 @@ describe OriginalPicturesController do get :new, :format => :json end end + end context '作家権限がないとき' do before do sign_out @user @@ -557,10 +577,17 @@ describe OriginalPicturesController do post :create, :original_picture => FactoryGirl.attributes_for(:original_picture), :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it '原画モデルにjson単体出力オプションを問い合わせている' do + OriginalPicture.should_receive(:show_json_opt).exactly(1) + post :create, :original_picture => FactoryGirl.attributes_for(:original_picture), :format => :json + end it 'データがアレになっている' do post :create, :original_picture => FactoryGirl.attributes_for(:original_picture, :ext => 'jpeg'), :format => :json json = JSON.parse response.body json["ext"].should match(/jpeg/) + json["md5"].should be_true + json["artist_id"].should be_true + json["width"].should be_true end end end @@ -615,7 +642,7 @@ describe OriginalPicturesController do before do OriginalPicture.any_instance.stub(:store).and_return(false) end - it "未保存のコミックを保持している" do + it "未保存の原画を保持している" do post :create, :original_picture => FactoryGirl.attributes_for(:original_picture) assigns(:original_picture).should be_a_new(OriginalPicture) end diff --git a/spec/controllers/panels_controller_spec.rb b/spec/controllers/panels_controller_spec.rb index 485b04d6..db00bf23 100644 --- a/spec/controllers/panels_controller_spec.rb +++ b/spec/controllers/panels_controller_spec.rb @@ -67,6 +67,10 @@ describe PanelsController do get :index, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it 'コマモデルにjson一覧出力オプションを問い合わせている' do + Panel.should_receive(:list_json_opt).exactly(1) + get :index, :format => :json + end it 'データがリスト構造になっている' do get :index, :format => :json json = JSON.parse response.body diff --git a/spec/controllers/pictures_controller_spec.rb b/spec/controllers/pictures_controller_spec.rb index 6fdc26ec..03cd7de2 100644 --- a/spec/controllers/pictures_controller_spec.rb +++ b/spec/controllers/pictures_controller_spec.rb @@ -18,7 +18,7 @@ describe PicturesController do before do @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id sign_in @user - Picture.stub(:show).and_return(@p) + Picture.stub(:show).with(@p.id.to_s, @author).and_return(@p) end context 'つつがなく終わるとき as json' do it 'ステータスコード200 OKを返す' do @@ -47,6 +47,7 @@ describe PicturesController do it 'データがアレになっている' do get :show, :id => @p.id, :format => :json json = JSON.parse response.body + json["revision"].should_not be_nil json["ext"].should match(/png/) end end @@ -159,7 +160,7 @@ describe PicturesController do before do @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id sign_in @user - Picture.stub(:show).and_return(@p) + Picture.stub(:show).with(@p.id.to_s, @author).and_return(@p) end context 'つつがなく終わるとき' do it 'ステータスコード200 OKを返す' do @@ -188,6 +189,7 @@ describe PicturesController do it 'データがアレになっている' do get :credit, :id => @p.id, :format => :json json = JSON.parse response.body + json["revision"].should_not be_nil json["ext"].should match(/png/) end end diff --git a/spec/controllers/resource_pictures_controller_spec.rb b/spec/controllers/resource_pictures_controller_spec.rb index 033cb5cf..d46e807e 100644 --- a/spec/controllers/resource_pictures_controller_spec.rb +++ b/spec/controllers/resource_pictures_controller_spec.rb @@ -48,10 +48,6 @@ describe ResourcePicturesController do end end context 'つつがなく終わるとき' do - it 'ステータスコード200 OKを返す' do - get :index - response.should be_success - end it '素材モデルに一覧を問い合わせている' do ResourcePicture.should_receive(:list).exactly(1) get :index @@ -61,16 +57,28 @@ describe ResourcePicturesController do assigns(:resource_pictures).should have_at_least(3).items end context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :index + response.should be_success + end it 'indexテンプレートを描画する' do get :index response.should render_template("index") end end context 'json形式' do + it 'ステータスコード200 OKを返す' do + get :index, :format => :json + response.should be_success + end it 'jsonデータを返す' do get :index, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it '素材モデルにjson一覧出力オプションを問い合わせている' do + ResourcePicture.should_receive(:list_json_opt).exactly(1) + get :index, :format => :json + end it 'データがリスト構造になっている' do get :index, :format => :json json = JSON.parse response.body @@ -80,6 +88,8 @@ describe ResourcePicturesController do get :index, :format => :json json = JSON.parse response.body json.first.has_key?("ext").should be_true + json.first.has_key?("md5").should be_true + json.first.has_key?("picture_id").should be_true end end end @@ -113,73 +123,104 @@ describe ResourcePicturesController do describe '単体表示に於いて' do before do @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id - @pic = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id sign_in @user - ResourcePicture.stub(:show).and_return(@pic) + ResourcePicture.stub(:show).with(@rp.id.to_s, @author).and_return(@rp) end context 'つつがなく終わるとき' do - it 'ステータスコード200 OKを返す' do - get :show, :id => @pic.id - response.should be_success - end it '素材モデルに単体取得を問い合わせている' do ResourcePicture.should_receive(:show).exactly(1) - get :show + get :show, :id => @rp.id end it '@resource_pictureにアレを取得している' do - get :show, :id => @pic.id - assigns(:resource_picture).id.should eq(@pic.id) + get :show, :id => @rp.id + assigns(:resource_picture).id.should eq(@rp.id) end context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :show, :id => @rp.id + response.should be_success + end it 'showテンプレートを描画する' do - get :show, :id => @pic.id + get :show, :id => @rp.id response.should render_template("show") end end context 'json形式' do + it 'ステータスコード200 OKを返す' do + get :show, :id => @rp.id, :format => :json + response.should be_success + end it 'jsonデータを返す' do - get :show, :id => @pic.id, :format => :json + get :show, :id => @rp.id, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it '素材モデルにjson単体出力オプションを問い合わせている' do + ResourcePicture.should_receive(:show_json_opt).exactly(1) + get :show, :id => @rp.id, :format => :json + end it 'データがアレになっている' do - get :show, :id => @pic.id, :format => :json + get :show, :id => @rp.id, :format => :json json = JSON.parse response.body json["ext"].should match(/png/) + json["md5"].should_not be_nil + json["picture_id"].should_not be_nil end end #画像送信では、send_dataにスタブをおいてテストしたいが、ここに噛ませると #renderが働かず、エラーとなってしまう。そこで、素材のファイル取得部分に #スタブをおいてsend_dataがデータを返す体裁でテストする。 context 'png形式' do + before do + ResourcePicture.any_instance.stub(:mime_type).and_return('image/png') + ResourcePicture.any_instance.stub(:restore).and_return('aaa') + end it '画像モデルに画像データを問い合わせる' do ResourcePicture.any_instance.should_receive(:restore).exactly(1) - get :show, :id => @pic.id, :format => :png + get :show, :id => @rp.id, :format => :png + end + it '画像モデルにMimeTypeを問い合わせる' do + ResourcePicture.any_instance.should_receive(:mime_type).exactly(1) + get :show, :id => @rp.id, :format => :png end it '画像を送信する' do - ResourcePicture.any_instance.stub(:restore).and_return('aaa') - get :show, :id => @pic.id, :format => :png + get :show, :id => @rp.id, :format => :png response.body.should eq 'aaa' end end context 'gif形式' do + before do + ResourcePicture.any_instance.stub(:mime_type).and_return('image/gif') + ResourcePicture.any_instance.stub(:restore).and_return('bbb') + end it '画像モデルに画像データを問い合わせる' do ResourcePicture.any_instance.should_receive(:restore).exactly(1) - get :show, :id => @pic.id, :format => :gif + get :show, :id => @rp.id, :format => :gif + end + it '画像モデルにMimeTypeを問い合わせる' do + ResourcePicture.any_instance.should_receive(:mime_type).exactly(1) + get :show, :id => @rp.id, :format => :png end it '画像を送信する' do - ResourcePicture.any_instance.stub(:restore).and_return('bbb') - get :show, :id => @pic.id, :format => :gif + get :show, :id => @rp.id, :format => :gif response.body.should eq 'bbb' end end context 'jpeg形式' do + before do + ResourcePicture.any_instance.stub(:mime_type).and_return('image/jpeg') + ResourcePicture.any_instance.stub(:restore).and_return('ccc') + end it '画像モデルに画像データを問い合わせる' do ResourcePicture.any_instance.should_receive(:restore).exactly(1) - get :show, :id => @pic.id, :format => :jpeg + get :show, :id => @rp.id, :format => :jpeg + end + it '画像モデルにMimeTypeを問い合わせる' do + ResourcePicture.any_instance.should_receive(:mime_type).exactly(1) + get :show, :id => @rp.id, :format => :png end it '画像を送信する' do - ResourcePicture.any_instance.stub(:restore).and_return('ccc') - get :show, :id => @pic.id, :format => :jpeg + get :show, :id => @rp.id, :format => :jpeg response.body.should eq 'ccc' end end @@ -190,21 +231,21 @@ describe ResourcePicturesController do end context 'html形式' do it 'ステータスコード302 Foundを返す' do - get :show, :id => @pic.id + get :show, :id => @rp.id response.status.should eq 302 end it 'サインインページへ遷移する' do - get :show, :id => @pic.id + get :show, :id => @rp.id response.body.should redirect_to '/users/sign_in' end end context 'json形式' do it 'ステータスコード401 Unauthorizedを返す' do - get :show, :id => @pic.id, :format => :json + get :show, :id => @rp.id, :format => :json response.status.should eq 401 end it '応答メッセージにUnauthorizedを返す' do - get :show, :id => @pic.id, :format => :json + get :show, :id => @rp.id, :format => :json response.message.should match(/Unauthorized/) end end @@ -231,20 +272,20 @@ describe ResourcePicturesController do end context '他人の素材を見ようとしたとき' do before do - ResourcePicture.stub(:show).and_return(@pic) + ResourcePicture.stub(:show).and_return(@rp) ResourcePicture.any_instance.stub(:own?).with(any_args()).and_return(false) end context 'html形式' do it '例外403 forbiddenを返す' do lambda{ - get :show, :id => @pic.id + get :show, :id => @rp.id }.should raise_error(ActiveRecord::Forbidden) end end context 'json形式' do it '例外403 forbiddenを返す' do lambda{ - get :show, :id => @pic.id, :format => :json + get :show, :id => @rp.id, :format => :json }.should raise_error(ActiveRecord::Forbidden) end end @@ -279,38 +320,48 @@ describe ResourcePicturesController do describe 'クレジット表示に於いて' do before do @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id - @pic = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id sign_in @user - ResourcePicture.stub(:show).and_return(@pic) + ResourcePicture.stub(:show).with(@rp.id.to_s, @author).and_return(@rp) end context 'つつがなく終わるとき' do - it 'ステータスコード200 OKを返す' do - get :credit, :id => @pic.id - response.should be_success - end it '素材モデルに単体取得を問い合わせている' do ResourcePicture.should_receive(:show).exactly(1) - get :credit, :id => @pic.id + get :credit, :id => @rp.id end it '@resource_pictureにアレを取得している' do - get :credit, :id => @pic.id - assigns(:resource_picture).id.should eq(@pic.id) + get :credit, :id => @rp.id + assigns(:resource_picture).id.should eq(@rp.id) end context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :credit, :id => @rp.id + response.should be_success + end it 'creditテンプレートを描画する' do - get :credit, :id => @pic.id + get :credit, :id => @rp.id response.should render_template("credit") end end context 'json形式' do + it 'ステータスコード200 OKを返す' do + get :credit, :id => @rp.id, :format => :json + response.should be_success + end it 'jsonデータを返す' do - get :credit, :id => @pic.id, :format => :json + get :credit, :id => @rp.id, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it '素材モデルにjson単体出力オプションを問い合わせている' do + ResourcePicture.should_receive(:show_json_opt).exactly(1) + get :credit, :id => @rp.id, :format => :json + end it 'データがアレになっている' do - get :credit, :id => @pic.id, :format => :json + get :credit, :id => @rp.id, :format => :json json = JSON.parse response.body json["ext"].should match(/png/) + json["md5"].should_not be_nil + json["picture_id"].should_not be_nil end end end @@ -320,21 +371,21 @@ describe ResourcePicturesController do end context 'html形式' do it 'ステータスコード302 Foundを返す' do - get :credit, :id => @pic.id + get :credit, :id => @rp.id response.status.should eq 302 end it 'サインインページへ遷移する' do - get :credit, :id => @pic.id + get :credit, :id => @rp.id response.body.should redirect_to '/users/sign_in' end end context 'json形式' do it 'ステータスコード401 Unauthorizedを返す' do - get :credit, :id => @pic.id, :format => :json + get :credit, :id => @rp.id, :format => :json response.status.should eq 401 end it '応答メッセージにUnauthorizedを返す' do - get :credit, :id => @pic.id, :format => :json + get :credit, :id => @rp.id, :format => :json response.message.should match(/Unauthorized/) end end @@ -360,5 +411,465 @@ describe ResourcePicturesController do end end =end - end + end + + #原画にライセンスを与えるため際の確認フォーム + describe '新規作成フォーム表示に於いて' do + before do + sign_in @user + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @attr = {:original_picture_id => @op.id, :original_picture_license_group => {:original_picture_id => @op.id, :license_group_id => @lg.id}, + :resource_picture => {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => @artist.name, :credit => '{}', :settings => '{}' }} + @newop = FactoryGirl.create :original_picture, :artist_id => @artist.id + @newattr = {:original_picture_id => @newop.id, :original_picture_license_group => {:original_picture_id => @newop.id, :license_group_id => @lg.id}, + :resource_picture => {:original_picture_id => @newop.id, :license_id => @license.id, :artist_name => @artist.name, :credit => '{}', :settings => '{}' }} + @imager = ImagerTest.load("abc\ndef\nghi") + end + context '事前チェックしておく' do + before do + OriginalPicture.stub(:edit).with(@op.id.to_s, @artist).and_return(@op) + OriginalPicture.stub(:edit).with(@newop.id.to_s, @artist).and_return(@newop) + OriginalPicture.any_instance.stub(:restore).with(any_args()).and_return(@imager.binary) + PettanImager.stub(:load).with(@imager.binary).and_return(@imager) + LicenseGroup.stub(:show).with(@lg.id).and_return(@lg) + ResourcePicture.any_instance.stub(:overwrite).with(@op).and_return(true) + ResourcePicture.any_instance.stub(:overwrite).with(@newop).and_return(true) + end + it '原画モデルに編集取得を依頼してしている' do + OriginalPicture.should_receive(:edit).with(@op.id.to_s, @artist).exactly(1) + get :new, @attr + end + it '原画モデルに画像データを問い合わせている' do + OriginalPicture.any_instance.should_receive(:restore).with(any_args()).exactly(1) + get :new, @attr + end + it '画像ライブラリをロードしている' do + PettanImager.should_receive(:load).with(any_args()).exactly(1) + get :new, @attr + end + it 'ライセンスグループモデルに単体取得を依頼している' do + LicenseGroup.should_receive(:show).with(any_args()).exactly(1) + get :new, @attr + end + context 'ライセンスを与えようとしている原画が素材を作成してないとき' do + it '素材モデルにデフォルト値補充を依頼している' do + ResourcePicture.any_instance.should_receive(:supply_default).with(any_args()).exactly(1) + get :new, @newattr + end + end + context 'ライセンスを与えようとしている原画が既に素材を作成しているとき' do + it '素材モデルにデフォルト値補充を依頼してない' do + ResourcePicture.any_instance.should_not_receive(:supply_default).with(any_args()) + get :new, @attr + end + end + it '素材モデルに上書き補充を依頼している' do + ResourcePicture.any_instance.should_receive(:overwrite).with(@op).exactly(1) + get :new, @attr + end + end + context 'つつがなく終わるとき' do + before do + OriginalPicture.stub(:edit).with(@op.id.to_s, @artist).and_return(@op) + OriginalPicture.stub(:edit).with(@newop.id.to_s, @artist).and_return(@newop) + OriginalPicture.any_instance.stub(:restore).with(any_args()).and_return(@imager.binary) + PettanImager.stub(:load).with(@imager.binary).and_return(@imager) + LicenseGroup.stub(:show).with(@lg.id).and_return(@lg) + ResourcePicture.any_instance.stub(:overwrite).with(@op).and_return(true) + ResourcePicture.any_instance.stub(:overwrite).with(@newop).and_return(true) + end + it '@original_pictureに原画を取得している' do + get :new, @attr + assigns(:original_picture).should eq @op + end + it '@imagerに画像ライブラリをロードしている' do + get :new, @attr + assigns(:imager).should eq @imager + end + it '@original_picture_license_groupに新規原画ライセンスグループデータを用意している' do + get :new, @attr + assigns(:original_picture_license_group).should be_a_new(OriginalPictureLicenseGroup) + end + it '@license_groupにライセンスグループを取得している' do + get :new, @attr + assigns(:license_group).should eq @lg + end + context 'ライセンスを与えようとしている原画が素材を作成してないとき' do + it '@resource_pictureに新規素材データを用意している' do + get :new, @newattr + assigns(:resource_picture).should be_a_new(ResourcePicture) + end + end + context 'ライセンスを与えようとしている原画が既に素材を作成しているとき' do + it '@resource_pictureに素材データを用意している' do + get :new, @attr + assigns(:resource_picture).is_a?(ResourcePicture).should be_true + assigns(:resource_picture).should_not be_a_new(ResourcePicture) + end + end + context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :new, @attr + response.should be_success + end + it 'ページテンプレートnewを描画する' do + get :new, @attr + response.should render_template("new") + end + end + context 'js形式' do + before do + @attr.merge!({:format => :js}) + end + it 'ステータスコード200 OKを返す' do + get :new, @attr + response.should be_success + end + it '部分テンプレートnew.jsを描画する' do + get :new, @attr + response.should render_template("new") + end + end + end + context '作家権限がないとき' do + before do + sign_out @user + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :new, @attr + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + get :new, @attr + response.body.should redirect_to '/users/sign_in' + end + end + context 'js形式' do + before do + @attr.merge!({:format => :js}) + end + it 'ステータスコード401 Unauthorizedを返す' do + get :new, @attr + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + get :new, @attr + response.message.should match(/Unauthorized/) + end + end + end + context '作家が絵師でないとき' do + before do + Author.any_instance.stub(:artist?).and_return(false) + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :new, @attr + response.status.should eq 302 + end + it '絵師登録ページへ遷移する' do + get :new, @attr + response.should redirect_to new_artist_path + end + end + context 'js形式' do + before do + @attr.merge!({:format => :js}) + end + it 'ステータスコード200 Okを返す' do + get :new, @attr + response.status.should eq 200 + end + it '絵師登録部分テンプレートartists/new.jsを描画する' do + get :new, @attr + response.should render_template("artists/new") + end + end + end + context '対象ライセンスグループがないとき' do + before do + @attr = {:original_picture_id => @op.id, :original_picture_license_group => {:original_picture_id => @op.id, :license_group_id => 0}, + :resource_picture => {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => @artist.name, :credit => '{}', :settings => '{}' }} + end + context 'html形式' do + it '例外404 not_foundを返す' do + lambda{ + get :new, @attr + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + context 'json形式' do + before do + @attr.merge!({:format => :js}) + end + it '例外404 not_foundを返す' do + lambda{ + get :new, @attr + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + end + + describe '新規作成に於いて' do + before do + sign_in @user + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @attr = {:original_picture_id => @op.id, :original_picture_license_group => {:original_picture_id => @op.id, :license_group_id => @lg.id}, + :resource_picture => {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => @artist.name, :credit => '{}', :settings => '{"new":0}' }} + @newop = FactoryGirl.create :original_picture, :artist_id => @artist.id + @newattr = {:original_picture_id => @newop.id, :original_picture_license_group => {:original_picture_id => @newop.id, :license_group_id => @lg.id}, + :resource_picture => {:original_picture_id => @newop.id, :license_id => @license.id, :artist_name => @artist.name, :credit => '{}', :settings => '{"new":1}' }} + @imager = ImagerTest.load("abc\ndef\nghi") + end + context '事前チェックしておく' do + before do + OriginalPicture.stub(:edit).with(@op.id.to_s, @artist).and_return(@op) + OriginalPicture.stub(:edit).with(@newop.id.to_s, @artist).and_return(@newop) + OriginalPicture.any_instance.stub(:restore).with(any_args()).and_return(@imager.binary) + PettanImager.stub(:load).with(@imager.binary).and_return(@imager) + LicenseGroup.stub(:show).with(@lg.id).and_return(@lg) + ResourcePicture.any_instance.stub(:overwrite).with(@op).and_return(true) + ResourcePicture.any_instance.stub(:overwrite).with(@newop).and_return(true) + ResourcePicture.any_instance.stub(:store).with(@imager).and_return(true) + end + it '原画モデルに編集取得を依頼してしている' do + OriginalPicture.should_receive(:edit).with(@op.id.to_s, @artist).exactly(1) + post :create, @attr + end + it '原画モデルに画像データを問い合わせている' do + OriginalPicture.any_instance.should_receive(:restore).with(any_args()).exactly(1) + post :create, @attr + end + it '画像ライブラリをロードしている' do + PettanImager.should_receive(:load).with(any_args()).exactly(1) + post :create, @attr + end + it 'ライセンスグループモデルに単体取得を依頼している' do + LicenseGroup.should_receive(:show).with(any_args()).exactly(1) + post :create, @attr + end + context 'ライセンスを与えようとしている原画が素材を作成してないとき' do + it '素材モデルにデフォルト値補充を依頼している' do + ResourcePicture.any_instance.should_receive(:supply_default).with(any_args()).exactly(1) + post :create, @newattr + end + end + context 'ライセンスを与えようとしている原画が既に素材を作成しているとき' do + it '素材モデルにデフォルト値補充を依頼してない' do + ResourcePicture.any_instance.should_not_receive(:supply_default).with(any_args()) + post :create, @attr + end + end + it '素材モデルに上書き補充を依頼している' do + ResourcePicture.any_instance.should_receive(:overwrite).with(@op).exactly(1) + post :create, @attr + end + it '素材モデルに保存を依頼している' do + ResourcePicture.any_instance.should_receive(:store).with(@imager).exactly(1) + post :create, @attr + end + end + context 'つつがなく終わるとき[ライセンスを与えようとしている原画が素材を作成してない]' do + before do + OriginalPicture.stub(:edit).with(@newop.id.to_s, @artist).and_return(@newop) + OriginalPicture.any_instance.stub(:restore).with(any_args()).and_return(@imager.binary) + PettanImager.stub(:load).with(@imager.binary).and_return(@imager) + LicenseGroup.stub(:show).with(@lg.id).and_return(@lg) + ResourcePicture.any_instance.stub(:store).with(@imager).and_return { + assigns(:resource_picture).attributes = @newattr[:resource_picture] + assigns(:resource_picture).overwrite @newop + assigns(:resource_picture).picture_id = @p.id + assigns(:resource_picture).save! + true + } + end + it '@original_pictureに原画を取得している' do + post :create, @newattr + assigns(:original_picture).should eq @newop + end + it '@imagerに画像ライブラリをロードしている' do + post :create, @newattr + assigns(:imager).should eq @imager + end + it '@original_picture_license_groupに新規原画ライセンスグループデータを用意している' do + post :create, @newattr + assigns(:original_picture_license_group).should be_a_new(OriginalPictureLicenseGroup) + end + it '@license_groupにライセンスグループを取得している' do + post :create, @newattr + assigns(:license_group).should eq @lg + end + it '素材データにPOSTデータの素材情報を適用している' do + post :create, @newattr + assigns(:resource_picture).license_id.should eq @license.id + assigns(:resource_picture).artist_name.should eq @artist.name + assigns(:resource_picture).credit.should eq '{}' + assigns(:resource_picture).settings.should eq '{"new":1}' + end + it "作成された素材がDBにある" do + lambda{ + post :create, @newattr + }.should change(ResourcePicture, :count) + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + post :create, @newattr + response.status.should eq 302 + end + it '作成された素材の表示ページへ遷移する' do + post :create, @newattr + response.should redirect_to(ResourcePicture.last) + end + end + context 'json形式' do + before do + @newattr.merge!({:format => :json}) + end + it 'ステータスコード200 OKを返す' do + post :create, @newattr + response.should be_success + end + it '作成された素材をjsonデータで返す' do + post :create, @newattr + lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) + end + it '素材モデルにjson単体出力オプションを問い合わせている' do + ResourcePicture.should_receive(:show_json_opt).exactly(1) + post :create, @newattr + end + it 'データがアレになっている' do + post :create, @newattr + json = JSON.parse response.body + json["ext"].should match(/png/) + json["md5"].should_not be_nil + json["picture_id"].should_not be_nil + end + end + end + context 'つつがなく終わるとき[ライセンスを与えようとしている原画が既に素材を作成している]' do + before do + OriginalPicture.stub(:edit).with(@op.id.to_s, @artist).and_return(@op) + OriginalPicture.any_instance.stub(:restore).with(any_args()).and_return(@imager.binary) + PettanImager.stub(:load).with(@imager.binary).and_return(@imager) + LicenseGroup.stub(:show).with(@lg.id).and_return(@lg) + ResourcePicture.any_instance.stub(:store).with(@imager).and_return { + assigns(:resource_picture).attributes = @attr[:resource_picture] + assigns(:resource_picture).overwrite @op + assigns(:resource_picture).save! + true + } + end + it '@original_pictureに原画を取得している' do + post :create, @attr + assigns(:original_picture).should eq @op + end + it '素材データにPOSTデータの素材情報を適用している' do + post :create, @attr + assigns(:resource_picture).license_id.should eq @license.id + assigns(:resource_picture).artist_name.should eq @artist.name + assigns(:resource_picture).credit.should eq '{}' + assigns(:resource_picture).settings.should eq '{"new":0}' + end + it "素材が更新される" do + post :create, @attr + r = ResourcePicture.find(@rp.id) + r.settings.should eq '{"new":0}' + end + it "上書きなので件数は変化しない" do + lambda{ + post :create, @attr + }.should_not change(ResourcePicture, :count) + end + end + context '作家権限がないとき' do + before do + sign_out @user + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + post :create, @attr + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + post :create, @attr + response.body.should redirect_to '/users/sign_in' + end + end + context 'json形式' do + before do + @attr.merge!({:format => :js}) + end + it 'ステータスコード401 Unauthorizedを返す' do + post :create, @attr + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + post :create, @attr + response.message.should match(/Unauthorized/) + end + end + end + context '作家が絵師でないとき' do + before do + Author.any_instance.stub(:artist?).and_return(false) + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + post :create, @attr + response.status.should eq 302 + end + it '絵師登録ページへ遷移する' do + post :create, @attr + response.should redirect_to new_artist_path + end + end + context 'json形式' do + before do + @attr.merge!({:format => :json}) + end + it '例外403 forbiddenを返す' do + lambda{ + post :create, @attr + }.should raise_error(ActiveRecord::Forbidden) + end + end + end + context '検証、保存に失敗した' do + before do + ResourcePicture.any_instance.stub(:store).and_return(false) + end + it "未保存の素材を保持している" do + post :create, @newattr + assigns(:resource_picture).should be_a_new(ResourcePicture) + end + context 'html形式' do + it 'ステータスコード200 OKを返す' do + post :create, @newattr + response.status.should eq 200 + end + it '新規ページを描画する' do + post :create, @newattr + response.should render_template("new") + end + end + context 'json形式' do + before do + @newattr.merge!({:format => :json}) + end + it 'ステータスコード422 unprocessable_entity を返す' do + post :create, @newattr + response.status.should eq 422 + end + it '応答メッセージUnprocessable Entityを返す' do + post :create, @newattr + response.message.should match(/Unprocessable/) + end + end + end + end + end diff --git a/spec/controllers/speech_balloon_templates_controller_spec.rb b/spec/controllers/speech_balloon_templates_controller_spec.rb index f2e941ff..597376f2 100644 --- a/spec/controllers/speech_balloon_templates_controller_spec.rb +++ b/spec/controllers/speech_balloon_templates_controller_spec.rb @@ -19,10 +19,6 @@ describe SpeechBalloonTemplatesController do SpeechBalloonTemplate.stub(:list).and_return([@sbt, @sbt, @sbt]) end context 'つつがなく終わるとき' do - it 'ステータスコード200 OKを返す' do - get :index - response.should be_success - end it 'フキダシテンプレートモデルに一覧を問い合わせている' do SpeechBalloonTemplate.should_receive(:list).exactly(1) get :index @@ -32,16 +28,28 @@ describe SpeechBalloonTemplatesController do assigns(:speech_balloon_templates).should have_at_least(3).items end context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :index + response.should be_success + end it 'indexテンプレートを描画する' do get :index response.should render_template("index") end end context 'json形式' do + it 'ステータスコード200 OKを返す' do + get :index, :format => :json + response.should be_success + end it 'jsonデータを返す' do get :index, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it 'フキダシテンプレートモデルにjson一覧出力オプションを問い合わせている' do + SpeechBalloonTemplate.should_receive(:list_json_opt).exactly(1) + get :index, :format => :json + end it 'データがリスト構造になっている' do get :index, :format => :json json = JSON.parse response.body @@ -50,7 +58,9 @@ describe SpeechBalloonTemplatesController do it 'リストの先頭くらいはフキダシテンプレートっぽいものであって欲しい' do get :index, :format => :json json = JSON.parse response.body + json.first.has_key?("name").should be_true json.first.has_key?("classname").should be_true + json.first.has_key?("t").should be_true end end end @@ -84,32 +94,40 @@ describe SpeechBalloonTemplatesController do describe '単体表示に於いて' do before do sign_in @user - SpeechBalloonTemplate.stub(:show).and_return(@sbt) + SpeechBalloonTemplate.stub(:show).with(@sbt.id.to_s, @author).and_return(@sbt) end context 'つつがなく終わるとき' do - it 'ステータスコード200 OKを返す' do - get :show, :id => @sbt.id - response.should be_success - end it 'フキダシテンプレートモデルに単体取得を問い合わせている' do SpeechBalloonTemplate.should_receive(:show).exactly(1) get :show end it '@speech_balloon_templateにアレを取得している' do get :show, :id => @sbt.id - assigns(:speech_balloon_template).id.should eq(@sbt.id) + assigns(:speech_balloon_template).should eq(@sbt) end context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :show, :id => @sbt.id + response.should be_success + end it 'showテンプレートを描画する' do get :show, :id => @sbt.id response.should render_template("show") end end context 'json形式' do + it 'ステータスコード200 OKを返す' do + get :show, :id => @sbt.id, :format => :json + response.should be_success + end it 'jsonデータを返す' do get :show, :id => @sbt.id, :format => :json lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) end + it 'フキダシテンプレートモデルにjson単体出力オプションを問い合わせている' do + SpeechBalloonTemplate.should_receive(:show_json_opt).exactly(1) + get :show, :id => @sbt.id, :format => :json + end it 'データがアレになっている' do get :show, :id => @sbt.id, :format => :json json = JSON.parse response.body diff --git a/spec/controllers/system_controller_spec.rb b/spec/controllers/system_controller_spec.rb index 8d221210..e7486944 100644 --- a/spec/controllers/system_controller_spec.rb +++ b/spec/controllers/system_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' describe SystemController do - end diff --git a/spec/controllers/system_pictures_controller_spec.rb b/spec/controllers/system_pictures_controller_spec.rb index 713534b4..e8cc0130 100644 --- a/spec/controllers/system_pictures_controller_spec.rb +++ b/spec/controllers/system_pictures_controller_spec.rb @@ -3,4 +3,437 @@ require 'spec_helper' describe SystemPicturesController do + before do + @admin = FactoryGirl.create :admin + @user = FactoryGirl.create( :user_yas) + @author = @user.author + @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @sp = FactoryGirl.create :system_picture + @lg = FactoryGirl.create :license_group + @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + end + + describe '一覧表示に於いて' do + before do + sign_in @user + sign_in @admin + SystemPicture.stub(:list).and_return([@sp, @sp, @sp]) + end + context 'パラメータpageについて' do + it '@pageに値が入る' do + get :index, :page => 5 + assigns(:page).should eq 5 + end + it '省略されると@pageに1値が入る' do + get :index + assigns(:page).should eq 1 + end + it '与えられたpage_sizeがセットされている' do + get :index, :page_size => 15 + assigns(:page_size).should eq 15 + end + it '省略されると@page_sizeにデフォルト値が入る' do + get :index + assigns(:page_size).should eq SystemPicture.default_page_size + end + it '最大を超えると@page_sizeにデフォルト最大値が入る' do + get :index, :page_size => 1500 + assigns(:page_size).should eq SystemPicture.max_page_size + end + it '不正な値が入ると@page_sizeにデフォルト最大値が入る' do + get :index, :page_size => 0 + assigns(:page_size).should eq SystemPicture.default_page_size + end + end + context 'つつがなく終わるとき' do + it 'システム画像モデルに一覧を問い合わせている' do + SystemPicture.should_receive(:list).exactly(1) + get :index + end + it '@system_picturesにリストを取得している' do + get :index + assigns(:system_pictures).should have_at_least(3).items + end + context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :index + response.should be_success + end + it 'indexテンプレートを描画する' do + get :index + response.should render_template("index") + end + end + context 'json形式' do + it 'ステータスコード200 OKを返す' do + get :index, :format => :json + response.should be_success + end + it 'jsonデータを返す' do + get :index, :format => :json + lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) + end + it 'システム画像モデルにjson一覧出力オプションを問い合わせている' do + SystemPicture.should_receive(:list_json_opt).exactly(1) + get :index, :format => :json + end + it 'データがリスト構造になっている' do + get :index, :format => :json + json = JSON.parse response.body + json.should have_at_least(3).items + end + it 'リストの先頭くらいはシステム画像っぽいものであって欲しい' do + get :index, :format => :json + json = JSON.parse response.body + json.first.has_key?("ext").should be_true + json.first.has_key?("md5").should be_true + end + end + end + context '作家権限がないとき' do + before do + sign_out @user + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :index + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + get :index + response.should redirect_to '/users/sign_in' + end + end + context 'json形式' do + it 'ステータスコード401 Unauthorizedを返す' do + get :index, :format => :json + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + get :index, :format => :json + response.message.should match(/Unauthorized/) + end + end + end + end + + describe '単体表示に於いて' do + before do + sign_in @user + SystemPicture.stub(:show).and_return(@sp) + end + context 'つつがなく終わるとき' do + it 'ステータスコード200 OKを返す' do + get :show, :id => @sp.id + response.should be_success + end + it 'システム画像モデルに単体取得を問い合わせている' do + SystemPicture.should_receive(:show).exactly(1) + get :show + end + it '@system_pictureにアレを取得している' do + get :show, :id => @sp.id + assigns(:system_picture).should eq @sp + end + context 'html形式' do + it 'showテンプレートを描画する' do + get :show, :id => @sp.id + response.should render_template("show") + end + end + context 'json形式' do + it 'jsonデータを返す' do + get :show, :id => @sp.id, :format => :json + lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) + end + it 'システム画像モデルにjson単体出力オプションを問い合わせている' do + SystemPicture.should_receive(:show_json_opt).exactly(1) + get :show, :id => @sp.id, :format => :json + end + it 'データがアレになっている' do + get :show, :id => @sp.id, :format => :json + json = JSON.parse response.body + json["ext"].should match(/png/) + json["md5"].should be_true + json["width"].should be_true + end + end + #画像送信では、send_dataにスタブをおいてテストしたいが、ここに噛ませると + #renderが働かず、エラーとなってしまう。そこで、システム画像のファイル取得部分に + #スタブをおいてsend_dataがデータを返す体裁でテストする。 + context 'png形式' do + before do + SystemPicture.any_instance.stub(:mime_type).and_return('image/png') + SystemPicture.any_instance.stub(:restore).and_return('aaa') + end + it '画像モデルに画像データを問い合わせる' do + SystemPicture.any_instance.should_receive(:restore).exactly(1) + get :show, :id => @sp.id, :format => :png + end + it '画像モデルにMimeTypeを問い合わせる' do + SystemPicture.any_instance.should_receive(:mime_type).exactly(1) + get :show, :id => @sp.id, :format => :png + end + it '画像を送信する' do + get :show, :id => @sp.id, :format => :png + response.body.should eq 'aaa' + end + end + context 'gif形式' do + before do + SystemPicture.any_instance.stub(:mime_type).and_return('image/gif') + SystemPicture.any_instance.stub(:restore).and_return('bbb') + end + it '画像モデルに画像データを問い合わせる' do + SystemPicture.any_instance.should_receive(:restore).exactly(1) + get :show, :id => @sp.id, :format => :gif + end + it '画像モデルにMimeTypeを問い合わせる' do + SystemPicture.any_instance.should_receive(:mime_type).exactly(1) + get :show, :id => @sp.id, :format => :gif + end + it '画像を送信する' do + get :show, :id => @sp.id, :format => :gif + response.body.should eq 'bbb' + end + end + context 'jpeg形式' do + before do + SystemPicture.any_instance.stub(:mime_type).and_return('image/jpeg') + SystemPicture.any_instance.stub(:restore).and_return('ccc') + end + it '画像モデルに画像データを問い合わせる' do + SystemPicture.any_instance.should_receive(:restore).exactly(1) + get :show, :id => @sp.id, :format => :jpeg + end + it '画像モデルにMimeTypeを問い合わせる' do + SystemPicture.any_instance.should_receive(:mime_type).exactly(1) + get :show, :id => @sp.id, :format => :jpeg + end + it '画像を送信する' do + get :show, :id => @sp.id, :format => :jpeg + response.body.should eq 'ccc' + end + end + end + context '作家権限がないとき' do + before do + sign_out @user + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :show, :id => @sp.id + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + get :show, :id => @sp.id + response.body.should redirect_to '/users/sign_in' + end + end + context 'json形式' do + it 'ステータスコード401 Unauthorizedを返す' do + get :show, :id => @sp.id, :format => :json + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + get :show, :id => @sp.id, :format => :json + response.message.should match(/Unauthorized/) + end + end + end +=begin + context '対象システム画像がないとき' do + before do + SystemPicture.unstub(:show) + end + context 'html形式' do + it '例外404 not_foundを返す' do + lambda{ + get :show, :id => 0 + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + context 'json形式' do + it '例外404 not_foundを返す' do + lambda{ + get :show, :id => 0, :format => :json + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + context '他人のシステム画像を見ようとしたとき' do + before do + SystemPicture.stub(:show).and_return(@sp) + SystemPicture.any_instance.stub(:own?).with(any_args()).and_return(false) + end + context 'html形式' do + it '例外403 forbiddenを返す' do + lambda{ + get :show, :id => @sp.id + }.should raise_error(ActiveRecord::Forbidden) + end + end + context 'json形式' do + it '例外403 forbiddenを返す' do + lambda{ + get :show, :id => @sp.id, :format => :json + }.should raise_error(ActiveRecord::Forbidden) + end + end + end +=end + end + + describe '新規作成フォーム表示に於いて' do + before do + sign_in @user + sign_in @admin + end + context 'つつがなく終わるとき' do + context 'html形式' do + it 'ステータスコード200 OKを返す' do + get :new + response.should be_success + end + it 'ページテンプレートnewを描画する' do + get :new + response.should render_template("new") + end + end + end + context '管理者権限がないとき' do + before do + sign_out @admin + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + get :new + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + get :new + response.body.should redirect_to '/admins/sign_in' + end + end + end + end + + describe '新規作成に於いて' do + before do + sign_in @admin + sign_in @user + @attr = {:system_picture => {:file => "abc\ndef\nghi"}} + @imager = ImagerTest.load("abc\ndef\nghi") + end + context '事前チェックしておく' do + before do + PettanImager.stub(:load).with(any_args).and_return(@imager) + SystemPicture.any_instance.stub(:store).with(@imager).and_return(true) + end + it "画像ライブラリをロードしている" do + PettanImager.should_receive(:load).with(any_args).exactly(1) + post :create, @attr + end + it 'システム画像モデルに保存依頼する' do + SystemPicture.should_receive(:store).with(@imager).exactly(1) + post :create, @attr + end + end + context 'つつがなく終わるとき' do + before do + PettanImager.stub(:load).with(any_args).and_return(@imager) + SystemPicture.stub(:store).with(@imager).and_return(@sp) + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + post :create, @attr + response.status.should eq 302 + end + it '作成されたシステム画像の表示ページへ遷移する' do + post :create, @attr + response.should redirect_to(SystemPicture.last) + end + end + context 'json形式' do + before do + @attr.merge!({:format => :json}) + end + it 'ステータスコード200 OKを返す' do + post :create, @attr + response.should be_success + end + it '作成されたシステム画像をjsonデータで返す' do + post :create, @attr + lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError) + end + it 'システム画像モデルにjson単体出力オプションを問い合わせている' do + SystemPicture.should_receive(:show_json_opt).exactly(1) + post :create, @attr + end + it 'データがアレになっている' do + post :create, @attr + json = JSON.parse response.body + json["ext"].should match(/png/) + json["md5"].should be_true + json["width"].should be_true + end + end + end + context '管理者権限がないとき' do + before do + sign_out @admin + end + context 'html形式' do + it 'ステータスコード302 Foundを返す' do + post :create, @attr + response.status.should eq 302 + end + it 'サインインページへ遷移する' do + post :create, @attr + response.body.should redirect_to '/admins/sign_in' + end + end + context 'json形式' do + before do + @attr.merge!({:format => :json}) + end + it 'ステータスコード401 Unauthorizedを返す' do + post :create, @attr + response.status.should eq 401 + end + it '応答メッセージにUnauthorizedを返す' do + post :create, @attr + response.message.should match(/Unauthorized/) + end + end + end + context '検証、保存に失敗した' do + before do + SystemPicture.stub(:store).and_return(nil) + end + context 'html形式' do + it 'ステータスコード200 OKを返す' do + post :create, @attr + response.status.should eq 200 + end + it '新規ページを描画する' do + post :create, @attr + response.should render_template("new") + end + end + context 'json形式' do + before do + @attr.merge!({:format => :json}) + end + it 'ステータスコード422 unprocessable_entity を返す' do + post :create, @attr + response.status.should eq 422 + end + it '応答メッセージUnprocessable Entityを返す' do + post :create, @attr + response.message.should match(/Unprocessable/) + end + end + end + end end diff --git a/spec/models/comic_spec.rb b/spec/models/comic_spec.rb index 794cb210..8887e3e0 100644 --- a/spec/models/comic_spec.rb +++ b/spec/models/comic_spec.rb @@ -198,16 +198,16 @@ describe Comic do c.should eq [@comic] end end - context 'DBに5件あって1ページの件数を0件に変えたとして' do + context 'DBに5件あって1ページの件数を2件に変えたとして' do before do @comic2 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 100 @comic3 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 200 @comic4 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 300 @comic5 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 400 - Color.stub(:default_page_size).and_return(0) + Comic.stub(:default_page_size).and_return(2) end - it '通常は全件(5件)を返す' do - r = Comic.list + it '件数0は全件(5件)を返す' do + r = Comic.list 5, 0 r.should have(5).items end end @@ -351,7 +351,7 @@ describe Comic do it '403Forbidden例外を返す' do Comic.any_instance.stub(:visible?).and_return(false) lambda{ - Comic.show @author.id, @author + Comic.show @comic.id, @author }.should raise_error(ActiveRecord::Forbidden) end end diff --git a/spec/models/license_group_spec.rb b/spec/models/license_group_spec.rb index a6ca057a..97cc5d24 100644 --- a/spec/models/license_group_spec.rb +++ b/spec/models/license_group_spec.rb @@ -207,6 +207,8 @@ describe LicenseGroup do before do @n = @j.keys.first @a = @j.values.first + @imager = ImagerTest.load("abc\ndef\nghi") + PettanImager.stub(:load).with(any_args).and_return(@imager) end context 'つつがなく終わるとき' do it 'データ更新準備を依頼する' do diff --git a/spec/models/original_picture_spec.rb b/spec/models/original_picture_spec.rb index b3327704..7c82cbf4 100644 --- a/spec/models/original_picture_spec.rb +++ b/spec/models/original_picture_spec.rb @@ -170,57 +170,36 @@ describe OriginalPicture do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id end - it '自分の原画を見るときは許可する' do - OriginalPicture.any_instance.stub(:own?).and_return(true) + it '自分の原画を見るときは許可する' do + OriginalPicture.any_instance.stub(:own?).and_return(true) r = @op.visible?(@artist) r.should == true - end - it '他人の原画なら許可しない' do - OriginalPicture.any_instance.stub(:own?).and_return(false) + end + it '他人の原画なら許可しない' do + OriginalPicture.any_instance.stub(:own?).and_return(false) r = @op.visible?(@artist) r.should == false - end - end - - #大文字混じりは検証ではねているので、無用になっている - describe '拡張子に於いて' do - before do - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id, :ext => 'jpeg' end - it '画像ファイル拡張子を英数小文字で返す' do - r = @op.dext - r.should eq 'jpeg' - end end describe 'ファイル名に於いて' do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - OriginalPicture.any_instance.stub(:dext).and_return('gif') - end - it '拡張子取得を依頼している' do - OriginalPicture.any_instance.should_receive(:dext).exactly(1) - @op.filename end - it 'id+拡張子のフォーマットで返す' do + it 'id+拡張子のフォーマットで返す' do r = @op.filename - r.should eq "#{@op.id}.gif" - end + r.should eq "#{@op.id}.png" + end end describe 'MimeTypeに於いて' do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - OriginalPicture.any_instance.stub(:dext).and_return('gif') - end - it '拡張子取得を依頼している' do - OriginalPicture.any_instance.should_receive(:dext).exactly(1) - @op.mime_type end - it 'image/拡張子のフォーマットで返す' do + it 'image/拡張子のフォーマットで返す' do r = @op.mime_type - r.should eq "image/gif" - end + r.should eq "image/png" + end end describe 'ファイルのurlに於いて' do @@ -232,10 +211,10 @@ describe OriginalPicture do OriginalPicture.any_instance.should_receive(:filename).exactly(1) @op.url end - it '/original_pictures/3.gifのフォーマットで返す' do + it '/original_pictures/3.gifのフォーマットで返す' do r = @op.url r.should eq "/original_pictures/3.gif" - end + end end describe '画像タグオプションに於いて' do @@ -248,10 +227,10 @@ describe OriginalPicture do ResourcePicture.should_receive(:fix_size_both).with(any_args).exactly(1) @op.opt_img_tag end - it '戻り値はHashで返す' do + it '戻り値はHashで返す' do r = @op.opt_img_tag r.is_a?(Hash).should be_true - end + end it 'srcキーを含んでいる' do r = @op.opt_img_tag r.has_key?(:src).should be_true @@ -340,13 +319,13 @@ describe OriginalPicture do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id end - context 'つつがなく終わるとき' do - it '一覧取得オプションを利用している' do - OriginalPicture.stub(:list_opt).with(any_args).and_return({}) - OriginalPicture.should_receive(:list_opt).with(any_args).exactly(1) + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + OriginalPicture.stub(:list_opt).with(any_args).and_return({}) + OriginalPicture.should_receive(:list_opt).with(any_args).exactly(1) r = OriginalPicture.mylist @artist - end - end + end + end it 'リストを返す' do r = OriginalPicture.mylist @artist r.should eq [@op] @@ -434,25 +413,25 @@ describe OriginalPicture do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id end - context 'つつがなく終わるとき' do - it '単体取得オプションを利用している' do - OriginalPicture.stub(:show_opt).with(any_args).and_return({}) - OriginalPicture.should_receive(:show_opt).with(any_args).exactly(1) + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + OriginalPicture.stub(:show_opt).with(any_args).and_return({}) + OriginalPicture.should_receive(:show_opt).with(any_args).exactly(1) r = OriginalPicture.show @op.id, @artist - end - it '閲覧許可を問い合わせている' do - OriginalPicture.any_instance.stub(:visible?).with(any_args).and_return(true) - OriginalPicture.any_instance.should_receive(:visible?).with(any_args).exactly(1) + end + it '閲覧許可を問い合わせている' do + OriginalPicture.any_instance.stub(:visible?).with(any_args).and_return(true) + OriginalPicture.any_instance.should_receive(:visible?).with(any_args).exactly(1) r = OriginalPicture.show @op.id, @artist - end - end + end + end it '指定の原画を返す' do pic = OriginalPicture.show @op.id, @artist pic.should eq @op end context '他人の原画を開こうとしたとき' do it '403Forbidden例外を返す' do - OriginalPicture.any_instance.stub(:visible?).and_return(false) + OriginalPicture.any_instance.stub(:visible?).and_return(false) lambda{ pic = OriginalPicture.show @op.id, @other_artist }.should raise_error(ActiveRecord::Forbidden) @@ -470,18 +449,18 @@ describe OriginalPicture do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id end - context 'つつがなく終わるとき' do - it '単体取得オプションを利用している' do - OriginalPicture.stub(:show_opt).with(any_args).and_return({}) - OriginalPicture.should_receive(:show_opt).with(any_args).exactly(1) + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + OriginalPicture.stub(:show_opt).with(any_args).and_return({}) + OriginalPicture.should_receive(:show_opt).with(any_args).exactly(1) r = OriginalPicture.edit @op.id, @artist - end - it '所持判定を問い合わせている' do - OriginalPicture.any_instance.stub(:own?).with(any_args).and_return(true) - OriginalPicture.any_instance.should_receive(:own?).with(any_args).exactly(1) + end + it '所持判定を問い合わせている' do + OriginalPicture.any_instance.stub(:own?).with(any_args).and_return(true) + OriginalPicture.any_instance.should_receive(:own?).with(any_args).exactly(1) r = OriginalPicture.edit @op.id, @artist - end - end + end + end it '指定の原画を返す' do pic = OriginalPicture.edit @op.id, @artist pic.should eq @op @@ -538,93 +517,68 @@ describe OriginalPicture do r.has_key?(:pictures).should be_true end end - describe 'RMagick変換に於いて' do - before do - @op = FactoryGirl.build :original_picture, :artist_id => @artist.id - end - context 'つつがなく終わるとき' do - it '画像データをオブジェクト化している' do - Magick::Image.stub(:from_blob).and_return(['mgkobj']) - @op.data_to_mgk('mgkbin').should eq 'mgkobj' - end - end - context '失敗するとき' do - it 'Falseを返す' do - Magick::Image.should_receive(:from_blob).with(any_args).and_raise('StandardError') - @op.data_to_mgk('mgkbin').should be_false - end - it '全体エラーがセットされている' do - Magick::Image.should_receive(:from_blob).with(any_args).and_raise('StandardError') - lambda { - @op.data_to_mgk('mgkbin') - }.should change(@op.errors[:base], :count) - end - end - end describe '作成・更新に於いて' do before do @op = FactoryGirl.build :original_picture, :artist_id => @artist.id - @bd = File.open(Rails.root + 'spec/StandardA.gif', 'rb').read + @imager = ImagerTest.load "abc\ndef\nghi" end context '事前チェック' do before do #すべての処理が正常パターンで通過すれば、一番深い分岐まで通る。 #それで外部のメソッド呼び出しだけに着目してテストする。 OriginalPicture.any_instance.stub(:save).with(any_args).and_return(true) - PictureIO::LocalPicture.any_instance.stub(:put).with(any_args).and_return(true) - end - it 'RMagick変換を依頼している' do - OriginalPicture.any_instance.should_receive(:data_to_mgk).exactly(1) - @op.store @bd, @artist + PictureIO.original_picture_io.stub(:put).with(any_args).and_return(true) end it '自身に属性をセットしている' do OriginalPicture.any_instance.should_receive(:attributes=).exactly(1) - @op.store @bd, @artist + @op.store @imager end it '自身が保存されている' do OriginalPicture.any_instance.should_receive(:save).exactly(1) - @op.store @bd, @artist + @op.store @imager end it 'PictureIoに画像データの保存を依頼している' do - PictureIO::LocalPicture.any_instance.should_receive(:put).with(any_args).exactly(1) - @op.store @bd, @artist + PictureIO.original_picture_io.should_receive(:put).with(any_args).exactly(1) + @op.store @imager end end context 'つつがなく終わるとき' do before do - #すべての処理を正常パターンで通過させ、保存機能をチェックする。 -# OriginalPicture.any_instance.stub(:save).with(any_args).and_return(true) -# PictureIO::LocalPicture.any_instance.stub(:put).with(any_args).and_return(true) end it '自身に属性をセットしている' do - lambda { - @op.store @bd, @artist - }.should change @op, :filesize + @op.store @imager + @op.width.should eq 3 + @op.height.should eq 3 + @op.filesize.should eq 9 end it '原画モデルが作成されている' do lambda { - @op.store @bd, @artist + @op.store @imager }.should change OriginalPicture, :count end it '原画が保存されている' do - @op.store @bd, @artist + @op.store @imager OriginalPicture.find(@op).should_not be_nil end it 'Trueを返す' do - @op.store(@bd, @artist).should eq true + @op.store(@imager).should eq true end end #以下から例外ケース。処理先頭から失敗させていく - context 'RMagick変換が失敗したとき' do + context 'imagerが初期化に失敗したとき' do before do - OriginalPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(false) end it 'falseを返す' do - @op.store(@bd, @artist).should be_false + @op.store(false).should be_false end it '自身の保存は呼ばれていない' do OriginalPicture.any_instance.should_not_receive(:save) - @op.store(@bd, @artist) + @op.store(false) + end + it '全体エラーメッセージがセットされている' do + lambda { + @op.store(false) + }.should change(@op.errors[:base], :count) end end context '自身の保存に失敗したとき' do @@ -632,10 +586,10 @@ describe OriginalPicture do OriginalPicture.any_instance.stub(:save).with(any_args).and_return(false) end it 'falseを返す' do - @op.store(@bd, @artist).should be_false + @op.store(@imager).should be_false end it '更新されていない' do - @op.store(@bd, @artist) + @op.store(@imager) @op.should be_a_new OriginalPicture end it '原画の保存は呼ばれていない' do @@ -645,24 +599,150 @@ describe OriginalPicture do context '原画の保存に失敗したとき' do before do OriginalPicture.any_instance.stub(:save).with(any_args).and_return(true) - PictureIO::LocalPicture.any_instance.stub(:put).with(any_args).and_return(false) + PictureIO.original_picture_io.stub(:put).with(any_args).and_return(false) end it 'falseを返す' do - @op.store(@bd, @artist).should be_false + @op.store(@imager).should be_false end it '更新されていない' do - @op.store(@bd, @artist) + @op.store(@imager) @op.should be_a_new OriginalPicture end - it '対象素材オブジェクトの保存は呼ばれていない' do - ResourcePicture.any_instance.should_not_receive(:save) - @op.store(@bd, @artist) - end it '全体エラーメッセージがセットされている' do lambda { - @op.store(@bd, @artist) + @op.store(@imager) }.should change(@op.errors[:base], :count) end end end + +=begin + describe 'エクスポートに於いて' do + before do + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :revision => 0 + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :picture_id => @p.id + #他人の原画排除 + @other_op = FactoryGirl.create :original_picture, :artist_id => @other_artist.id + end + context 'つつがなく終わるとき' do + it 'ライセンスグループに依頼してリストを取得している' do + LicenseGroup.stub(:list).with(any_args).and_return([@lg]) + LicenseGroup.should_receive(:list).with(any_args).exactly(1) + r = OriginalPicture.export(@artist) + end + it '原画に依頼してリストを取得している' do + OriginalPicture.stub(:list).with(any_args).and_return([@op]) + OriginalPicture.should_receive(:list).with(any_args).exactly(1) + r = OriginalPicture.export(@artist) + end + it 'Hashを返す' do + r = OriginalPicture.export(@artist) + r.is_a?(Hash).should be_true + end + it 'Hashはライセンスグループを含んでいる' do + r = OriginalPicture.export(@artist) + r.include?(:license_groups).should be_true + end + it 'Hashは原画を含んでいる' do + r = OriginalPicture.export(@artist) + r.include?(:original_pictures).should be_true + end + #素材がライセンスされていないケースもある + it 'Hashの原画は素材を含んでいる' do + r = OriginalPicture.export(@artist) + r[:original_pictures].first.resource_picture.should_not be_nil + end + it 'Hashの原画は実素材を含んでいる' do + r = OriginalPicture.export(@artist) + r[:original_pictures].first.pictures.should be_nil + end + end + context '実データ単体のとき' do + it 'ライセンスは配列構造になっている' do + r = OriginalPicture.export(@artist) + r[:license_groups].is_a?(Array).should be_true + end + it 'ライセンスが全件出ている' do + r = OriginalPicture.export(@artist) + r[:license_groups].size.should eq 1 + r[:license_groups].first.should eq @lg + end + it '原画は配列構造になっている' do + r = OriginalPicture.export(@artist) + r[:original_pictures].is_a?(Array).should be_true + end + it '原画が全件出ている' do + r = OriginalPicture.export(@artist) + r[:original_pictures].size.should eq 1 + r[:original_pictures].first.should eq @op + end + it '原画に素材が関連付いている' do + r = OriginalPicture.export(@artist) + i = r[:original_pictures].first + i.resource_picture.should eq @rp + end + it '原画に実素材が関連付いている' do + r = OriginalPicture.export(@artist) + i = r[:original_pictures].first + i.picture.should eq @p + end + end + context '実データ複数のとき' do + before do + @lg2 = FactoryGirl.create :license_group, :name => 'export test', :url => 'http://export.test/' + @license2 = FactoryGirl.create :license, :license_group_id => @lg2.id, :system_picture_id => @sp.id, :name => 'export test license', :url => 'http://export.test/license' + @op2 = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p2 = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op2.id, :license_id => @license2.id, :revision => 0 + @rp2 = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op2.id, :license_id => @license2.id, :picture_id => @p2.id + end + it 'ライセンスは配列構造になっている' do + r = OriginalPicture.export(@artist) + r[:license_groups].is_a?(Array).should be_true + end + it 'ライセンスが全件出ている' do + r = OriginalPicture.export(@artist) + r[:license_groups].size.should eq 2 + r[:license_groups].first.should eq @lg + r[:license_groups].last.should eq @lg2 + end + it '原画は配列構造になっている' do + r = OriginalPicture.export(@artist) + r[:original_pictures].is_a?(Array).should be_true + end + it '原画が全件出ている' do + r = OriginalPicture.export(@artist) + r[:original_pictures].size.should eq 2 + r[:original_pictures].first.should eq @op + r[:original_pictures].last.should eq @op2 + end + it '原画に素材が関連付いている' do + r = OriginalPicture.export(@artist) + i = r[:original_pictures].first + i.resource_picture.should eq @rp + i2 = r[:original_pictures].last + i2.resource_picture.should eq @rp2 + end + it '原画に実素材が関連付いている' do + r = OriginalPicture.export(@artist) + i = r[:original_pictures].first + i.picture.should eq @p + i2 = r[:original_pictures].last + i2.picture.should eq @p2 + end + end + end + + describe 'エクスポートオプションに於いて' do + end + + describe 'インポートに於いて' do + before do + @imports = {:licenses => {}, :artist_id => @artist.id} + end + context '事前チェックしておく' do + end + end + +=end end diff --git a/spec/models/picture_spec.rb b/spec/models/picture_spec.rb index 7177bfc0..002c7162 100644 --- a/spec/models/picture_spec.rb +++ b/spec/models/picture_spec.rb @@ -19,21 +19,33 @@ describe Picture do describe '検証に於いて' do before do + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id end - it 'オーソドックスなデータなら通る' do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - @p.should be_valid - end - - context 'original_picture_idを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @p.revision = 1 + @p.ext = 'png' #リストにない拡張子は通らないし + @p.width = 1 + @p.height = 1 + @p.filesize = 1 + @p.md5 = 'a'*32 + @p.classname = 'a'*1 + @p.should be_valid end - it 'テストデータの確認' do - @p.original_picture_id = @op.id + it '上限データが通る' do + @p.revision = 99999 + @p.ext = 'jpeg' + @p.width = 99999 + @p.height = 99999 + @p.filesize = 2000000 + @p.md5 = 'a'*32 + @p.classname = 'a'*50 @p.should be_valid end + end + + context 'original_picture_idを検証するとき' do it 'nullなら失敗する' do @p.original_picture_id = nil @p.should_not be_valid @@ -48,13 +60,6 @@ describe Picture do end end context 'revisionを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.revision = 1 - @p.should be_valid - end it 'nullなら失敗する' do @p.revision = nil @p.should_not be_valid @@ -65,13 +70,6 @@ describe Picture do end end context 'extを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.ext = 'jpeg' - @p.should be_valid - end it 'nullなら失敗する' do @p.ext = '' @p.should_not be_valid @@ -86,13 +84,6 @@ describe Picture do end end context 'widthを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.width = 1 - @p.should be_valid - end it 'nullなら失敗する' do @p.width = nil @p.should_not be_valid @@ -111,13 +102,6 @@ describe Picture do end end context 'heightを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.height = 1 - @p.should be_valid - end it 'nullなら失敗する' do @p.height = nil @p.should_not be_valid @@ -136,13 +120,6 @@ describe Picture do end end context 'filesizeを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.filesize = 1 - @p.should be_valid - end it 'nullなら失敗する' do @p.filesize = nil @p.should_not be_valid @@ -160,14 +137,21 @@ describe Picture do @p.should_not be_valid end end - context 'artist_idを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + context 'md5を検証するとき' do + it 'nullなら失敗する' do + @p.md5 = '' + @p.should_not be_valid end - it 'テストデータの確認' do - @p.artist_id = @artist.id - @p.should be_valid + it '31文字なら失敗する' do + @p.md5 = 'a'*31 + @p.should_not be_valid + end + it '32文字以上なら失敗する' do + @p.md5 = 'a'*33 + @p.should_not be_valid end + end + context 'artist_idを検証するとき' do it 'nullなら失敗する' do @p.artist_id = nil @p.should_not be_valid @@ -181,31 +165,7 @@ describe Picture do @p.should_not be_valid end end - context 'md5を検証するとき' do - before do - @p = FactoryGirl.build :picture - end - it 'テストデータの確認' do - @p.md5 = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - @p.should be_valid - end - it 'nullなら失敗する' do - @p.md5 = '' - @p.should_not be_valid - end - it '32文字以上なら失敗する' do - @p.md5 = 'a'*33 - @p.should_not be_valid - end - end context 'license_idを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.license_id = @license.id - @p.should be_valid - end it 'nullなら失敗する' do @p.license_id = nil @p.should_not be_valid @@ -214,32 +174,18 @@ describe Picture do @p.license_id = 'a' @p.should_not be_valid end - it '存在するライセンスグループでなければ失敗する' do + it '存在するライセンスでなければ失敗する' do @p.license_id = 0 @p.should_not be_valid end end context 'artist_nameを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.artist_name = 'a' - @p.should be_valid - end it 'nullなら失敗する' do @p.artist_name = nil @p.should_not be_valid end end context 'classnameを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.classname = 'a'*50 - @p.should be_valid - end it 'nullなら失敗する' do @p.classname = '' @p.should_not be_valid @@ -250,26 +196,120 @@ describe Picture do end end context 'creditを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.credit = 'a' - @p.should be_valid - end end context 'settingsを検証するとき' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it 'テストデータの確認' do - @p.settings = 'a' - @p.should be_valid - end end end - describe '補充に於いて' do + + describe 'デフォルト値補充に於いて' do + it 'defined' do + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @p.supply_default + end + end + + describe '上書き補充に於いて' do + before do + attr = {:ext => 'jpeg', :width => 264, :height => 265, :filesize => 266, + :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, + :artist_name => 'tester', :classname => 'Tester', :credit => {:title => 'cap'}.to_json.to_s, :settings => {:set => 1}.to_json.to_s} + @rp = FactoryGirl.build :resource_picture, attr + @p = FactoryGirl.build :picture, :original_picture_id => nil, :license_id => nil, :artist_id => nil, :revision => nil + end + it 'width, height, ext, filesize, md5, original_picture_idが設定されている' do + @p.overwrite @rp + @p.width.should eq 264 + @p.height.should eq 265 + @p.ext.should eq 'jpeg' + @p.filesize.should eq 266 + @p.md5.should eq @rp.md5 + @p.original_picture_id.should eq @op.id + end + it 'license_id, artist_id, artist_name, classname, credit, settingsが設定されている' do + @p.overwrite @rp + @p.license_id.should eq @license.id + @p.artist_id.should eq @artist.id + @p.artist_name.should eq 'tester' + @p.classname.should eq 'Tester' + @p.credit.should match /title/ + @p.settings.should match /set/ + end + it 'new_revisionに問い合わせている' do + Picture.any_instance.stub(:new_revision).with(any_args).and_return(3) + Picture.any_instance.should_receive(:new_revision).with(any_args).exactly(1) + @p.overwrite @rp + end + it 'revisionは、new_revisionに設定されている' do + Picture.any_instance.stub(:new_revision).with(any_args).and_return(3) + @p.overwrite @rp + @p.revision.should eq 3 + end + end + + describe '所持判定に於いて' do + before do + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + end + it '実素材を更新することはないので、Falseを返す' do + @p.own?(@author).should == false + end + end + + describe '閲覧許可に於いて' do + before do + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + end + it '必ず許可となる' do + r = @p.visible?(@author) + r.should == true + end + end + + describe 'ファイル名に於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' + end + it 'id+拡張子のフォーマットで返す' do + r = @p.filename + r.should eq "#{@p.id}.png" + end + end + + describe 'gifファイル名に於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'gif' + end + it 'id.gifのフォーマットで返す' do + r = @p.filename + r.should eq "#{@p.id}.gif" + end + end + + describe 'MimeTypeに於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' + end + it 'image/拡張子のフォーマットで返す' do + r = @p.mime_type + r.should eq "image/png" + end + end + + describe 'ファイルのurlに於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + Picture.any_instance.stub(:filename).and_return('3.gif') + end + it 'ファイル名取得を依頼している' do + Picture.any_instance.should_receive(:filename).exactly(1) + @p.url + end + it '/pictures/3.gifのフォーマットで返す' do + r = @p.url + r.should eq "/pictures/3.gif" + end end + describe '最新Revision取得に於いて' do context '初めての原画を公開したとき' do before do @@ -299,32 +339,90 @@ describe Picture do end end end - describe '素材からのコピーデータセットに於いて' do + + describe 'head判定に於いて' do before do - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - attr = {:ext => 'jpeg', :width => 264, :height => 265, :filesize => 266, - :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, - :artist_name => 'tester', :classname => 'Tester', :credit => {:title => 'cap'}.to_json.to_s, :settings => {:set => 1}.to_json.to_s} - @rp = FactoryGirl.build :resource_picture, attr - @p = FactoryGirl.build :picture end - it '素材オブジェクトから属性を取り出して対象実素材にセットしている' do - res = @p.copy_data(@rp) - @p.ext.should eq 'jpeg' - @p.width.should eq 264 - @p.height.should eq 265 - @p.filesize.should eq 266 - @p.artist_id.should eq @artist.id - @p.md5.should eq @rp.md5 - @p.license_id.should eq @license.id - @p.original_picture_id.should eq @op.id - @p.artist_name.should eq 'tester' - @p.classname.should eq 'Tester' - @p.credit.should match /title/ - @p.settings.should match /set/ + context '自身とリンクした素材があるとき' do + before do + @p = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :picture_id => @p.id + end + it 'trueを返す' do + res = @p.head? + res.should be_true + end + end + context '自身とリンクした素材がないとき' do + before do + @p = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :revision => 0 + @p2 = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :revision => 1 + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :picture_id => @p2.id + end + it 'falseを返す' do + res = @p.head? + res.should be_false + end end end + describe 'フォーマット変換対象判定に於いて' do + before do + @p = FactoryGirl.build :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id + end + context '変換するケース' do + it '画像フォーマットがpngかつライセンスの変換禁止フラグが無効のときTrue' do + Picture.any_instance.stub(:flag_gif_convert).with(any_args).and_return(0) + @p.ext = 'png' + @p.to_gif?.should be_true + end + end + context '変換しないケース' do + it '画像フォーマットがpngでない' do + Picture.any_instance.stub(:flag_gif_convert).with(any_args).and_return(0) + @p.ext = 'gif' + @p.to_gif?.should be_false + end + it '変換禁止フラグが無効' do + Picture.any_instance.stub(:flag_gif_convert).with(any_args).and_return(-1) + @p.ext = 'png' + @p.to_gif?.should be_false + end + end + end + + describe 'サブディレクトリリストに於いて' do + before do + @p = FactoryGirl.build :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id + end + it '配列で返す' do + Picture.any_instance.stub(:flag_gif_convert).with(any_args).and_return(0) + r = @p.subdirs + r.is_a?(Array).should be_true + end + it '本画像(ベースディレクトリ)を含んでいる' do + Picture.any_instance.stub(:flag_reverse).with(any_args).and_return(0) + r = @p.subdirs + r.include?('').should be_true + end + context '反転が許可されているとき' do + it '垂直・水平・垂直水平反転ディレクトリも返す' do + Picture.any_instance.stub(:flag_reverse).with(any_args).and_return(0) + r = @p.subdirs + r.include?('v').should be_true + r.include?('h').should be_true + r.include?('vh').should be_true + end + end + context '反転が許可されていないとき' do + it '本画像(ベースディレクトリ)だけを返す' do + Picture.any_instance.stub(:flag_reverse).with(any_args).and_return(-1) + r = @p.subdirs + r.size.should eq 1 + end + end + end + describe 'md5重複リストに於いて' do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id @@ -409,45 +507,41 @@ describe Picture do end end - describe 'head判定に於いて' do + describe '単体取得に於いて' do before do + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id end - context '自身とリンクした素材があるとき' do - before do - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - @p = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id - @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :picture_id => @p.id - end - it 'trueを返す' do - res = @p.head? - res.should be_true + context 'つつがなく終わるとき' do + it '閲覧許可を問い合わせている' do + Picture.any_instance.stub(:visible?).with(any_args).and_return(true) + Picture.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = Picture.show @p.id, @author end end - context '自身とリンクした素材がないとき' do - before do - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - @p = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :revision => 0 - @p2 = FactoryGirl.create :picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :revision => 1 - @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :picture_id => @p2.id + it '指定の実素材を返す' do + r = Picture.show @p.id, @author + r.should eq @p + end + context '他人の実素材を開こうとしたとき' do + it '403Forbidden例外を返す' do + Picture.any_instance.stub(:visible?).and_return(false) + lambda{ + r = Picture.show @p.id, @other_author + }.should raise_error(ActiveRecord::Forbidden) end - it 'falseを返す' do - res = @p.head? - res.should be_false + end + context '存在しない実素材を開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + r = Picture.show 0, @author + }.should raise_error(ActiveRecord::RecordNotFound) end end end describe '作成に於いて' do before do - #RMagickのスタブをおいておく - class Mgk ; class Image ; end ; end - @filesize = 76543 - Mgk::Image.stub(:from_blob).with(any_args).and_return([Mgk.new]) - Mgk.any_instance.stub(:format).with(any_args).and_return('png') - Mgk.any_instance.stub(:rows).with(any_args).and_return(200) - Mgk.any_instance.stub(:columns).with(any_args).and_return(100) - Mgk.any_instance.stub(:filesize).with(any_args).and_return(@filesize) - Mgk.any_instance.stub(:to_blob).with(any_args).and_return('data') + @imager = ImagerTest.load "abc\ndef\nghi" #原画ファイル削除だけは必ず成功するものとしておく PictureIO::LocalPicture.any_instance.stub(:delete).with(any_args).and_return(true) end @@ -458,178 +552,117 @@ describe Picture do Picture.any_instance.stub(:save).with(any_args).and_return(true) Picture.any_instance.stub(:store_picture).with(any_args).and_return(true) Picture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - class GifMgk < Mgk ; end #store_pictureは二回呼び出される。区別をつけるために - @gifmgk = GifMgk.new #パラメータを二種類用意する。 - Picture.stub(:png_to_gif).with(any_args).and_return(@gifmgk) - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - it '最新Revisionを取得している' do - Picture.any_instance.should_receive(:new_revision).with(any_args).exactly(1) - res = @p.store(Mgk.new) + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end it '自身を保存している' do Picture.any_instance.should_receive(:save).with(any_args).exactly(1) - res = @p.store(Mgk.new) + r = @p.store(@imager) end it '画像ファイルの作成機能で画像を保存している' do - mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 Picture.any_instance.stub(:filename).with(any_args).and_return('1.png') - Picture.any_instance.should_receive(:store_picture).with(mgk, '1.png').exactly(1) - res = @p.store(mgk) + #二回目の保存はgif変換の結果を渡す。 + Picture.any_instance.should_receive(:store_picture).with(any_args).exactly(2) + r = @p.store(@imager) end it '自身にgifフォーマット変換対象かを問い合わせている' do Picture.any_instance.should_receive(:to_gif?).with(any_args).exactly(1) - res = @p.store(Mgk.new) - end - it '自身にGifフォーマット変換を依頼している' do - Picture.should_receive(:png_to_gif).with(any_args).exactly(1) - res = @p.store(Mgk.new) - end - it '画像ファイルの作成機能でgif画像を保存している' do - #二回目の保存はgif変換の結果を渡す。 - Picture.any_instance.stub(:gifname).with(any_args).and_return('1.gif') - Picture.any_instance.should_receive(:store_picture).with(@gifmgk, '1.gif').exactly(1) - res = @p.store(Mgk.new) + r = @p.store(@imager) end end context 'つつがなく終わるとき' do before do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 -# Picture.any_instance.stub(:save).with(any_args).and_return(true) Picture.any_instance.stub(:store_picture).with(any_args).and_return(true) Picture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - class GifMgk < Mgk ; end #store_pictureは二回呼び出される。区別をつけるために - @gifmgk = GifMgk.new #パラメータを二種類用意する。 - Picture.stub(:png_to_gif).with(any_args).and_return(@gifmgk) - @p = FactoryGirl.build :picture, :revision => nil, :original_picture_id => @op.id, :license_id => @license.id + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end it 'Trueを返す' do - res = @p.store(Mgk.new) - res.should be_true - end - it 'Revisionに最新Revisionセット' do - res = @p.store(Mgk.new) - @p.revision.should eq 1 + r = @p.store(@imager) + r.should be_true end it '自身が保存されている' do lambda { - res = @p.store(Mgk.new) + r = @p.store(@imager) }.should change Picture, :count end end context 'gif変換なしで、つつがなく終わるとき' do before do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 - Picture.any_instance.stub(:save).with(any_args).and_return(true) Picture.any_instance.stub(:store_picture).with(any_args).and_return(true) Picture.any_instance.stub(:to_gif?).with(any_args).and_return(false) - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end it 'Trueを返す' do - res = @p.store(Mgk.new) - res.should be_true + r = @p.store(@imager) + r.should be_true end it 'gif保存は呼ばれていない' do #二回目の画像作成が呼び出されないで1回こっきりならgif保存は呼ばれていないんだろう。 Picture.any_instance.should_receive(:store_picture).with(any_args).exactly(1) - res = @p.store(Mgk.new) + r = @p.store(@imager) end end #以下から例外ケース。処理先頭から失敗させていく context '自身の保存に失敗したとき' do before do Picture.any_instance.stub(:save).with(any_args).and_return(false) - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end it 'Falseを返す' do - res = @p.store(Mgk.new) - res.should be_false + r = @p.store(@imager) + r.should be_false end it '更新されていない' do - @p.store(Mgk.new) + r = @p.store(@imager) @p.should be_a_new Picture end end context '画像の保存に失敗したとき' do before do - Picture.any_instance.stub(:save).with(any_args).and_return(true) Picture.any_instance.stub(:store_picture).with(any_args).and_return(false) - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end it 'Falseを返す' do - res = @p.store(Mgk.new) - res.should be_false + r = @p.store(@imager) + r.should be_false end it 'gif変換判定は呼ばれていない' do - Picture.any_instance.should_not_receive(:to_gif?).with(any_args) - res = @p.store(Mgk.new) + Picture.any_instance.should_not_receive(:to_gif?).with(any_args).exactly(0) + r = @p.store(@imager) end end context 'gif変換に失敗したとき' do before do - Picture.any_instance.stub(:save).with(any_args).and_return(true) Picture.any_instance.stub(:store_picture).with(any_args).and_return(true) Picture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - Picture.stub(:png_to_gif).with(any_args).and_return(false) - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + ImagerTest.stub(:load).with(any_args).and_return(false) + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end it 'Falseを返す' do - res = @p.store(Mgk.new) - res.should be_false + r = @p.store(@imager) + r.should be_false end it 'gif画像の保存は呼ばれていない' do #本画像の保存があるので、一度は呼ばれる Picture.any_instance.should_receive(:store_picture).with(any_args).exactly(1) - res = @p.store(Mgk.new) + r = @p.store(@imager) end end context 'gif画像の保存に失敗したとき' do before do - @mgk = Mgk.new + @gifimager = @imager.to_gif + ImagerTest.any_instance.stub(:to_gif).with(any_args).and_return(@gifimager) Picture.any_instance.stub(:filename).with(any_args).and_return('1.png') Picture.any_instance.stub(:gifname).with(any_args).and_return('1.gif') - Picture.any_instance.stub(:save).with(any_args).and_return(true) - Picture.any_instance.stub(:store_picture).with(@mgk, '1.png').and_return(true) + Picture.any_instance.stub(:store_picture).with(@imager, '1.png').and_return(true) Picture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - class GifMgk < Mgk ; end #store_pictureは二回呼び出される。区別をつけるために - @gifmgk = GifMgk.new #パラメータを二種類用意する。 - Picture.stub(:png_to_gif).with(any_args).and_return(@gifmgk) - Picture.any_instance.stub(:store_picture).with(@gifmgk, '1.gif').and_return(false) - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + Picture.any_instance.stub(:store_picture).with(@gifimager, '1.gif').and_return(false) + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end it 'Falseを返す' do - res = @p.store(@mgk) - res.should be_false - end - end - end - - describe '反転画像の保存先に於いて' do - before do - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id - end - context '禁止のとき' do - it 'ベースディレクトリだけを返す' do - Picture.any_instance.should_receive(:flag_reverse).with(any_args).and_return(-1) - r = @p.subdirs - r.should have(1).item - end - it 'ベースディレクトリだけを返す' do - Picture.any_instance.should_receive(:flag_reverse).with(any_args).and_return(-1) - r = @p.subdirs - r.first.should eq '' - end - end - context '許可のとき' do - it 'ベースディレクトリと反転3種を返す' do - Picture.any_instance.should_receive(:flag_reverse).with(any_args).and_return(1) - r = @p.subdirs - r.should have(4).item - end - it 'ベースディレクトリと反転3種を返す' do - Picture.any_instance.should_receive(:flag_reverse).with(any_args).and_return(1) - r = @p.subdirs - r.last.should eq 'vh' + r = @p.store(@imager) + r.should be_false end end end @@ -637,23 +670,12 @@ describe Picture do describe '画像ファイルの作成に於いて' do #PictureIo経由で画像を保存するための機能。ファイル名に自身のidを使うので事前に自身の保存が必要。 before do - #RMagickのスタブをおいておく - class Mgk ; class Image ; end ; end - @filesize = 76543 - Mgk::Image.stub(:from_blob).with(any_args).and_return([Mgk.new]) - Mgk.any_instance.stub(:format).with(any_args).and_return('png') - Mgk.any_instance.stub(:rows).with(any_args).and_return(200) - Mgk.any_instance.stub(:columns).with(any_args).and_return(100) - Mgk.any_instance.stub(:filesize).with(any_args).and_return(@filesize) - Mgk.any_instance.stub(:to_blob).with(any_args).and_return('data') + @imager = ImagerTest.load "abc\ndef\nghi" #原画ファイル削除だけは必ず成功するものとしておく PictureIO::LocalPicture.any_instance.stub(:delete).with(any_args).and_return(true) Picture.any_instance.stub(:subdirs).with(any_args).and_return(['', 'v', 'h', 'vh']) - Picture.any_instance.stub(:h).with(any_args).and_return('data') - Picture.any_instance.stub(:v).with(any_args).and_return('data') - Picture.any_instance.stub(:vh).with(any_args).and_return('data') - @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id + @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png' end context '事前チェック' do before do @@ -662,35 +684,23 @@ describe Picture do end it '画像ファイルの保存が4回呼ばれる' do PictureIO.picture_io.should_receive(:put).with(any_args).exactly(4) - res = @p.store_picture(Mgk.new, '1.png') + r = @p.store_picture(@imager, '1.png') end it '画像ファイルのベースへの保存が1回呼ばれる' do - PictureIO.picture_io.should_receive(:put).with('data', '1.png', '').exactly(1) - res = @p.store_picture(Mgk.new, '1.png') + PictureIO.picture_io.should_receive(:put).with("abc\ndef\nghi", '1.png', '').exactly(1) + r = @p.store_picture(@imager, '1.png') end it '画像ファイルの垂直反転への保存が1回呼ばれる' do - PictureIO.picture_io.should_receive(:put).with('data', '1.png', 'v').exactly(1) - res = @p.store_picture(Mgk.new, '1.png') + PictureIO.picture_io.should_receive(:put).with("cba\nfed\nihg", '1.png', 'v').exactly(1) + r = @p.store_picture(@imager, '1.png') end it '画像ファイルの水平反転への保存が1回呼ばれる' do - PictureIO.picture_io.should_receive(:put).with('data', '1.png', 'h').exactly(1) - res = @p.store_picture(Mgk.new, '1.png') + PictureIO.picture_io.should_receive(:put).with("ghi\ndef\nabc", '1.png', 'h').exactly(1) + r = @p.store_picture(@imager, '1.png') end it '画像ファイルの垂直水平反転への保存が1回呼ばれる' do - PictureIO.picture_io.should_receive(:put).with('data', '1.png', 'vh').exactly(1) - res = @p.store_picture(Mgk.new, '1.png') - end - it '垂直反転が1回呼ばれる' do - Picture.any_instance.should_receive(:v).with(any_args).exactly(1) - res = @p.store_picture(Mgk.new, '1.png') - end - it '水平反転が1回呼ばれる' do - Picture.any_instance.should_receive(:h).with(any_args).exactly(1) - res = @p.store_picture(Mgk.new, '1.png') - end - it '垂直水平反転が1回呼ばれる' do - Picture.any_instance.should_receive(:vh).with(any_args).exactly(1) - res = @p.store_picture(Mgk.new, '1.png') + PictureIO.picture_io.should_receive(:put).with("ihg\nfed\ncba", '1.png', 'vh').exactly(1) + r = @p.store_picture(@imager, '1.png') end end context 'つつがなく終わるとき' do @@ -699,8 +709,8 @@ describe Picture do PictureIO.picture_io.stub(:put).with(any_args).and_return(true) end it 'Trueを返す' do - res = @p.store_picture(Mgk.new, '1.png') - res.should be_true + r = @p.store_picture(@imager, '1.png') + r.should be_true end end context '例外ケース' do @@ -708,8 +718,8 @@ describe Picture do PictureIO.picture_io.stub(:put).with(any_args).and_return(false) end it 'Falseを返す' do - res = @p.store_picture(Mgk.new, '1.png') - res.should be_false + r = @p.store_picture(@imager, '1.png') + r.should be_false end end diff --git a/spec/models/resource_picture_spec.rb b/spec/models/resource_picture_spec.rb index c8d377da..ba5d62a7 100644 --- a/spec/models/resource_picture_spec.rb +++ b/spec/models/resource_picture_spec.rb @@ -16,14 +16,6 @@ describe ResourcePicture do @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id @original_picture = FactoryGirl.create :original_picture, :artist_id => @artist.id - class Mgk ; class Image ; end ; end - Mgk::Image.stub(:from_blob).with(any_args).and_return([Mgk.new]) - Mgk.any_instance.stub(:format).with(any_args).and_return('png') - Mgk.any_instance.stub(:format=).with(any_args) - Mgk.any_instance.stub(:rows).with(any_args).and_return(200) - Mgk.any_instance.stub(:columns).with(any_args).and_return(100) - Mgk.any_instance.stub(:filesize).with(any_args).and_return(20000) - Mgk.any_instance.stub(:to_blob).with(any_args).and_return('data') #原画ファイル削除だけは必ず成功するものとしておく PictureIO::LocalPicture.any_instance.stub(:delete).with(any_args).and_return(true) Picture.any_instance.stub(:subdirs).with(any_args).and_return(['', 'v', 'h', 'vh']) @@ -38,15 +30,28 @@ describe ResourcePicture do @rp = FactoryGirl.build :resource_picture, :artist_id => @artist.id, :original_picture_id => @original_picture.id, :license_id => @license.id, :picture_id => @p.id end - it 'オーソドックスなデータなら通る' do - @rp.should be_valid - end - + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @rp.ext = 'png' #リストにない拡張子は通らないし + @rp.width = 1 + @rp.height = 1 + @rp.filesize = 1 + @rp.md5 = 'a'*32 + @rp.classname = 'a'*1 + @rp.should be_valid + end + it '上限データが通る' do + @rp.ext = 'jpeg' + @rp.width = 99999 + @rp.height = 99999 + @rp.filesize = 2000000 + @rp.md5 = 'a'*32 + @rp.classname = 'a'*50 + @rp.should be_valid + end + end + context 'extを検証するとき' do - it 'テストデータの確認' do - @rp.ext = 'jpeg' - @rp.should be_valid - end it 'nullなら失敗する' do @rp.ext = '' @rp.should_not be_valid @@ -61,10 +66,6 @@ describe ResourcePicture do end end context 'widthを検証するとき' do - it 'テストデータの確認' do - @rp.width = 1 - @rp.should be_valid - end it 'nullなら失敗する' do @rp.width = nil @rp.should_not be_valid @@ -83,10 +84,6 @@ describe ResourcePicture do end end context 'heightを検証するとき' do - it 'テストデータの確認' do - @rp.height = '1' - @rp.should be_valid - end it 'nullなら失敗する' do @rp.height = nil @rp.should_not be_valid @@ -105,10 +102,6 @@ describe ResourcePicture do end end context 'filesizeを検証するとき' do - it 'テストデータの確認' do - @rp.filesize = '1' - @rp.should be_valid - end it 'nullなら失敗する' do @rp.filesize = nil @rp.should_not be_valid @@ -127,10 +120,6 @@ describe ResourcePicture do end end context 'artist_idを検証するとき' do - it 'テストデータの確認' do - @rp.artist_id = @artist.id - @rp.should be_valid - end it 'nullなら失敗する' do @rp.artist_id = nil @rp.should_not be_valid @@ -145,27 +134,20 @@ describe ResourcePicture do end end context 'md5を検証するとき' do - before do - @rp = FactoryGirl.build :picture - end - it 'テストデータの確認' do - @rp.md5 = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - @rp.should be_valid - end it 'nullなら失敗する' do @rp.md5 = '' @rp.should_not be_valid end + it '31文字なら失敗する' do + @rp.md5 = 'a'*31 + @rp.should_not be_valid + end it '32文字以上なら失敗する' do @rp.md5 = 'a'*33 @rp.should_not be_valid end end context 'license_idを検証するとき' do - it 'テストデータの確認' do - @rp.license_id = @license.id - @rp.should be_valid - end it 'nullなら失敗する' do @rp.license_id = nil @rp.should_not be_valid @@ -180,10 +162,6 @@ describe ResourcePicture do end end context 'original_picture_idを検証するとき' do - it 'テストデータの確認' do - @rp.original_picture_id = @original_picture.id - @rp.should be_valid - end it 'nullなら失敗する' do @rp.original_picture_id = nil @rp.should_not be_valid @@ -198,20 +176,12 @@ describe ResourcePicture do end end context 'artist_nameを検証するとき' do - it 'テストデータの確認' do - @rp.artist_name = 'a' - @rp.should be_valid - end it 'nullなら失敗する' do @rp.artist_name = nil @rp.should_not be_valid end end context 'classnameを検証するとき' do - it 'テストデータの確認' do - @rp.classname = 'a'*50 - @rp.should be_valid - end it 'nullなら失敗する' do @rp.classname = '' @rp.should_not be_valid @@ -222,22 +192,10 @@ describe ResourcePicture do end end context 'creditを検証するとき' do - it 'テストデータの確認' do - @rp.credit = 'a' - @rp.should be_valid - end end context 'settingsを検証するとき' do - it 'テストデータの確認' do - @rp.settings = 'a' - @rp.should be_valid - end end context 'picture_idを検証するとき' do - it 'テストデータの確認' do - @rp.picture_id = @p.id - @rp.should be_valid - end it 'nullなら失敗する' do @rp.picture_id = nil @rp.should_not be_valid @@ -253,48 +211,91 @@ describe ResourcePicture do end end - describe 'データ補充に於いて' do - before do - end - - end - - describe '単体取得に於いて' do - before do - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id - @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :picture_id => @p.id - end - it '指定の素材を返す' do - pic = ResourcePicture.show @rp.id - pic.should eq @rp - end - context '関連テーブルオプションがないとき' do - it 'ライセンスと絵師を含んでいる' do - r = ResourcePicture.show_include_opt - r.should eq [:license, :artist] - end - end - context '関連テーブルオプションで原画を含ませたとき' do - it 'ライセンスと絵師と原画データを含んでいる' do - r = ResourcePicture.show_include_opt(:include => :original_picture) - r.should eq [:license, :artist, :original_picture] - end - end - context '存在しない素材を開こうとしたとき' do - it '404RecordNotFound例外を返す' do - lambda{ - pic = ResourcePicture.show 0 - }.should raise_error(ActiveRecord::RecordNotFound) - end - end - end - describe 'json単体出力オプションに於いて' do - it 'includeキーがライセンスと絵師を含んでいる' do - r = ResourcePicture.show_json_include_opt - r[:include].should eq [:license, :artist] - end - end + describe 'デフォルト値補充に於いて' do + it 'defined' do + @p = FactoryGirl.create :picture, :original_picture_id => @original_picture.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.build :resource_picture, :artist_id => @artist.id, :original_picture_id => @original_picture.id, :license_id => @license.id, :picture_id => @p.id + @rp.supply_default + end + end + + describe '上書き補充に於いて' do + before do + @original_picture.attributes = {:ext => 'gif', :width => 267, :height => 268, :filesize => 269, + :artist_id => @artist.id } + @rp = FactoryGirl.build :resource_picture, :original_picture_id => @original_picture.id + end + it 'width, height, ext, filesize, md5, original_picture_id, artist_idが設定されている' do + @rp.overwrite @original_picture + @rp.width.should eq 267 + @rp.height.should eq 268 + @rp.ext.should eq 'gif' + @rp.filesize.should eq 269 + @rp.md5.should eq @rp.md5 + @rp.original_picture_id.should eq @original_picture.id + @rp.artist_id.should eq @artist.id + end + end + + describe '所持判定に於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @original_picture.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.build :resource_picture, :artist_id => @artist.id, :original_picture_id => @original_picture.id, :license_id => @license.id, :picture_id => @p.id + end + it '素材を更新することはないので、Falseを返す' do + @rp.own?(@author).should == false + end + end + + describe '閲覧許可に於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @original_picture.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.build :resource_picture, :artist_id => @artist.id, :original_picture_id => @original_picture.id, :license_id => @license.id, :picture_id => @p.id + end + it '必ず許可となる' do + r = @rp.visible?(@author) + r.should == true + end + end + + describe 'ファイル名に於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @original_picture.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @original_picture.id, :license_id => @license.id, :picture_id => @p.id + end + it 'id+拡張子のフォーマットで返す' do + r = @rp.filename + r.should eq "#{@rp.id}.png" + end + end + + describe 'MimeTypeに於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @original_picture.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.build :resource_picture, :artist_id => @artist.id, :original_picture_id => @original_picture.id, :license_id => @license.id, :picture_id => @p.id + end + it 'image/拡張子のフォーマットで返す' do + r = @rp.mime_type + r.should eq "image/png" + end + end + + describe 'ファイルのurlに於いて' do + before do + @p = FactoryGirl.create :picture, :original_picture_id => @original_picture.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @original_picture.id, :license_id => @license.id, :picture_id => @p.id + ResourcePicture.any_instance.stub(:filename).and_return('3.gif') + end + it 'ファイル名取得を依頼している' do + ResourcePicture.any_instance.should_receive(:filename).exactly(1) + @rp.url + end + it '/resource_pictures/3.gifのフォーマットで返す' do + r = @rp.url + r.should eq "/resource_pictures/3.gif" + end + end + describe '一覧取得に於いて' do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id @@ -327,14 +328,14 @@ describe ResourcePicture do end end it 'リストを返す' do - pic = ResourcePicture.list - pic.should eq [@rp] + r = ResourcePicture.list + r.should eq [@rp] end it '時系列で並んでいる' do nop = FactoryGirl.create :original_picture, :artist_id => @artist.id nrp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => nop.id, :picture_id => @p.id, :updated_at => Time.now + 100 - pic = ResourcePicture.list - pic.should eq [nrp, @rp] + r = ResourcePicture.list + r.should eq [nrp, @rp] end context 'DBに5件あって1ページの件数を2件に変えたとして' do before do @@ -349,48 +350,168 @@ describe ResourcePicture do ResourcePicture.stub(:default_page_size).and_return(2) end it '通常は2件を返す' do - pic = ResourcePicture.list - pic.should have(2).items + r = ResourcePicture.list + r.should have(2).items end it 'page=1なら末尾2件を返す' do #時系列で並んでいる - pic = ResourcePicture.list({}, 1) - pic.should eq [@nrp5, @nrp4] + r = ResourcePicture.list(1) + r.should eq [@nrp5, @nrp4] end it 'page=2なら中間2件を返す' do - pic = ResourcePicture.list({}, 2) - pic.should eq [@nrp3, @nrp2] + r = ResourcePicture.list(2) + r.should eq [@nrp3, @nrp2] end it 'page=3なら先頭1件を返す' do - pic = ResourcePicture.list({}, 3) - pic.should eq [@rp] + r = ResourcePicture.list(3) + r.should eq [@rp] end end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + nop2 = FactoryGirl.create :original_picture, :artist_id => @artist.id + @nrp2 = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => nop2.id, :picture_id => @p.id, :updated_at => Time.now + 100 + nop3 = FactoryGirl.create :original_picture, :artist_id => @artist.id + @nrp3 = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => nop3.id, :picture_id => @p.id, :updated_at => Time.now + 200 + nop4 = FactoryGirl.create :original_picture, :artist_id => @artist.id + @nrp4 = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => nop4.id, :picture_id => @p.id, :updated_at => Time.now + 300 + nop5 = FactoryGirl.create :original_picture, :artist_id => @artist.id + @nrp5 = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => nop5.id, :picture_id => @p.id, :updated_at => Time.now + 400 + ResourcePicture.stub(:default_page_size).and_return(2) + end + it '件数0は全件(5件)を返す' do + r = ResourcePicture.list 5, 0 + r.should have(5).items + end + end + end + describe '一覧出力オプションに於いて' do + it 'includeキーを含んでいる' do + r = ResourcePicture.list_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = ResourcePicture.list_opt[:include] + r.should have(3).items + end + it 'ライセンスを含んでいる' do + r = ResourcePicture.list_opt[:include] + r.has_key?(:license).should be_true + end + it '絵師を含んでいる' do + r = ResourcePicture.list_opt[:include] + r.has_key?(:artist).should be_true + end + it '実素材を含んでいる' do + r = ResourcePicture.list_opt[:include] + r.has_key?(:picture).should be_true + end end describe 'json一覧出力オプションに於いて' do - it 'includeキーがライセンスと絵師を含んでいる' do - r = ResourcePicture.list_json_opt - r[:include].should eq [:license, :artist] - end + it 'includeキーを含んでいる' do + r = ResourcePicture.list_json_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = ResourcePicture.list_json_opt[:include] + r.should have(3).items + end + it 'ライセンスを含んでいる' do + r = ResourcePicture.list_json_opt[:include] + r.has_key?(:license).should be_true + end + it '絵師を含んでいる' do + r = ResourcePicture.list_json_opt[:include] + r.has_key?(:artist).should be_true + end + it '実素材を含んでいる' do + r = ResourcePicture.list_json_opt[:include] + r.has_key?(:picture).should be_true + end end - describe 'サイズの調整に於いて' do + describe '単体取得に於いて' do before do + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :original_picture_id => @op.id, :license_id => @license.id, :picture_id => @p.id end - - it 'サイズに収まるときはそのまま使う' do - ResourcePicture.fix_size_both(64, 64, 64, 64).should eq [64, 64] - end - it '小さくても拡大しない' do - ResourcePicture.fix_size_both(64, 64, 32, 32).should eq [32, 32] - end - it '縦長のときは縦に合わせて縮小' do - ResourcePicture.fix_size_both(64, 64, 64, 128).should eq [32, 64] - end - it '横長のときは横に合わせて縮小' do - ResourcePicture.fix_size_both(64, 64, 128, 64).should eq [64, 32] + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + ResourcePicture.stub(:show_opt).with(any_args).and_return({}) + ResourcePicture.should_receive(:show_opt).with(any_args).exactly(1) + r = ResourcePicture.show @rp.id, @author + end + it '閲覧許可を問い合わせている' do + ResourcePicture.any_instance.stub(:visible?).with(any_args).and_return(true) + ResourcePicture.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = ResourcePicture.show @rp.id, @author + end + end + it '指定の素材を返す' do + r = ResourcePicture.show @rp.id, @author + r.should eq @rp + end + context '他人の素材を開こうとしたとき' do + it '403Forbidden例外を返す' do + ResourcePicture.any_instance.stub(:visible?).and_return(false) + lambda{ + r = ResourcePicture.show @rp.id, @other_author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しない素材を開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + r = ResourcePicture.show 0, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end end end + describe '単体出力オプションに於いて' do + it 'includeキーを含んでいる' do + r = ResourcePicture.show_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = ResourcePicture.show_opt[:include] + r.should have(3).items + end + it 'ライセンスを含んでいる' do + r = ResourcePicture.show_opt[:include] + r.has_key?(:license).should be_true + end + it '絵師を含んでいる' do + r = ResourcePicture.show_opt[:include] + r.has_key?(:artist).should be_true + end + it '実素材を含んでいる' do + r = ResourcePicture.show_opt[:include] + r.has_key?(:picture).should be_true + end + end + describe 'json単体出力オプションに於いて' do + it 'includeキーを含んでいる' do + r = ResourcePicture.show_json_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = ResourcePicture.show_json_opt[:include] + r.should have(3).items + end + it 'ライセンスを含んでいる' do + r = ResourcePicture.show_json_opt[:include] + r.has_key?(:license).should be_true + end + it '絵師を含んでいる' do + r = ResourcePicture.show_json_opt[:include] + r.has_key?(:artist).should be_true + end + it '実素材を含んでいる' do + r = ResourcePicture.show_json_opt[:include] + r.has_key?(:picture).should be_true + end + end describe 'フォーマット変換対象判定に於いて' do before do @@ -418,112 +539,6 @@ describe ResourcePicture do end end - describe 'Gifフォーマット変換に於いて' do - before do - Magick::Image.stub(:from_blob).with(any_args).and_return([Mgk.new]) - end - context 'つつがなく終わるとき' do - it 'Mgkオブジェクトが返る' do - mgk = ResourcePicture.png_to_gif('mgkbin') - mgk.is_a?(Mgk).should be_true - end - it 'Mgkオブジェクトはgif変換されている' do - #スタブばかりで変換できないので代入されているかでチェックする - Mgk.any_instance.should_receive(:format=).with('gif').exactly(1) - ResourcePicture.png_to_gif('mgkbin') - end - end - context 'RMagick変換が失敗したとき' do - before do - Magick::Image.should_receive(:from_blob).with(any_args).and_raise('StandardError') - end - it 'falseを返す' do - res = ResourcePicture.png_to_gif('mgkbin') - res.should be_false - end - end - end - - describe '原画からのコピーデータセットに於いて' do - before do - @op = FactoryGirl.create :original_picture, :ext => 'jpeg', :width => 264, :height => 265, :filesize => 266, - :artist_id => @artist.id - @rp = FactoryGirl.build :resource_picture, - :artist_id => @artist.id - end - it '原画オブジェクトから属性を取り出して対象素材にセットしている' do - res = @rp.copy_data(@op) - @rp.ext.should eq 'jpeg' - @rp.width.should eq 264 - @rp.height.should eq 265 - @rp.filesize.should eq 266 - @rp.md5.should eq @op.md5 - @rp.artist_id.should eq @artist.id - end - end - - describe 'RMagick変換に於いて' do - before do - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id - attr = {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => 'tester', :credit => '{}', :settings => {}.to_json.to_s} - @rp = FactoryGirl.build :resource_picture, attr - end - context 'つつがなく終わるとき' do - it '画像データをオブジェクト化している' do - Magick::Image.stub(:from_blob).and_return(['mgkobj']) - @rp.data_to_mgk('mgkbin').should eq 'mgkobj' - end - end - context '失敗するとき' do - it 'Falseを返す' do - Magick::Image.should_receive(:from_blob).with(any_args).and_raise('StandardError') - @rp.data_to_mgk('mgkbin').should be_false - end - it '全体エラーがセットされている' do - Magick::Image.should_receive(:from_blob).with(any_args).and_raise('StandardError') - lambda { - @rp.data_to_mgk('mgkbin') - }.should change(@rp.errors[:base], :count) - end - end - end - describe '画像オブジェクトの取得に於いて' do - before do - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id - attr = {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => 'tester', :credit => '{}', :settings => {}.to_json.to_s} - @rp = FactoryGirl.build :resource_picture, attr - end - context '事前チェック' do - before do - OriginalPicture.any_instance.stub(:restore).with(any_args).and_return('data') - ResourcePicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(Mgk.new) - end - it '原画から画像データを取得している' do - OriginalPicture.any_instance.should_receive(:restore).with(any_args).exactly(1) - res = @rp.op_mgk - end - it '素材に原画データのRMagick変換を依頼している' do - ResourcePicture.any_instance.should_receive(:data_to_mgk).with(any_args).exactly(1) - res = @rp.op_mgk - end - end - context 'つつがなく終わるとき' do - #原画から画像データを取得する。 - #素材に原画データのRMagick変換を依頼し、画像オブジェクトを返す。 - before do - @mgk = Mgk.new - OriginalPicture.any_instance.stub(:restore).with(any_args).and_return('data') - ResourcePicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(@mgk) - end - it '画像オブジェクトを返す' do - res = @rp.op_mgk - res.should eq @mgk - end - end - end - describe '新規実素材の取得に於いて' do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id @@ -531,35 +546,43 @@ describe ResourcePicture do attr = {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => 'tester', :credit => '{}', :settings => {:reverse => 1, :gif_convert => 1}.to_json.to_s} @rp = FactoryGirl.build :resource_picture, attr - @mgk = Mgk.new + @imager = ImagerTest.load "abc\ndef\nghi" end context '事前チェック' do before do - Picture.any_instance.stub(:copy_data).with(any_args).and_return(true) Picture.any_instance.stub(:store).with(any_args).and_return(true) end - it '実素材に原画からのコピーデータを依頼している' do - Picture.any_instance.should_receive(:copy_data).with(any_args).exactly(1) - res = @rp.new_picture @mgk + it '実素材モデルにデフォルト値補充を依頼している' do + Picture.any_instance.should_receive(:supply_default).with(any_args).exactly(1) + r = @rp.new_picture @imager + end + it '実素材モデルに上書き補充を依頼している' do + Picture.any_instance.should_receive(:overwrite).with(any_args).exactly(1) + r = @rp.new_picture @imager end it '実素材を保存している' do Picture.any_instance.should_receive(:store).with(any_args).exactly(1) - res = @rp.new_picture @mgk + r = @rp.new_picture @imager end end context 'つつがなく終わるとき' do - it '実素材に原画からのコピーデータをセットしている' do - res = @rp.new_picture @mgk - @rp.ext.should eq @op.ext - @rp.width.should eq @op.width - @rp.height.should eq @op.height - @rp.filesize.should eq @op.filesize - @rp.artist_id.should eq @op.artist_id - @rp.original_picture_id.should eq @op.id + it '保存された実素材を返す' do + r = @rp.new_picture @imager + r.is_a?(Picture).should be_true end - it '実素材を返す' do - res = @rp.new_picture @mgk - res.is_a?(Picture).should be_true + end + #以下から例外ケース。処理先頭から失敗させていく + context '実素材の保存に失敗したとき' do + before do + Picture.any_instance.stub(:store).with(any_args).and_return(false) + end + it 'Falseを返す' do + r = @rp.new_picture @imager + r.should be_false + end + it '自身の全体エラーメッセージにその旨をセットしている' do + r = @rp.new_picture @imager + @rp.errors[:base].should_not be_empty end end end @@ -568,235 +591,231 @@ describe ResourcePicture do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id - attr = {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => 'tester', :classname => 'StandardLicense', :credit => '{}', :settings => {}.to_json.to_s} + attr = {:original_picture_id => @op.id, :picture_id => nil, :license_id => @license.id, :artist_name => 'tester', :classname => 'StandardLicense', :credit => '{}', :settings => {}.to_json.to_s} @rp = FactoryGirl.build :resource_picture, attr + @imager = ImagerTest.load "abc\ndef\nghi" end context '事前チェック' do before do #すべての処理が正常パターンで通過すれば、一番深い分岐まで通る。 #それで外部のメソッド呼び出しだけに着目してテストする。 - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 - ResourcePicture.any_instance.stub(:op_mgk).with(any_args).and_return(@mgk) ResourcePicture.any_instance.stub(:new_picture).with(any_args).and_return(@p) ResourcePicture.any_instance.stub(:store_picture_with_gif).with(any_args).and_return(true) end - it '素材に原画からのコピーデータをセットしている' do - ResourcePicture.any_instance.stub(:copy_data).with(any_args).and_return(true) - ResourcePicture.any_instance.should_receive(:copy_data).with(any_args).exactly(1) - res = @rp.store - end - it '画像オブジェクトの取得を依頼している' do - ResourcePicture.any_instance.should_receive(:op_mgk).with(any_args).exactly(1) - res = @rp.store - end it '新規実素材の取得を依頼している' do ResourcePicture.any_instance.should_receive(:new_picture).with(any_args).exactly(1) - res = @rp.store + r = @rp.store @imager end it '自身を保存している' do ResourcePicture.any_instance.should_receive(:save).with(any_args).exactly(1) - res = @rp.store + r = @rp.store @imager end - it '画像ファイルの作成・更新機能で画像を保存している' do - ResourcePicture.any_instance.should_receive(:store_picture_with_gif).with(@mgk).exactly(1) - res = @rp.store + it 'gif付き画像ファイルの作成・更新機能で画像を保存している' do + ResourcePicture.any_instance.should_receive(:store_picture_with_gif).with(@imager).exactly(1) + r = @rp.store @imager end end context 'つつがなく終わるとき' do before do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 - ResourcePicture.any_instance.stub(:op_mgk).with(any_args).and_return(@mgk) ResourcePicture.any_instance.stub(:new_picture).with(any_args).and_return(@p) - ResourcePicture.any_instance.stub(:store_picture_with_gif).with(any_args).and_return(true) + ResourcePicture.any_instance.stub(:store_picture_with_gif).with(@imager).and_return(true) end it 'Trueを返す' do - res = @rp.store - res.should be_true - end - it '実素材idをセットしている' do - res = @rp.store - @rp.picture_id.should_not be_nil + r = @rp.store @imager + r.should be_true end it '実素材idから最新画像idを取得してセットしている' do - res = @rp.store + r = @rp.store @imager @rp.picture_id.should eq @p.id end it '自身が保存されている' do lambda { - res = @rp.store + r = @rp.store @imager }.should change ResourcePicture, :count end end #以下から例外ケース。処理先頭から失敗させていく context '画像オブジェクトの取得に失敗したとき' do before do - ResourcePicture.any_instance.stub(:op_mgk).with(any_args).and_return(false) + @imager = false end it 'Falseを返す' do - res = @rp.store - res.should be_false + r = @rp.store @imager + r.should be_false end it '更新されていない' do - @rp.store + r = @rp.store @imager @rp.should be_a_new ResourcePicture end + it '処理を中断してロールバックする' do + lambda { + r = @rp.store @imager + }.should_not change Picture, :count + end end context '新規実素材の取得に失敗したとき' do before do - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 - ResourcePicture.any_instance.stub(:op_mgk).with(any_args).and_return(@mgk) - ResourcePicture.any_instance.stub(:new_picture).with(any_args).and_return(@p) - Picture.any_instance.stub(:valid?).with(any_args).and_return(false) + ResourcePicture.any_instance.stub(:new_picture).with(any_args).and_return(false) end it 'Falseを返す' do - res = @rp.store - res.should be_false + r = @rp.store @imager + r.should be_false end it '更新されていない' do - @rp.store + r = @rp.store @imager @rp.should be_a_new ResourcePicture end + it '処理を中断してロールバックする' do + lambda { + r = @rp.store @imager + }.should_not change Picture, :count + end end context '自身の保存に失敗したとき' do before do - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 - ResourcePicture.any_instance.stub(:op_mgk).with(any_args).and_return(@mgk) ResourcePicture.any_instance.stub(:new_picture).with(any_args).and_return(@p) ResourcePicture.any_instance.stub(:save).with(any_args).and_return(false) end it 'Falseを返す' do - res = @rp.store - res.should be_false + r = @rp.store @imager + r.should be_false end it '更新されていない' do - @rp.store + r = @rp.store @imager @rp.should be_a_new ResourcePicture end it '処理を中断してロールバックする' do lambda { - res = @rp.store + r = @rp.store @imager + }.should_not change Picture, :count + end + end + context 'gif付き画像ファイルの作成・更新機能に失敗したとき' do + before do + ResourcePicture.any_instance.stub(:new_picture).with(any_args).and_return(@p) + ResourcePicture.any_instance.stub(:store_picture_with_gif).with(any_args).and_return(false) + end + it 'Falseを返す' do + r = @rp.store @imager + r.should be_false + end + it '更新されていない' do + r = @rp.store @imager + @rp.should be_a_new ResourcePicture + end + it '処理を中断してロールバックする' do + lambda { + r = @rp.store @imager }.should_not change Picture, :count end end end - describe '画像ファイルの作成・更新に於いて' do + describe 'gif付き画像ファイルの作成・更新に於いて' do before do @op = FactoryGirl.create :original_picture, :artist_id => @artist.id @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id attr = {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => 'tester', :credit => '{}', :settings => {}.to_json.to_s} @rp = FactoryGirl.build :resource_picture, attr + @imager = ImagerTest.load "abc\ndef\nghi" end context '事前チェック' do before do #すべての処理が正常パターンで通過すれば、一番深い分岐まで通る。 #それで外部のメソッド呼び出しだけに着目してテストする。 - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 ResourcePicture.any_instance.stub(:store_picture).with(any_args).and_return(true) ResourcePicture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - class GifMgk < Mgk ; end #store_pictureは二回呼び出される。区別をつけるために - @gifmgk = GifMgk.new #パラメータを二種類用意する。 - ResourcePicture.stub(:png_to_gif).with(any_args).and_return(@gifmgk) + ResourcePicture.any_instance.stub(:filename).with(any_args).and_return('1.png') + ResourcePicture.any_instance.stub(:gifname).with(any_args).and_return('1.gif') end it '画像ファイルの作成・更新機能で画像を保存している' do - ResourcePicture.any_instance.stub(:filename).with(any_args).and_return('1.png') - ResourcePicture.any_instance.should_receive(:store_picture).with(@mgk, '1.png').exactly(1) - res = @rp.store_picture_with_gif @mgk + #二回目の保存はgif変換の結果を渡す。 + ResourcePicture.any_instance.should_receive(:store_picture).with(any_args).exactly(2) + r = @rp.store_picture_with_gif @imager end it '自身にフォーマット変換対象かを問い合わせている' do ResourcePicture.any_instance.should_receive(:to_gif?).with(any_args).exactly(1) - res = @rp.store_picture_with_gif @mgk + r = @rp.store_picture_with_gif @imager end - it '自身にGifフォーマット変換を依頼している' do - ResourcePicture.should_receive(:png_to_gif).with(any_args).exactly(1) - res = @rp.store_picture_with_gif @mgk - end - it '画像ファイルの作成・更新機能でgif画像を保存している' do - #二回目の保存はgif変換の結果を渡す。 - ResourcePicture.any_instance.stub(:gifname).with(any_args).and_return('1.gif') - ResourcePicture.any_instance.should_receive(:store_picture).with(@gifmgk, '1.gif').exactly(1) - res = @rp.store_picture_with_gif @mgk + it '画像ライブラリにGifフォーマット変換を依頼している' do + ImagerTest.any_instance.should_receive(:to_gif).with(any_args).exactly(1) + r = @rp.store_picture_with_gif @imager end end context 'つつがなく終わるとき' do before do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 ResourcePicture.any_instance.stub(:store_picture).with(any_args).and_return(true) ResourcePicture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - class GifMgk < Mgk ; end #store_pictureは二回呼び出される。区別をつけるために - @gifmgk = GifMgk.new #パラメータを二種類用意する。 - ResourcePicture.stub(:png_to_gif).with(any_args).and_return(@gifmgk) + ResourcePicture.any_instance.stub(:filename).with(any_args).and_return('1.png') + ResourcePicture.any_instance.stub(:gifname).with(any_args).and_return('1.gif') end it 'Trueを返す' do - res = @rp.store_picture_with_gif @mgk - res.should be_true + r = @rp.store_picture_with_gif @imager + r.should be_true end end context 'gif変換なしで、つつがなく終わるとき' do before do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 ResourcePicture.any_instance.stub(:store_picture).with(any_args).and_return(true) ResourcePicture.any_instance.stub(:to_gif?).with(any_args).and_return(false) + ResourcePicture.any_instance.stub(:filename).with(any_args).and_return('1.png') + ResourcePicture.any_instance.stub(:gifname).with(any_args).and_return('1.gif') end it 'Trueを返す' do - res = @rp.store_picture_with_gif @mgk - res.should be_true + r = @rp.store_picture_with_gif @imager + r.should be_true end it 'gif保存は呼ばれていない' do ResourcePicture.any_instance.should_receive(:store_picture).with(any_args).exactly(1) - res = @rp.store_picture_with_gif @mgk + r = @rp.store_picture_with_gif @imager end end #以下から例外ケース。処理先頭から失敗させていく context '画像の保存に失敗したとき' do before do - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 ResourcePicture.any_instance.stub(:store_picture).with(any_args).and_return(false) end it 'Falseを返す' do - res = @rp.store_picture_with_gif @mgk - res.should be_false + r = @rp.store_picture_with_gif @imager + r.should be_false end it 'gif変換判定は呼ばれていない' do ResourcePicture.any_instance.should_not_receive(:to_gif?).with(any_args) - res = @rp.store_picture_with_gif @mgk + r = @rp.store_picture_with_gif @imager end end context 'gif変換に失敗したとき' do before do - @mgk = Mgk.new #一回目の本画像保存は与えたオブジェクトを使って保存する。 ResourcePicture.any_instance.stub(:store_picture).with(any_args).and_return(true) ResourcePicture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - ResourcePicture.stub(:png_to_gif).with(any_args).and_return(false) + ImagerTest.any_instance.stub(:to_gif).with(any_args).and_return(false) end it 'Falseを返す' do - res = @rp.store_picture_with_gif @mgk - res.should be_false + r = @rp.store_picture_with_gif @imager + r.should be_false end it 'gif画像の保存は呼ばれていない' do #本画像の保存があるので、一度は呼ばれる ResourcePicture.any_instance.should_receive(:store_picture).with(any_args).exactly(1) - res = @rp.store_picture_with_gif @mgk + r = @rp.store_picture_with_gif @imager end end context 'gif画像の保存に失敗したとき' do before do + ResourcePicture.any_instance.stub(:store_picture).with(@imager, '1.png').and_return(true) + ResourcePicture.any_instance.stub(:to_gif?).with(any_args).and_return(true) + @gifimager = @imager.to_gif + ImagerTest.any_instance.stub(:to_gif).with(any_args).and_return(@gifimager) + ResourcePicture.any_instance.stub(:store_picture).with(@gifimager, '1.gif').and_return(false) ResourcePicture.any_instance.stub(:filename).with(any_args).and_return('1.png') ResourcePicture.any_instance.stub(:gifname).with(any_args).and_return('1.gif') - @mgk = Mgk.new - ResourcePicture.any_instance.stub(:store_picture).with(@mgk, '1.png').and_return(true) - ResourcePicture.any_instance.stub(:to_gif?).with(any_args).and_return(true) - class GifMgk < Mgk ; end #store_pictureは二回呼び出される。区別をつけるために - @gifmgk = GifMgk.new #パラメータを二種類用意する。 - ResourcePicture.stub(:png_to_gif).with(any_args).and_return(@gifmgk) - ResourcePicture.any_instance.stub(:store_picture).with(@gifmgk, '1.gif').and_return(false) end it 'Falseを返す' do - res = @rp.store_picture_with_gif @mgk - res.should be_false + r = @rp.store_picture_with_gif @imager + r.should be_false end end end @@ -808,30 +827,30 @@ describe ResourcePicture do @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id attr = {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => 'tester', :credit => '{}', :settings => {}.to_json.to_s} @rp = FactoryGirl.build :resource_picture, attr - @rp.copy_data @op + @rp.overwrite @op + @imager = ImagerTest.load "abc\ndef\nghi" end context '事前チェック' do before do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 PictureIO.resource_picture_io.stub(:put).with(any_args).and_return(true) ResourcePicture.any_instance.stub(:flag_thumbnail).with(any_args).and_return(1) - ResourcePicture.any_instance.stub(:thumbnail).with(any_args).and_return('tmbdata') end it 'サムネイル化が1回呼ばれる' do - ResourcePicture.any_instance.should_receive(:thumbnail).with(any_args).exactly(1) - res = @rp.store_picture(Mgk.new, '1.gif') + ImagerTest.any_instance.should_receive(:to_thumbnail).with(any_args).exactly(1) + r = @rp.store_picture(@imager, '1.png') end it '画像ファイルの保存が2回呼ばれる' do PictureIO.resource_picture_io.should_receive(:put).with(any_args).exactly(2) - res = @rp.store_picture(Mgk.new, '1.gif') + r = @rp.store_picture(@imager, '1.gif') end it '画像ファイルのベースへのサムネイル保存が1回呼ばれる' do - PictureIO.resource_picture_io.should_receive(:put).with('tmbdata', '1.gif').exactly(1) - res = @rp.store_picture(Mgk.new, '1.gif') + PictureIO.resource_picture_io.should_receive(:put).with(@imager.to_thumbnail.binary, '1.gif').exactly(1) + r = @rp.store_picture(@imager, '1.gif') end it '画像ファイルのfullへの保存が1回呼ばれる' do - PictureIO.resource_picture_io.should_receive(:put).with('data', '1.gif', 'full').exactly(1) - res = @rp.store_picture(Mgk.new, '1.gif') + PictureIO.resource_picture_io.should_receive(:put).with(@imager.binary, '1.gif', 'full').exactly(1) + r = @rp.store_picture(@imager, '1.gif') end end context 'つつがなく終わるとき' do @@ -839,44 +858,57 @@ describe ResourcePicture do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 PictureIO.resource_picture_io.stub(:put).with(any_args).and_return(true) ResourcePicture.any_instance.stub(:flag_thumbnail).with(any_args).and_return(1) - ResourcePicture.any_instance.stub(:thumbnail).with(any_args).and_return('tmbdata') end it 'Trueを返す' do - res = @rp.store_picture(Mgk.new, '1.gif') - res.should be_true + r = @rp.store_picture(@imager, '1.gif') + r.should be_true end end - context '例外ケース' do + #以下から例外ケース。処理先頭から失敗させていく + context 'サムネイル化に失敗したとき' do before do ResourcePicture.any_instance.stub(:flag_thumbnail).with(any_args).and_return(1) - ResourcePicture.any_instance.stub(:thumbnail).with(any_args).and_return('tmbdata') - PictureIO.resource_picture_io.stub(:put).with(any_args).and_return(false) + ImagerTest.any_instance.stub(:to_thumbnail).with(any_args).and_return(false) end - it '画像の保存に失敗したならFalseを返す' do - res = @rp.store_picture(Mgk.new, '1.gif') - res.should be_false + it 'Falseを返す' do + r = @rp.store_picture(@imager, '1.gif') + r.should be_false + end + it '画像ファイルの保存は呼ばれていない' do + PictureIO.resource_picture_io.should_not_receive(:put).with(any_args) + r = @rp.store_picture(@imager, '1.gif') end end - - end - - describe 'サムネイル変換に於いて' do - #サムネイル化した画像データを返すが、スタブをおくので、リサイズと画像データ化を試みるかをチェックする - before do - ResourcePicture.stub(:resize).with(any_args).and_return(Mgk.new) - @op = FactoryGirl.create :original_picture, :artist_id => @artist.id - @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id - attr = {:original_picture_id => @op.id, :license_id => @license.id, :artist_name => 'tester', :credit => '{}', :settings => {}.to_json.to_s} - @rp = FactoryGirl.build :resource_picture, attr - end - it 'サムネイルサイズに縮小した画像データを返す' do - ResourcePicture.should_receive(:resize).with(any_args).exactly(1) - @rp.thumbnail(Mgk.new) + context 'サムネイル画像の保存に失敗したとき' do + before do + ResourcePicture.any_instance.stub(:flag_thumbnail).with(any_args).and_return(1) + @tmbimager = @imager.to_thumbnail + ImagerTest.any_instance.stub(:to_thumbnail).with(any_args).and_return(@tmbimager) + PictureIO.resource_picture_io.stub(:put).with(@tmbimager.binary, '1.gif').and_return(false) + end + it 'Falseを返す' do + r = @rp.store_picture(@imager, '1.gif') + r.should be_false + end + it '画像ファイルの保存は呼ばれていない' do + PictureIO.resource_picture_io.should_receive(:put).with(any_args).exactly(1) + r = @rp.store_picture(@imager, '1.gif') + end end - it 'データが返る' do - #全体スタブより - @rp.thumbnail(Mgk.new).should eq 'data' + context '画像の保存に失敗したとき' do + before do + ResourcePicture.any_instance.stub(:flag_thumbnail).with(any_args).and_return(1) + @tmbimager = @imager.to_thumbnail + ImagerTest.any_instance.stub(:to_thumbnail).with(any_args).and_return(@tmbimager) + PictureIO.resource_picture_io.stub(:put).with(@tmbimager.binary, '1.gif').and_return(true) + PictureIO.resource_picture_io.stub(:put).with(@imager.binary, '1.gif', 'full').and_return(false) + end + it 'Falseを返す' do + r = @rp.store_picture(@imager, '1.gif') + r.should be_false + end end + end describe 'クレジットデータに於いて' do diff --git a/spec/models/speech_balloon_template_spec.rb b/spec/models/speech_balloon_template_spec.rb index c4788007..18b4352a 100644 --- a/spec/models/speech_balloon_template_spec.rb +++ b/spec/models/speech_balloon_template_spec.rb @@ -15,25 +15,40 @@ describe SpeechBalloonTemplate do @jes = JSON.parse @tes @admin = FactoryGirl.create :admin + @user = FactoryGirl.create( :user_yas) + @author = @user.author + @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @other_user = FactoryGirl.create( :user_yas) + @other_author = @other_user.author + @other_artist = FactoryGirl.create :artist_yas, :author_id => @other_author.id end describe '検証に於いて' do before do - end - - it 'オーソドックスなデータなら通る' do @st = FactoryGirl.build :speech_balloon_template - @st.should be_valid end - context 'nameを検証するとき' do - before do - @st = FactoryGirl.build :speech_balloon_template + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @st.name = 'a' + @st.classname = 'a' + @st.caption = 'a' + @st.t = 0 + @st.settings = '{}' + @st.should be_valid end - it 'テストデータの確認' do - @st.name = 'abcdefghi0abcdefghi0abcdefghi0abcdefghi0abcdefghi0' + it '上限データが通る' do + @st.name = 'a'*50 + @st.classname = 'a'*50 + @st.caption = 'a'*30 + @st.t = 99999 + @st.settings = '{' + 'a'*99999 + '}' @st.should be_valid end + end + + + context 'nameを検証するとき' do it 'nullなら失敗する' do @st.name = '' @st.should_not be_valid @@ -44,13 +59,6 @@ describe SpeechBalloonTemplate do end end context 'classnameを検証するとき' do - before do - @st = FactoryGirl.build :speech_balloon_template - end - it 'テストデータの確認' do - @st.classname = 'abcdefghi0abcdefghi0abcdefghi0abcdefghi0abcdefghi0' - @st.should be_valid - end it 'nullなら失敗する' do @st.classname = '' @st.should_not be_valid @@ -61,13 +69,6 @@ describe SpeechBalloonTemplate do end end context 'captionを検証するとき' do - before do - @st = FactoryGirl.build :speech_balloon_template - end - it 'テストデータの確認' do - @st.caption = 'abcdefghi0abcdefghi0abcdefghi0' - @st.should be_valid - end it 'nullなら失敗する' do @st.caption = '' @st.should_not be_valid @@ -78,13 +79,6 @@ describe SpeechBalloonTemplate do end end context 'tを検証するとき' do - before do - @st = FactoryGirl.build :speech_balloon_template - end - it 'テストデータの確認' do - @st.t = 0 - @st.should be_valid - end it 'nullなら失敗する' do @st.t = nil @st.should_not be_valid @@ -99,13 +93,6 @@ describe SpeechBalloonTemplate do end end context 'settingsを検証するとき' do - before do - @st = FactoryGirl.build :speech_balloon_template - end - it 'テストデータの確認' do - @st.settings = '{}' - @st.should be_valid - end it 'nullなら失敗する' do @st.settings = nil @st.should_not be_valid @@ -113,377 +100,246 @@ describe SpeechBalloonTemplate do end end - describe 'データ補充に於いて' do - before do + describe 'デフォルト値補充に於いて' do + it 'defined' do + @st = FactoryGirl.build :speech_balloon_template + @st.supply_default end - end - describe 'Json解析に於いて' do + describe '上書き補充に於いて' do before do + @st = FactoryGirl.build :speech_balloon_template end - context 'テキストを渡されたとき' do - it 'Json解析している' do - JSON.should_receive(:parse).with(@t).exactly(1) - r = SpeechBalloonTemplate.parse @t - end - it 'Hashで返す' do - r = SpeechBalloonTemplate.parse @t - r.is_a?(Hash).should be_true - end + it 'テーブルが空のときは0を返す' do + @st.overwrite + @st.t.should eq 0 end - context 'パース失敗したとき' do - it 'Falseを返す' do - JSON.should_receive(:parse).with(any_args).and_raise('StandardError') - r = SpeechBalloonTemplate.parse @t - r.should be_false - end + it 'テーブルが1行あるときは1を返す' do + FactoryGirl.create :speech_balloon_template + @st.overwrite + @st.t.should eq 1 + end + it 'テーブルが2行あるときは2を返す' do + FactoryGirl.create :speech_balloon_template + FactoryGirl.create :speech_balloon_template, :name => "5", :t => 1 + @st.overwrite + @st.t.should eq 2 end end - describe 'システム画像置換に於いて' do + describe '閲覧許可に於いて' do before do - @sp = FactoryGirl.create :system_picture - @sp2 = FactoryGirl.create :system_picture @st = FactoryGirl.build :speech_balloon_template - @hash = {"classname" => 'sore', "caption" => 'store test', - "templates" => { - "one" => {"balloon" => {"system_picture" => 'BASE64'}} - } - } - @hashs = {"classname" => 'sore2', "caption" => 'store test2', - "templates" => { - "one" => {"balloon" => {"system_picture" => 'DUAL'}}, - "two" => {"balloon" => {"system_picture" => 'BASE64ENC'}} - } - } - end - context '事前チェック' do - it 'システム画像に保存を依頼している' do - SystemPicture.stub(:store).with(any_args).and_return(@sp) - SystemPicture.should_receive(:store).exactly(1) - r = @st.pic_rehash @hash - end - end - context 'つつがなく終わるとき' do - before do - SystemPicture.stub(:store).with(any_args).and_return(@sp) - end - it 'システム画像のidを作成している' do - r = @st.pic_rehash @hash - @hash["templates"]["one"]["balloon"].has_key?("system_picture_id").should be_true - @hash["templates"]["one"]["balloon"]["system_picture_id"].should eq @sp.id - end - it 'システム画像のテキストデータを削除している' do - r = @st.pic_rehash @hash - @hash["templates"]["one"]["balloon"].has_key?("system_picture").should_not be_true - end - it 'trueを返す' do - r = @st.pic_rehash @hash - r.should be_true - end - end - context 'システム画像の作成に失敗したとき' do - before do - SystemPicture.stub(:store).with(any_args).and_return(false) - end - it 'Falseを返す' do - r = @st.pic_rehash @hash - r.should be_false - end - end - context '複数のとき' do - before do - SystemPicture.stub(:store).with(any_args).and_return(@sp) - end - it 'システム画像のidを作成している' do - r = @st.pic_rehash @hashs - @hashs["templates"]["one"]["balloon"].has_key?("system_picture_id").should be_true - @hashs["templates"]["one"]["balloon"]["system_picture_id"].should eq @sp.id - @hashs["templates"]["two"]["balloon"].has_key?("system_picture_id").should be_true - @hashs["templates"]["two"]["balloon"]["system_picture_id"].should eq @sp.id - end - it 'システム画像のテキストデータを削除している' do - r = @st.pic_rehash @hashs - @hashs["templates"]["one"]["balloon"].has_key?("system_picture").should_not be_true - @hashs["templates"]["two"]["balloon"].has_key?("system_picture").should_not be_true - end - end - context '例外データのとき' do - it 'templatesがなくても何ごともなく続行する' do - r = @st.pic_rehash({}) - r.should be_true - end - it 'templatesが空でも何ごともなく続行する' do - r = @st.pic_rehash( {"templates" => nil}) - r.should be_true - end - it 'balloonがなくても何ごともなく続行する' do - r = @st.pic_rehash({"templates" => { - "one" => {} - }}) - r.should be_true - end - it 'balloonが空でも何ごともなく続行する' do - r = @st.pic_rehash({"templates" => { - "one" => {"balloon" => nil} - }}) - r.should be_true - end - it 'system_pictureがなくても何ごともなく続行する' do - r = @st.pic_rehash({"templates" => { - "one" => {"balloon" => {}} - }}) - r.should be_true - end end + it '許可する' do + @st.visible?(@author).should == true + end end - describe 'フキダシテンプレート保存に於いて' do + describe '一覧取得に於いて' do before do - @st = FactoryGirl.build :speech_balloon_template - @hash = {"classname" => 'sore', "caption" => 'store test'} + @st = FactoryGirl.create :speech_balloon_template end - context '事前チェック' do - it 'システム画像置換を依頼している' do - SpeechBalloonTemplate.any_instance.stub(:pic_rehash).with(@hash).and_return(true) - SpeechBalloonTemplate.any_instance.should_receive(:pic_rehash).exactly(1) - r = @st.store @hash - end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + SpeechBalloonTemplate.stub(:list_opt).with(any_args).and_return({}) + SpeechBalloonTemplate.should_receive(:list_opt).with(any_args).exactly(1) + r = SpeechBalloonTemplate.list + end + end + it 'リストを返す' do + l = SpeechBalloonTemplate.list + l.should eq [@st] + end + it 't順で並んでいる' do + @st2 = FactoryGirl.create :speech_balloon_template, :name => "5", :t => 1 + l = SpeechBalloonTemplate.list + l.should eq [@st, @st2] end - context 'つつがなく終わるとき' do - before do - SpeechBalloonTemplate.any_instance.stub(:pic_rehash).with(@hash).and_return(true) - end - it 'hashから取り出したclassnameをセットしている' do - @st.store @hash - @st.classname.should eq @hash["classname"] - end - it 'hashから取り出したcaptionをセットしている' do - @st.store @hash - @st.caption.should eq @hash["caption"] - end - it 'hashをテキスト化してsettingsにセットしている' do - @st.store @hash - @st.settings.should eq @hash.to_s - end - it 'フキダシテンプレートが作成されている' do - lambda { - @st.store @hash - }.should change SpeechBalloonTemplate, :count - end - end - context 'システム画像置換が失敗したとき' do - before do - SpeechBalloonTemplate.any_instance.stub(:pic_rehash).with(@hash).and_return(false) - end - it 'Falseを返す' do - r = @st.store @hash - r.should be_false - end + end + describe '一覧取得オプションに於いて' do + it '空のHashを返す' do + r = SpeechBalloonTemplate.list_opt + r.is_a?(Hash).should be_true + r.should be_empty end - context '保存が失敗したとき' do - before do - SpeechBalloonTemplate.any_instance.stub(:pic_rehash).with(@hash).and_return(true) - SpeechBalloonTemplate.any_instance.stub(:save).with(any_args).and_return(false) - end - it 'Falseを返す' do - r = @st.store @hash - r.should be_false - end + end + describe 'json一覧出力オプションに於いて' do + it '空のHashを返す' do + r = SpeechBalloonTemplate.list_json_opt + r.is_a?(Hash).should be_true + r.should be_empty end end - describe 'フキダシテンプレート更新に於いて' do + describe '単体取得に於いて' do before do @st = FactoryGirl.create :speech_balloon_template - @hash = {} end - context 'つつがなく終わるとき' do - it '保存依頼している' do - SpeechBalloonTemplate.any_instance.stub(:store).with(@hash).and_return(true) - SpeechBalloonTemplate.should_receive(:store).exactly(1) - SpeechBalloonTemplate.store @st.name, @hash - end - context '新規のとき' do - #新規作成をチェックしたいが、楽するために(storeが保存しないことを利用して)新規オブジェクト生成かでテスト - it 'フキダシテンプレートは新規オブジェクトである' do - SpeechBalloonTemplate.any_instance.stub(:store).with(@hash).and_return(true) - r = SpeechBalloonTemplate.store :newsbtname, @hash - r.should be_a_new SpeechBalloonTemplate - end - end - context '更新のとき' do - it '名前が一致するテンプレを返す' do - SpeechBalloonTemplate.any_instance.stub(:store).with(@hash).and_return(true) - r = SpeechBalloonTemplate.store @st.name, @hash - r.name.should eq @st.name - r.should_not be_a_new SpeechBalloonTemplate - end - end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + SpeechBalloonTemplate.stub(:show_opt).with(any_args).and_return({}) + SpeechBalloonTemplate.should_receive(:show_opt).with(any_args).exactly(1) + r = SpeechBalloonTemplate.show @st.id, @author + end + end + it '指定のフキダシテンプレートを返す' do + l = SpeechBalloonTemplate.show @st.id, @author + l.should eq @st + end + context '他人のフキダシテンプレートを開こうとしたとき' do + it '403Forbidden例外を返す' do + SpeechBalloonTemplate.any_instance.stub(:visible?).and_return(false) + lambda{ + r = SpeechBalloonTemplate.show @st.id, @other_author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないフキダシテンプレートを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + SpeechBalloonTemplate.show 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + describe '単体出力オプションに於いて' do + it '空のHashを返す' do + r = SpeechBalloonTemplate.show_opt + r.is_a?(Hash).should be_true + r.should be_empty end - context 'フキダシテンプレートの作成に失敗するとき' do - before do - SpeechBalloonTemplate.any_instance.stub(:store).with(any_args).and_return(false) - end - #成功失敗に関わらずオブジェクトを返すのでテストのやりようがない - + end + describe 'json単体出力オプションに於いて' do + it '空のHashを返す' do + r = SpeechBalloonTemplate.show_json_opt + r.is_a?(Hash).should be_true + r.should be_empty end end - describe 'テキスト取り込みに於いて' do - #成功でTrue、パース失敗でFalse、失敗は保存エラーのモデルを配列で返す + describe '拡張データ補充に於いて' do + #置換まわりが破壊的でテストしにくいので、外部と連携したテストが多い。 + #特にシステム画像データはidを直接記述して置換させないようにテストしている。 before do + @sp = FactoryGirl.create :system_picture + @st = FactoryGirl.build :speech_balloon_template + @templates = { + "one" => {"balloon" => {"system_picture" => 'BASE64'}} + } + @sp_replaced_templates = { + "one" => {"balloon" => {"system_picture_id" => @sp.id}} + } + @attr = {"classname" => 'store', "caption" => 'store test', + "templates" => @templates + } + @sp_replaced_attr = {"classname" => 'store', "caption" => 'store test', + "templates" => @sp_replaced_templates + } end - context 'つつがなく終わるとき' do - it 'Json解析を依頼する' do - SpeechBalloonTemplate.should_receive(:parse).with(any_args).exactly(1) - SpeechBalloonTemplate.stub(:parse).with(any_args).and_return(@j) - SpeechBalloonTemplate.import(@t) - end - it 'フキダシテンプレート更新を一回依頼する' do - SpeechBalloonTemplate.stub(:store).with(any_args).and_return(SpeechBalloonTemplate.new) - SpeechBalloonTemplate.any_instance.stub(:valid?).with(any_args).and_return(true) - SpeechBalloonTemplate.should_receive(:store).with(any_args).exactly(1) - SpeechBalloonTemplate.import(@t) - end - it 'フキダシテンプレートが追加される' do - lambda { - SpeechBalloonTemplate.import(@t) - }.should change SpeechBalloonTemplate, :count - end - it '[]を返す' do - SpeechBalloonTemplate.import(@t).should eq [] + context '事前チェック' do + it 'システム画像置換に依頼して、テキストの画像データをシステム画像idに置換している' do + SpeechBalloonTemplate.stub(:replace_system_picture).with(any_args).and_return(true) + SpeechBalloonTemplate.should_receive(:replace_system_picture).exactly(1) + r = SpeechBalloonTemplate.templates_json_from @attr end end - context '複数データがつつがなく終わるとき' do - it 'フキダシテンプレート更新を二回依頼する' do - SpeechBalloonTemplate.stub(:store).with(any_args).and_return(SpeechBalloonTemplate.new) - SpeechBalloonTemplate.any_instance.stub(:valid?).with(any_args).and_return(true) - SpeechBalloonTemplate.should_receive(:store).with(any_args).exactly(2) - SpeechBalloonTemplate.import(@ts) - end - it 'フキダシテンプレートが二個追加される' do - lambda { - SpeechBalloonTemplate.import(@ts) - }.should change(SpeechBalloonTemplate, :count).by 2 + context 'つつがなく終わるとき' do + before do end - it '[]を返す' do - SpeechBalloonTemplate.import(@ts).should eq [] + it 'templates以下をjsonテキスト化して返す' do + r = SpeechBalloonTemplate.templates_json_from @sp_replaced_attr + r.should eq @sp_replaced_templates.to_json.to_s end end - #例外ケース - context 'Json解析に失敗したとき' do + context 'システム画像の作成に失敗したとき' do before do - SpeechBalloonTemplate.stub(:parse).with(any_args).and_return(false) - end - it 'フキダシテンプレートの数に変化がない' do - lambda { - SpeechBalloonTemplate.import(@t) - }.should_not change SpeechBalloonTemplate, :count + SpeechBalloonTemplate.stub(:replace_system_picture).with(any_args).and_return(false) end - it 'Falseを返す' do - SpeechBalloonTemplate.import(@t).should be_false + it 'nilを返す' do + r = SpeechBalloonTemplate.templates_json_from @attr + r.should be_nil end end - context 'フキダシテンプレート作成に失敗したとき' do + context 'カラム値にtemplatesがないとき' do before do - SpeechBalloonTemplate.any_instance.stub(:save).with(any_args).and_return(false) - SpeechBalloonTemplate.any_instance.stub(:valid?).with(any_args).and_return(false) - end - it 'フキダシテンプレートの数に変化がない' do - lambda { - SpeechBalloonTemplate.import(@t) - }.should_not change SpeechBalloonTemplate, :count - end - it '配列を返す' do - r = SpeechBalloonTemplate.import(@t) - r.is_a?(Array).should be_true - end - it '配列の中身は一件' do - r = SpeechBalloonTemplate.import(@t) - r.should have(1).items + @attr.delete "templates" + SpeechBalloonTemplate.stub(:replace_system_picture).with(any_args).and_return(true) end - it 'フキダシテンプレートオブジェクトが入っている' do - r = SpeechBalloonTemplate.import(@t) - r.first.is_a?(SpeechBalloonTemplate).should be_true + it '{}をjsonテキスト化して返す' do + r = SpeechBalloonTemplate.templates_json_from @attr + r.should eq '{}' end end - context '複数のフキダシテンプレート作成に失敗したとき' do - #三件中、二件の失敗、一件を成功させ、成功データは戻り値に含まないことを確認する - it 'フキダシテンプレートの数に変化がない' do - lambda { - SpeechBalloonTemplate.import(@tes) - }.should_not change SpeechBalloonTemplate, :count - end - it '途中で保存に失敗しても全件更新依頼する' do - SpeechBalloonTemplate.stub(:store).with(any_args).and_return(SpeechBalloonTemplate.new) - SpeechBalloonTemplate.should_receive(:store).with(any_args).exactly(3) - SpeechBalloonTemplate.import(@tes) - end - it '配列を返す' do - r = SpeechBalloonTemplate.import(@tes) - r.is_a?(Array).should be_true - end - it '配列の中身は2件' do - r = SpeechBalloonTemplate.import(@tes) - r.should have(2).items + context 'templateにballoonがないとき' do + before do + @templates = { + "one" => {} + } + @attr = {"classname" => 'store', "caption" => 'store test', + "templates" => @templates + } end - it '配列の中身は失敗したフキダシテンプレートオブジェクトが入っている' do - r = SpeechBalloonTemplate.import(@tes) - r[0].is_a?(SpeechBalloonTemplate).should be_true - r[0]["name"].should eq 'squareR@pettan.com' - r[1].is_a?(SpeechBalloonTemplate).should be_true - r[1]["name"].should eq 'squareRR@pettan.com' + it 'templates以下をjsonテキスト化してを返す' do + r = SpeechBalloonTemplate.templates_json_from @attr + r.should eq @templates.to_json.to_s end end end - describe 'インポートエラーの表示に於いて' do - end - - describe 'ファイル取り込みに於いて' do + describe '更新に於いて' do + #置換まわりが破壊的でテストしにくいので、外部と連携したテストが多い。 + #特にシステム画像データはidを直接記述して置換させないようにテストしている。 before do - SpeechBalloonTemplate.stub(:import).with(any_args).and_return(true) + @sp = FactoryGirl.create :system_picture + @st = FactoryGirl.create :speech_balloon_template + @templates = { + "one" => {"balloon" => {"system_picture_id" => @sp.id}} + } + @attr = {"classname" => 'store', "caption" => 'store test', + "templates" => @templates + } end - context 'つつがなく終わるとき' do + context '事前チェック' do before do - SpeechBalloonTemplate.stub(:import).with(any_args).and_return(true) - end - it 'ファイルを開いてテキストを読む' do - File.should_receive(:open).with(@f, 'r').exactly(1) - SpeechBalloonTemplate.import_file(@f) - end - it 'テキスト取り込みを依頼する' do - SpeechBalloonTemplate.should_receive(:import).with(any_args).exactly(1) - SpeechBalloonTemplate.import_file(@f) + SpeechBalloonTemplate.stub(:templates_json_from).with(any_args).and_return('{}') + SpeechBalloonTemplate.stub(:modify_object).with(any_args).and_return(@st) + SpeechBalloonTemplate.any_instance.stub(:overwrite).with(any_args).and_return(true) + SpeechBalloonTemplate.any_instance.stub(:save).with(any_args).and_return(true) end - #テキスト取り込み成功でTrueが返る - it 'Trueを返す' do - SpeechBalloonTemplate.import_file(@f).should be_true + it 'テンプレート拡張データ置換に問い合わせている' do + SpeechBalloonTemplate.should_receive(:templates_json_from).exactly(1) + r = SpeechBalloonTemplate.store 'circle_v01', @attr end - end - context 'ファイルが開けないとき' do - before do - File.stub(:open).with(any_args).and_raise('StandardError') + it 'インポート処理のデータ更新準備に依頼している' do + SpeechBalloonTemplate.should_receive(:modify_object).exactly(1) + r = SpeechBalloonTemplate.store 'circle_v01', @attr end - it 'ファイルエラーのメッセージを出力する' do - pending + it '上書き補充を依頼している' do + SpeechBalloonTemplate.any_instance.should_receive(:overwrite).exactly(1) + r = SpeechBalloonTemplate.store 'circle_v01', @attr end - it 'Falseを返す' do - SpeechBalloonTemplate.import_file(@f).should be_false + it 'オブジェクトを保存している' do + SpeechBalloonTemplate.any_instance.should_receive(:save).exactly(1) + r = SpeechBalloonTemplate.store 'circle_v01', @attr end end - #失敗したときは、失敗したフキダシテンプレートが配列で返る - context 'テキスト取り込みが失敗したとき' do + context 'つつがなく終わるとき' do before do - SpeechBalloonTemplate.stub(:import).with(any_args).and_return(false) end - it '各フキダシテンプレートのエラーメッセージを出力する' do - pending + it 'カラム値のsettingsをセットしている' do + r = SpeechBalloonTemplate.store 'circle_v01', @attr + r.settings.should eq @templates.to_json.to_s + end + it 'モデルが作成されている' do + lambda { + r = SpeechBalloonTemplate.store 'circle_v01', @attr + }.should change SpeechBalloonTemplate, :count end - it 'Falseを返す' do - SpeechBalloonTemplate.import_file(@f).should be_false + it 'オブジェクトを返している' do + r = SpeechBalloonTemplate.store 'circle_v01', @attr + r.is_a?(SpeechBalloonTemplate).should be_true end end end diff --git a/spec/models/story_spec.rb b/spec/models/story_spec.rb index 4301a689..bdda0156 100644 --- a/spec/models/story_spec.rb +++ b/spec/models/story_spec.rb @@ -21,15 +21,18 @@ describe Story do @story = FactoryGirl.build :story, :comic_id => @comic.id, :panel_id => @panel.id, :author_id => @author.id end - it 'オーソドックスなデータなら通る' do - @story.should be_valid + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @story.t = 0 + @story.should be_valid + end + it '上限データが通る' do + @story.t = 99999 + @story.should be_valid + end end context 'comic_idを検証するとき' do - it 'テストデータの確認' do - @story.comic_id = @comic.id - @story.should be_valid - end it 'nullなら失敗する' do @story.comic_id = nil @story.should_not be_valid @@ -45,10 +48,6 @@ describe Story do end context 'panel_idを検証するとき' do - it 'テストデータの確認' do - @story.panel_id = @panel.id - @story.should be_valid - end it 'nullなら失敗する' do @story.panel_id = nil @story.should_not be_valid @@ -64,12 +63,6 @@ describe Story do end context 'tを検証するとき' do - before do - end - it 'テストデータの確認' do - @story.t = 0 - @story.should be_valid - end it 'nullなら失敗する' do @story.t = nil @story.should_not be_valid @@ -85,10 +78,6 @@ describe Story do end context 'author_idを検証するとき' do - it 'テストデータの確認' do - @story.author_id = @author.id - @story.should be_valid - end it 'nullなら失敗する' do @story.author_id = nil @story.should_not be_valid @@ -103,9 +92,6 @@ describe Story do end end context '全体を検証するとき' do - before do - @story = FactoryGirl.create :story, :author_id => @author.id - end end end @@ -141,7 +127,7 @@ describe Story do end - describe '作者判定に於いて' do + describe '所持判定に於いて' do before do @comic = FactoryGirl.create :comic, :author_id => @author.id @panel = FactoryGirl.create :panel, :author_id => @author.id @@ -156,43 +142,15 @@ describe Story do it '他人のストーリーならno' do @storyo.own?(@author).should == false end - it '作家が不明ならno' do - @story.own?(nil).should == false - end - end - describe '編集取得に於いて' do - before do - @comic = FactoryGirl.create :comic, :author_id => @author.id - @panel = FactoryGirl.create :panel, :author_id => @author.id - @story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id - end - it '指定のストーリーを返す' do - l = Story.edit @story.id, @author - l.should eq @story - end - context '他人のストーリーを開こうとしたとき' do - it '403Forbidden例外を返す' do - Story.any_instance.stub(:own?).and_return(false) - lambda{ - Story.edit @story.id, @author - }.should raise_error(ActiveRecord::Forbidden) - end - end - context '存在しないストーリーを開こうとしたとき' do - it '404RecordNotFound例外を返す' do - lambda{ - Story.edit 110, @author - }.should raise_error(ActiveRecord::RecordNotFound) - end - end end - describe '一覧取得に於いて' do before do @comic = FactoryGirl.create :comic, :author_id => @author.id @panel = FactoryGirl.create :panel, :author_id => @author.id @story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id @panel2 = FactoryGirl.create :panel, :author_id => @author.id, :publish => 0 + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id, :visible => 1 + @other_panel = FactoryGirl.create :panel, :author_id => @other_author.id, :publish => 1 end context 'offset補正について' do it '文字列から数値に変換される' do @@ -241,6 +199,7 @@ describe Story do c.should eq [@story] end it 't順で並んでいる' do + #公開コミックの公開コマは(他人のコミックであっても)含んでいる v = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 1 c = Story.list @comic, @author c.should eq [ @story, v] @@ -391,10 +350,19 @@ describe Story do describe '自分のストーリー一覧取得に於いて' do before do - @comic = FactoryGirl.create :comic, :author_id => @author.id - @panel = FactoryGirl.create :panel, :author_id => @author.id + @comic = FactoryGirl.create :comic, :author_id => @author.id, :visible => 0 + @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 0 @story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id - end + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id, :visible => 1 + @other_panel = FactoryGirl.create :panel, :author_id => @other_author.id, :publish => 1 + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Story.stub(:list_opt).with(any_args).and_return({}) + Story.should_receive(:list_opt).with(any_args).exactly(1) + r = Story.mylist @author + end + end it 'リストを返す' do s = Story.mylist @author s.should eq [@story] @@ -404,13 +372,209 @@ describe Story do sl = Story.mylist @author sl.should eq [ns, @story] end - it '他人のストーリーは含まない' do - cc = FactoryGirl.create :comic, :author_id => @other_author.id - pl = FactoryGirl.create :panel, :author_id => @other_author.id - so = FactoryGirl.create :story, :author_id => @other_author.id, :comic_id => cc.id, :panel_id => pl.id + it '他人のストーリーはコマコミックともに公開でも含まない' do + so = FactoryGirl.create :story, :author_id => @other_author.id, :comic_id => @other_comic.id, :panel_id => @other_panel.id sl = Story.mylist @author sl.should eq [@story] end + it '自分のストーリーはコマコミックともには非公開でも含んでいる' do + nc = FactoryGirl.create :comic, :author_id => @author.id, :visible => 0, :updated_at => Time.now + 100 + cl = Comic.mylist @author + cl.should eq [nc, @story] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 1, :updated_at => Time.now + 100 + @story3 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 2, :updated_at => Time.now + 200 + @story4 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 3, :updated_at => Time.now + 300 + @story5 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 4, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + c = Story.mylist @author, 1, 2 + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Story.mylist(@author, 1, 2) + c.should eq [@story5, @story4] + end + it 'page=2なら中間2件を返す' do + c = Story.mylist(@author, 2, 2) + c.should eq [@story3, @story2] + end + it 'page=3なら先頭1件を返す' do + c = Story.mylist(@author, 3, 2) + c.should eq [@story] + end + end + context 'DBに5件あって1ページの件数を0件に変えたとして' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 1, :updated_at => Time.now + 100 + @story3 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 2, :updated_at => Time.now + 200 + @story4 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 3, :updated_at => Time.now + 300 + @story5 = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id, :t => 4, :updated_at => Time.now + 400 + end + it '通常は全件(5件)を返す' do + r = Story.mylist @author, 5, 0 + r.should have(5).items + end + end + end + + describe '編集取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :panel_id => @panel.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + Story.stub(:show_opt).with(any_args).and_return({}) + Story.should_receive(:show_opt).with(any_args).exactly(1) + r = Story.edit @story.id, @author + end + it '所持判定を問い合わせている' do + Story.any_instance.stub(:own?).with(any_args).and_return(true) + Story.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = Story.edit @story.id, @author + end + end + it '指定のストーリーを返す' do + l = Story.edit @story.id, @author + l.should eq @story + end + context '他人のストーリーを開こうとしたとき' do + it '403Forbidden例外を返す' do + Story.any_instance.stub(:own?).and_return(false) + lambda{ + Story.edit @story.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないストーリーを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + Story.edit 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '単体取得オプションに於いて' do + it 'includeキーを含んでいる' do + r = Story.show_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = Story.show_opt[:include] + r.should have(3).items + end + it 'コミックを含んでいる' do + r = Story.show_opt[:include] + r.has_key?(:comic).should be_true + end + it 'コミックは作家を含んでいる' do + r = Story.show_opt[:include] + r[:comic].has_key?(:author).should be_true + end + it '作家を含んでいる' do + r = Story.show_opt[:include] + r.has_key?(:author).should be_true + end + it 'コマを含んでいる' do + r = Story.show_opt[:include] + r.has_key?(:panel).should be_true + end + it 'コマは作家を含んでいる' do + r = Story.show_opt[:include] + r[:panel].has_key?(:author).should be_true + end + it 'コマはコマ絵を含んでいる' do + r = Story.show_opt[:include] + r[:panel].has_key?(:panel_pictures).should be_true + end + it 'コマ絵は実素材を含んでいる' do + r = Story.show_opt[:include] + r[:panel][:panel_pictures].has_key?(:picture).should be_true + end + it '実素材は絵師を含んでいる' do + r = Story.show_opt[:include] + r[:panel][:panel_pictures][:picture].has_key?(:artist).should be_true + end + it '実素材はライセンスを含んでいる' do + r = Story.show_opt[:include] + r[:panel][:panel_pictures][:picture].has_key?(:license).should be_true + end + it 'コマはフキダシを含んでいる' do + r = Story.show_opt[:include] + r[:panel].has_key?(:speech_balloons).should be_true + end + it 'フキダシはフキダシ枠を含んでいる' do + r = Story.show_opt[:include] + r[:panel][:speech_balloons].has_key?(:balloons).should be_true + end + it 'フキダシはセリフを含んでいる' do + r = Story.show_opt[:include] + r[:panel][:speech_balloons].has_key?(:speeches).should be_true + end + end + describe 'json単体取得オプションに於いて' do + it 'includeキーを含んでいる' do + r = Story.show_json_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = Story.show_json_opt[:include] + r.should have(3).items + end + it 'コミックを含んでいる' do + r = Story.show_json_opt[:include] + r.has_key?(:comic).should be_true + end + it 'コミックは作家を含んでいる' do + r = Story.show_json_opt[:include] + r[:comic].has_key?(:author).should be_true + end + it '作家を含んでいる' do + r = Story.show_json_opt[:include] + r.has_key?(:author).should be_true + end + it 'コマを含んでいる' do + r = Story.show_json_opt[:include] + r.has_key?(:panel).should be_true + end + it 'コマは作家を含んでいる' do + r = Story.show_json_opt[:include] + r[:panel].has_key?(:author).should be_true + end + it 'コマはコマ絵を含んでいる' do + r = Story.show_json_opt[:include] + r[:panel].has_key?(:panel_pictures).should be_true + end + it 'コマ絵は実素材を含んでいる' do + r = Story.show_json_opt[:include] + r[:panel][:panel_pictures].has_key?(:picture).should be_true + end + it '実素材は絵師を含んでいる' do + r = Story.show_json_opt[:include] + r[:panel][:panel_pictures][:picture].has_key?(:artist).should be_true + end + it '実素材はライセンスを含んでいる' do + r = Story.show_json_opt[:include] + r[:panel][:panel_pictures][:picture].has_key?(:license).should be_true + end + it 'コマはフキダシを含んでいる' do + r = Story.show_json_opt[:include] + r[:panel].has_key?(:speech_balloons).should be_true + end + it 'フキダシはフキダシ枠を含んでいる' do + r = Story.show_json_opt[:include] + r[:panel][:speech_balloons].has_key?(:balloons).should be_true + end + it 'フキダシはセリフを含んでいる' do + r = Story.show_json_opt[:include] + r[:panel][:speech_balloons].has_key?(:speeches).should be_true + end end describe 't補充値に於いて' do diff --git a/spec/models/system_picture_spec.rb b/spec/models/system_picture_spec.rb index ead28463..41523ba4 100644 --- a/spec/models/system_picture_spec.rb +++ b/spec/models/system_picture_spec.rb @@ -8,21 +8,29 @@ describe SystemPicture do describe '検証に於いて' do before do - end - - it 'オーソドックスなデータなら通る' do @sp = FactoryGirl.build :system_picture - @sp.should be_valid end - context 'extを検証するとき' do - before do - @sp = FactoryGirl.build :system_picture + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @sp.ext = 'png' #リストにない拡張子は通らないし + @sp.width = 1 + @sp.height = 1 + @sp.filesize = 1 + @sp.md5 = 'a'*32 + @sp.should be_valid end - it 'テストデータの確認' do + it '上限データが通る' do @sp.ext = 'jpeg' + @sp.width = 99999 + @sp.height = 99999 + @sp.filesize = 2000000 + @sp.md5 = 'a'*32 @sp.should be_valid end + end + + context 'extを検証するとき' do it 'nullなら失敗する' do @sp.ext = '' @sp.should_not be_valid @@ -37,13 +45,6 @@ describe SystemPicture do end end context 'widthを検証するとき' do - before do - @sp = FactoryGirl.build :system_picture - end - it 'テストデータの確認' do - @sp.width = 1 - @sp.should be_valid - end it 'nullなら失敗する' do @sp.width = nil @sp.should_not be_valid @@ -62,13 +63,6 @@ describe SystemPicture do end end context 'heightを検証するとき' do - before do - @sp = FactoryGirl.build :system_picture - end - it 'テストデータの確認' do - @sp.height = 1 - @sp.should be_valid - end it 'nullなら失敗する' do @sp.height = nil @sp.should_not be_valid @@ -87,13 +81,6 @@ describe SystemPicture do end end context 'filesizeを検証するとき' do - before do - @sp = FactoryGirl.build :system_picture - end - it 'テストデータの確認' do - @sp.filesize = 1 - @sp.should be_valid - end it 'nullなら失敗する' do @sp.filesize = nil @sp.should_not be_valid @@ -112,119 +99,320 @@ describe SystemPicture do end end context 'md5を検証するとき' do - before do - @sp = FactoryGirl.build :system_picture - end - it 'テストデータの確認' do - @sp.md5 = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - @sp.should be_valid - end it 'nullなら失敗する' do @sp.md5 = '' @sp.should_not be_valid end - it '32文字以上なら失敗する' do + it '31文字なら失敗する' do + @sp.md5 = 'a'*31 + @sp.should_not be_valid + end + it '33文字なら失敗する' do @sp.md5 = 'a'*33 @sp.should_not be_valid end end end - describe 'データ補充に於いて' do + describe 'デフォルト値補充に於いて' do + it 'defined' do + @sp = FactoryGirl.build :system_picture + @sp.supply_default + end + end + + describe '上書き補充に於いて' do + it 'defined' do + @sp = FactoryGirl.build :system_picture + @sp.overwrite + end + end + + describe '所持判定に於いて' do before do + @sp = FactoryGirl.build :system_picture + end + it '管理者のアクセス権はすべて等しいので、Trueを返す' do + @sp.own?(@admin).should == true + end + end + + describe '閲覧許可に於いて' do + before do + @sp = FactoryGirl.build :system_picture + end + it '必ず許可となる' do + r = @sp.visible?(@admin) + r.should == true + end + end + + describe 'ファイル名に於いて' do + before do + @sp = FactoryGirl.create :system_picture + end + it 'id+拡張子のフォーマットで返す' do + r = @sp.filename + r.should eq "#{@sp.id}.png" + end + end + + describe 'MimeTypeに於いて' do + before do + @sp = FactoryGirl.create :system_picture + end + it 'image/拡張子のフォーマットで返す' do + r = @sp.mime_type + r.should eq "image/png" + end + end + + describe 'ファイルのurlに於いて' do + before do + @sp = FactoryGirl.create :system_picture + SystemPicture.any_instance.stub(:filename).and_return('3.gif') + end + it 'ファイル名取得を依頼している' do + SystemPicture.any_instance.should_receive(:filename).exactly(1) + @sp.url + end + it '/original_pictures/3.gifのフォーマットで返す' do + r = @sp.url + r.should eq "/system_pictures/3.gif" + end + end + + describe '一覧取得に於いて' do + before do + @sp = FactoryGirl.create :system_picture + end + context 'page補正について' do + it '文字列から数値に変換される' do + SystemPicture.page('8').should eq 8 + end + it 'nilの場合は1になる' do + SystemPicture.page().should eq 1 + end + it '0以下の場合は1になる' do + SystemPicture.page('0').should eq 1 + end + end + context 'page_size補正について' do + it '文字列から数値に変換される' do + SystemPicture.page_size('7').should eq 7 + end + it 'nilの場合はSystemPicture.default_page_sizeになる' do + SystemPicture.page_size().should eq SystemPicture.default_page_size + end + it '0以下の場合はSystemPicture.default_page_sizeになる' do + SystemPicture.page_size('0').should eq SystemPicture.default_page_size + end + it 'SystemPicture.max_page_sizeを超えた場合はSystemPicture.max_page_sizeになる' do + SystemPicture.page_size('1000').should eq SystemPicture.max_page_size + end + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + SystemPicture.stub(:list_opt).with(any_args).and_return({}) + SystemPicture.should_receive(:list_opt).with(any_args).exactly(1) + r = SystemPicture.list + end + end + it 'リストを返す' do + r = SystemPicture.list + r.should eq [@sp] + end + it '時系列で並んでいる' do + ni = FactoryGirl.create :system_picture, :updated_at => Time.now + 100 + r = SystemPicture.list + r.should eq [ni, @sp] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @sp2 = FactoryGirl.create :system_picture, :updated_at => Time.now + 100 + @sp3 = FactoryGirl.create :system_picture, :updated_at => Time.now + 200 + @sp4 = FactoryGirl.create :system_picture, :updated_at => Time.now + 300 + @sp5 = FactoryGirl.create :system_picture, :updated_at => Time.now + 400 + SystemPicture.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + r = SystemPicture.list + r.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + r = SystemPicture.list 1, 2 + r.should eq [@sp5, @sp4] + end + it 'page=2なら中間2件を返す' do + r = SystemPicture.list 2, 2 + r.should eq [@sp3, @sp2] + end + it 'page=3なら先頭1件を返す' do + r = SystemPicture.list 3, 2 + r.should eq [@sp] + end + end + context 'DBに5件あって1ページの件数を0件に変えたとして' do + before do + @sp2 = FactoryGirl.create :system_picture, :updated_at => Time.now + 100 + @sp3 = FactoryGirl.create :system_picture, :updated_at => Time.now + 200 + @sp4 = FactoryGirl.create :system_picture, :updated_at => Time.now + 300 + @sp5 = FactoryGirl.create :system_picture, :updated_at => Time.now + 400 + SystemPicture.stub(:default_page_size).and_return(2) + end + it '件数0は全件(5件)を返す' do + r = SystemPicture.list 5, 0 + r.should have(5).items + end + end + end + describe '一覧出力オプションに於いて' do + it 'Hashを返す' do + r = SystemPicture.list_opt + r.is_a?(Hash).should be_true + end + it '0の項目を含んでいる' do + r = SystemPicture.list_opt + r.should be_empty + end + end + describe 'json一覧出力オプションに於いて' do + it 'Hashを返す' do + r = SystemPicture.list_json_opt + r.is_a?(Hash).should be_true + end + it '0の項目を含んでいる' do + r = SystemPicture.list_json_opt + r.should be_empty + end + end + + describe '単体取得に於いて' do + before do + @sp = FactoryGirl.create :system_picture + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + SystemPicture.stub(:show_opt).with(any_args).and_return({}) + SystemPicture.should_receive(:show_opt).with(any_args).exactly(1) + r = SystemPicture.show @sp.id, @admin + end + it '閲覧許可を問い合わせている' do + SystemPicture.any_instance.stub(:visible?).with(any_args).and_return(true) + SystemPicture.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = SystemPicture.show @sp.id, @admin + end + end + it '指定のシステム画像を返す' do + r = SystemPicture.show @sp.id, @admin + r.should eq @sp + end + context '他人のシステム画像を開こうとしたとき' do + it '403Forbidden例外を返す' do + SystemPicture.any_instance.stub(:visible?).and_return(false) + lambda{ + r = SystemPicture.show @sp.id, @admin + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないシステム画像を開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + r = SystemPicture.show 0, @admin + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + describe '単体出力オプションに於いて' do + it 'Hashを返す' do + r = SystemPicture.show_opt + r.is_a?(Hash).should be_true + end + it '0の項目を含んでいる' do + r = SystemPicture.show_opt + r.should be_empty + end + end + describe 'json単体出力オプションに於いて' do + it 'Hashを返す' do + r = SystemPicture.show_json_opt + r.is_a?(Hash).should be_true + end + it '0の項目を含んでいる' do + r = SystemPicture.show_json_opt + r.should be_empty end - end describe '作成・更新に於いて' do before do @sp = FactoryGirl.build :system_picture - #RMagickのスタブをおいておく - class Mgk ; class Image ; end ; end - @filesize = 76543 - Mgk::Image.stub(:from_blob).with(any_args).and_return([Mgk.new]) - Mgk.any_instance.stub(:format).with(any_args).and_return('png') - Mgk.any_instance.stub(:rows).with(any_args).and_return(200) - Mgk.any_instance.stub(:columns).with(any_args).and_return(100) - Mgk.any_instance.stub(:filesize).with(any_args).and_return(@filesize) - Mgk.any_instance.stub(:to_blob).with(any_args).and_return('data') + @imager = ImagerTest.load "abc\ndef\nghi" end context '事前チェック' do before do #すべての処理が正常パターンで通過すれば、一番深い分岐まで通る。 #それで外部のメソッド呼び出しだけに着目してテストする。 - SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(Mgk.new) SystemPicture.any_instance.stub(:save).with(any_args).and_return(true) - PictureIO::LocalPicture.any_instance.stub(:put).with(any_args).and_return(true) - end - it 'RMagick変換を依頼している' do - SystemPicture.any_instance.should_receive(:data_to_mgk).exactly(1) - @sp.store 'bindata' - end - it '自身に属性をセットしている' do - SystemPicture.any_instance.should_receive(:attributes=).exactly(1) - @sp.store 'bindata' + PictureIO.system_picture_io.stub(:put).with(any_args).and_return(true) end it '自身が保存されている' do SystemPicture.any_instance.should_receive(:save).exactly(1) - @sp.store 'bindata' + r = @sp.store @imager end it 'PictureIoに画像データの保存を依頼している' do - PictureIO::LocalPicture.any_instance.should_receive(:put).with(any_args).exactly(1) - @sp.store 'bindata' + PictureIO.system_picture_io.should_receive(:put).with(any_args).exactly(1) + r = @sp.store @imager end end context 'つつがなく終わるとき' do before do #すべての処理を正常パターンで通過させ、保存機能をチェックする。 - SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(Mgk.new) -# SystemPicture.any_instance.stub(:save).with(any_args).and_return(true) - PictureIO::LocalPicture.any_instance.stub(:put).with(any_args).and_return(true) - end - it '自身に属性をセットしている' do - lambda { - @sp.store 'bindata' - }.should change @sp, :filesize + PictureIO.system_picture_io.stub(:put).with(any_args).and_return(true) end it 'システム画像モデルが作成されている' do lambda { - @sp.store 'bindata' + r = @sp.store @imager }.should change SystemPicture, :count end - it 'システム画像が保存されている' do - @sp.store 'bindata' - SystemPicture.find(@sp).should_not be_nil - end it 'Trueを返す' do - @sp.store('bindata').should eq true + r = @sp.store @imager + r.should eq true end end #以下から例外ケース。処理先頭から失敗させていく - context 'RMagick変換が失敗したとき' do + context 'imagerが初期化に失敗したとき' do before do - SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(false) end it 'falseを返す' do - @sp.store('bindata').should be_false + @sp.store(false).should be_false end it '自身の保存は呼ばれていない' do SystemPicture.any_instance.should_not_receive(:save) + @sp.store(false) + end + it '全体エラーメッセージがセットされている' do + lambda { + @sp.store(false) + }.should change(@sp.errors[:base], :count) end end context '自身の保存に失敗したとき' do before do - SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(Mgk.new) SystemPicture.any_instance.stub(:save).with(any_args).and_return(false) end it 'falseを返す' do - @sp.store('bindata').should be_false + r = @sp.store @imager + r.should be_false end it '更新されていない' do - @sp.store('bindata') + r = @sp.store @imager @sp.should be_a_new SystemPicture end it '原画の保存は呼ばれていない' do - PictureIO::LocalPicture.any_instance.should_not_receive(:put) + PictureIO.system_picture_io.should_not_receive(:put) + r = @sp.store @imager end end end @@ -232,50 +420,47 @@ describe SystemPicture do describe '置換に於いて' do before do @sp = FactoryGirl.create :system_picture + @imager = ImagerTest.load "abc\ndef\nghi" end - context '新規のとき' do + context '事前チェック' do before do - SystemPicture.stub(:find_by_md5).with(any_args).and_return(nil) - SystemPicture.any_instance.stub(:store).with(any_args).and_return(true) + #すべての処理が正常パターンで通過すれば、一番深い分岐まで通る。 + #それで外部のメソッド呼び出しだけに着目してテストする。 + SystemPicture.stub(:modify_object).with(any_args).and_return(@sp) + SystemPicture.any_instance.stub(:store).with(@imager).and_return(true) end - it '新規オブジェクト生成している' do - r = SystemPicture.store 'bindata' - r.should be_a_new SystemPicture + it 'データ更新準備を依頼する' do + SystemPicture.should_receive(:modify_object).with(any_args).exactly(1) + r = SystemPicture.store @imager end it '作成依頼している' do - SystemPicture.any_instance.should_receive(:store).with('bindata').exactly(1) - SystemPicture.store 'bindata' - end - it '保存された行を返す' do - r = SystemPicture.store 'bindata' - r.should_not eq @sp + SystemPicture.any_instance.should_receive(:store).with(@imager).exactly(1) + r = SystemPicture.store @imager end end - context '既存のとき' do + context 'つつがなく終わるとき' do before do - SystemPicture.stub(:find_by_md5).with(any_args).and_return(@sp) SystemPicture.any_instance.stub(:store).with(any_args).and_return(true) end - it '新規オブジェクト生成していない' do - SystemPicture.should_receive(:new).with(any_args).exactly(0) - SystemPicture.store 'bindata' - end - it '作成依頼している' do - SystemPicture.any_instance.should_receive(:store).with('bindata').exactly(1) - SystemPicture.store 'bindata' + it '自身に属性をセットしている' do + r = SystemPicture.store @imager + r.width.should eq @imager.width + r.height.should eq @imager.height + r.ext.should eq @imager.ext + r.filesize.should eq @imager.filesize + r.md5.should eq @imager.md5 end - it '保存された行を返す' do - r = SystemPicture.store 'bindata' - r.should eq @sp + it 'オブジェクトを返す' do + r = SystemPicture.store @imager + r.is_a?(SystemPicture).should eq true end end context '保存失敗のとき' do before do - SystemPicture.stub(:find_by_md5).with(any_args).and_return(@sp) SystemPicture.any_instance.stub(:store).with(any_args).and_return(false) end it 'nilを返す' do - r = SystemPicture.store 'bindata' + r = SystemPicture.store @imager r.should eq nil end end diff --git a/spec/support/imager_test.rb b/spec/support/imager_test.rb new file mode 100644 index 00000000..f4231a7b --- /dev/null +++ b/spec/support/imager_test.rb @@ -0,0 +1,136 @@ +#画像処理 +require 'digest/md5' +require 'RMagick' +class ImagerTest + @@tmb_w = 50 + @@tmb_h = 50 + + def self.tmb_w + @@tmb_w + end + + def self.tmb_w=(v) + @@tmb_w = v + end + + def self.tmb_h + @@tmb_h + end + + def self.tmb_h=(v) + @@tmb_h = v + end + + def initialize bindata + @binary = bindata + @lib = bindata.split /\n/ + @ext= 'png' + end + + def self.load bindata + r = nil + begin + r = ImagerTest.new bindata + rescue + r = false + end + r + end + + def binary + @binary + end + + def lib + @lib + end + + def width + @lib.first.size + end + + def height + @lib.size + end + + def filesize + @lib.join.size + end + + def ext + @ext + end + + def md5 + 'A'*32 + end + + def v + @lib.map {|r| r.reverse}.join("\n") + end + + def h + @lib.reverse.join("\n") + end + + def vh + @lib.reverse.map {|r| r.reverse}.join("\n") + end + + def to_gif + @ext = 'gif' + ImagerTest.load @lib.map {|r| r.upcase}.join("\n") + end + + def to_thumbnail + ImagerTest.load('i') + end + + def thumbnail_size + ImagerTest.fix_size_both ImagerTest.tmb_w, ImagerTest.tmb_h, self.width, self.height + end + + #ただサイズ計算したいとき + def self.thumbnail_size w, h + ImagerTest.fix_size_both ImagerTest.tmb_w, ImagerTest.tmb_h, w, h + end + + #サイズの調整(limw,limhに必ず収まるように合わせる) + def self.fix_size_both(limw, limh, w, h) + wr = if w > limw + limw*100/w + else + 100 + end + hr = if h > limh + limh*100/h + else + 100 + end + res = if wr < hr + #幅の方が圧縮率が高い + [w*wr/100, h*wr/100] + else + #高さの方が圧縮率が高い + [w*hr/100, h*hr/100] + end + res + end + +end + +=begin +i = ImagerTest.load "abc\ndef\nghi" +p i.binary +p i.lib +p i.width +p i.height +p i.filesize +p i.ext +p i.md5 +p i.v +p i.h +p i.vh +p i.to_gif +p i.to_thumbnail +=end diff --git a/vendor/plugins/pettan_importer/lib/pettan_importer.rb b/vendor/plugins/pettan_importer/lib/pettan_importer.rb index f28ce1ee..7131dfd4 100644 --- a/vendor/plugins/pettan_importer/lib/pettan_importer.rb +++ b/vendor/plugins/pettan_importer/lib/pettan_importer.rb @@ -19,7 +19,9 @@ module ActiveRecord def replace_system_picture attr d = attr["system_picture"] return nil if d.blank? - sp = SystemPicture.store Base64.decode64(d.to_s) + imager = PettanImager.load(Base64.decode64(d.to_s)) + return nil unless imager + sp = SystemPicture.store(imager) return false unless sp attr["system_picture_id"] = sp.id attr.delete "system_picture" -- 2.11.0