Browse Source

#47

feature/047
みてるぞ 1 day ago
parent
commit
e40f7a3620
4 changed files with 212 additions and 23 deletions
  1. +2
    -2
      backend/app/controllers/wiki_assets_controller.rb
  2. +16
    -0
      backend/app/representations/wiki_asset_repr.rb
  3. +191
    -0
      backend/spec/requests/wiki_assets_spec.rb
  4. +3
    -21
      backend/spec/requests/wiki_spec.rb

+ 2
- 2
backend/app/controllers/wiki_assets_controller.rb View File

@@ -7,7 +7,7 @@ class WikiAssetsController < ApplicationController
page = WikiPage.find_by(id: page_id) page = WikiPage.find_by(id: page_id)
return head :not_found unless page return head :not_found unless page


render json: page.assets
render json: WikiAssetRepr.many(page.assets)
end end


def create def create
@@ -34,6 +34,6 @@ class WikiAssetsController < ApplicationController
page.update!(next_asset_no: no + 1) page.update!(next_asset_no: no + 1)
end end


render json: asset.as_json(only: [:wiki_page_id, :no], methods: [:url])
render json: WikiAssetRepr.base(asset)
end end
end end

+ 16
- 0
backend/app/representations/wiki_asset_repr.rb View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true


module WikiAssetRepr
BASE = { only: [:wiki_page_id, :no], methods: [:url] }.freeze

module_function

def base wiki_asset
wiki_asset.as_json(BASE)
end

def many wiki_assets
wiki_assets.map { |a| base(a) }
end
end

+ 191
- 0
backend/spec/requests/wiki_assets_spec.rb View File

@@ -0,0 +1,191 @@
require 'digest'
require 'rails_helper'
require 'stringio'


RSpec.describe 'WikiAssets API', type: :request do
def dummy_upload(content = 'dummy-image', filename: 'dummy.png', content_type: 'image/png')
Rack::Test::UploadedFile.new(StringIO.new(content),
content_type,
original_filename: filename)
end

let(:member) { create(:user, :member, name: 'member user') }
let(:guest) { create(:user, name: 'guest user') }

let!(:tag_name) { TagName.create!(name: 'spec_wiki_asset_page') }
let!(:page) do
WikiPage.create!(tag_name: tag_name, created_user: member, updated_user: member).tap do |p|
Wiki::Commit.content!(page: p, body: 'init', created_user: member, message: 'init')
end
end

describe 'GET /wiki/:wiki_page_id/assets' do
subject(:do_request) do
get "/wiki/#{wiki_page_id}/assets"
end

let(:wiki_page_id) { page.id }

let!(:asset) do
WikiAsset.new(wiki_page: page,
no: 1,
alt_text: 'spec alt',
sha256: Digest::SHA256.digest('asset-1'),
created_by_user: member).tap do |record|
record.file.attach(dummy_upload('asset-1'))
record.save!
end
end

context 'when wiki page exists' do
it 'returns assets for the page' do
do_request

expect(response).to have_http_status(:ok)
expect(json).to be_an(Array)
expect(json.size).to eq(1)

expect(json.first).to include(
'wiki_page_id' => page.id,
'no' => 1)
end

it 'does not include assets from other pages' do
other_tag_name = TagName.create!(name: 'spec_other_wiki_asset_page')
other_page = WikiPage.create!(tag_name: other_tag_name,
created_user: member,
updated_user: member)
Wiki::Commit.content!(page: other_page, body: 'other', created_user: member, message: 'other')

WikiAsset.new(wiki_page: other_page,
no: 1,
alt_text: 'other alt',
sha256: Digest::SHA256.digest('asset-2'),
created_by_user: member).tap do |record|
record.file.attach(dummy_upload('asset-2', filename: 'other.png'))
record.save!
end

do_request

expect(response).to have_http_status(:ok)
expect(json.size).to eq(1)
expect(json.first['wiki_page_id']).to eq(page.id)
end
end

context 'when wiki page does not exist' do
let(:wiki_page_id) { 999_999_999 }

it 'returns 404' do
do_request
expect(response).to have_http_status(:not_found)
end
end
end

describe 'POST /wiki/:wiki_page_id/assets' do
subject(:do_request) do
post "/wiki/#{wiki_page_id}/assets", params: params
end

let(:wiki_page_id) { page.id }
let(:params) do
{ file: dummy_upload(upload_content),
alt_text: 'uploaded alt' }
end
let(:upload_content) { 'uploaded-image-binary' }

context 'when not logged in' do
it 'returns 401' do
sign_out
do_request
expect(response).to have_http_status(:unauthorized)
end
end

context 'when logged in but not member' do
it 'returns 403' do
sign_in_as(guest)
do_request
expect(response).to have_http_status(:forbidden)
end
end

context 'when wiki page does not exist' do
let(:wiki_page_id) { 999_999_999 }

it 'returns 404' do
sign_in_as(member)
do_request
expect(response).to have_http_status(:not_found)
end
end

context 'when file is blank' do
let(:params) { { alt_text: 'uploaded alt' } }

it 'returns 400' do
sign_in_as(member)
do_request
expect(response).to have_http_status(:bad_request)
end
end

context 'when success' do
before do
sign_in_as(member)
end

it 'creates asset, attaches file, increments next_asset_no, and returns json' do
expect { do_request }
.to change(WikiAsset, :count).by(1)

expect(response).to have_http_status(:ok)

asset = WikiAsset.order(:id).last
expect(asset.wiki_page_id).to eq(page.id)
expect(asset.no).to eq(1)
expect(asset.alt_text).to eq('uploaded alt')
expect(asset.sha256).to eq(Digest::SHA256.digest(upload_content))
expect(asset.created_by_user_id).to eq(member.id)
expect(asset.file).to be_attached
expect(asset.file.download).to eq(upload_content)

expect(page.reload.next_asset_no).to eq(2)

expect(json).to include(
'wiki_page_id' => page.id,
'no' => 1,
'url' => asset.url
)
end

it 'uses the next page-local number when assets already exist' do
existing = WikiAsset.new(wiki_page: page,
no: 1,
alt_text: 'existing alt',
sha256: Digest::SHA256.digest('existing'),
created_by_user: member)
existing.file.attach(dummy_upload('existing', filename: 'existing.png'))
existing.save!
page.update!(next_asset_no: 2)

do_request

expect(response).to have_http_status(:ok)

asset = WikiAsset.order(:id).last
expect(asset.no).to eq(2)
expect(page.reload.next_asset_no).to eq(3)

expect(json).to include(
'wiki_page_id' => page.id,
'no' => 2,
'url' => asset.url
)
end
end
end
end

+ 3
- 21
backend/spec/requests/wiki_spec.rb View File

@@ -97,13 +97,14 @@ RSpec.describe 'Wiki API', type: :request do
post endpoint, params: { title: 'TestPage', body: "a\nb\nc", message: 'init' }, post endpoint, params: { title: 'TestPage', body: "a\nb\nc", message: 'init' },
headers: auth_headers(member) headers: auth_headers(member)
end end
.to change(WikiPage, :count).by(1)
.and change(WikiRevision, :count).by(1)
.to change(WikiPage, :count).by(1)
.and change(WikiRevision, :count).by(1)


expect(response).to have_http_status(:created) expect(response).to have_http_status(:created)


page_id = json.fetch('id') page_id = json.fetch('id')
expect(json.fetch('title')).to eq('TestPage') expect(json.fetch('title')).to eq('TestPage')
expect(json.fetch('body')).to eq("a\nb\nc")


page = WikiPage.find(page_id) page = WikiPage.find(page_id)
rev = page.current_revision rev = page.current_revision
@@ -111,30 +112,11 @@ RSpec.describe 'Wiki API', type: :request do
expect(rev).to be_content expect(rev).to be_content
expect(rev.message).to eq('init') expect(rev.message).to eq('init')


# body が復元できること
expect(page.body).to eq("a\nb\nc") expect(page.body).to eq("a\nb\nc")

# 行数とリレーションの整合
expect(rev.lines_count).to eq(3) expect(rev.lines_count).to eq(3)
expect(rev.wiki_revision_lines.order(:position).pluck(:position)).to eq([0, 1, 2]) expect(rev.wiki_revision_lines.order(:position).pluck(:position)).to eq([0, 1, 2])
expect(rev.wiki_lines.pluck(:body)).to match_array(%w[a b c]) expect(rev.wiki_lines.pluck(:body)).to match_array(%w[a b c])
end end

it 'reuses existing WikiLine rows by sha256' do
# 先に同じ行を作っておく
WikiLine.create!(sha256: Digest::SHA256.hexdigest('a'), body: 'a', created_at: Time.current, updated_at: Time.current)

post endpoint,
params: { title: 'Reuse', body: "a\na" },
headers: auth_headers(member)

page = WikiPage.find(JSON.parse(response.body).fetch('id'))
rev = page.current_revision
expect(rev.lines_count).to eq(2)

# "a" の WikiLine が増殖しない(1行のはず)
expect(WikiLine.where(body: 'a').count).to eq(1)
end
end end
end end




Loading…
Cancel
Save