diff --git a/backend/Gemfile b/backend/Gemfile index 4853e44..1d48493 100644 --- a/backend/Gemfile +++ b/backend/Gemfile @@ -46,6 +46,8 @@ group :development, :test do # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/] gem "rubocop-rails-omakase", require: false + + gem 'factory_bot_rails' end diff --git a/backend/Gemfile.lock b/backend/Gemfile.lock index 1746b8c..42eb862 100644 --- a/backend/Gemfile.lock +++ b/backend/Gemfile.lock @@ -99,6 +99,11 @@ GEM drb (2.2.1) ed25519 (1.4.0) erubi (1.13.1) + factory_bot (6.5.6) + activesupport (>= 6.1.0) + factory_bot_rails (6.5.1) + factory_bot (~> 6.5) + railties (>= 6.1.0) ffi (1.17.2-aarch64-linux-gnu) ffi (1.17.2-aarch64-linux-musl) ffi (1.17.2-arm-linux-gnu) @@ -441,6 +446,7 @@ DEPENDENCIES diff-lcs discard dotenv-rails + factory_bot_rails gollum image_processing (~> 1.14) jwt diff --git a/backend/app/controllers/users_controller.rb b/backend/app/controllers/users_controller.rb index 4ee4836..4d8e57e 100644 --- a/backend/app/controllers/users_controller.rb +++ b/backend/app/controllers/users_controller.rb @@ -18,6 +18,8 @@ class UsersController < ApplicationController end def renew + return head :unauthorized unless current_user + user = current_user user.inheritance_code = SecureRandom.uuid user.save! diff --git a/backend/config/application.rb b/backend/config/application.rb index 5f1c45e..14b74b9 100644 --- a/backend/config/application.rb +++ b/backend/config/application.rb @@ -11,6 +11,8 @@ module Backend # Initialize configuration defaults for originally generated Rails version. config.load_defaults 8.0 + config.i18n.default_locale = :ja + # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. # Common ones are `templates`, `generators`, or `middleware`, for example. diff --git a/backend/spec/factories/tag_names.rb b/backend/spec/factories/tag_names.rb new file mode 100644 index 0000000..a33be1e --- /dev/null +++ b/backend/spec/factories/tag_names.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :tag_name do + name { "tag-#{SecureRandom.hex(4)}" } + end +end diff --git a/backend/spec/factories/tags.rb b/backend/spec/factories/tags.rb new file mode 100644 index 0000000..5d9530e --- /dev/null +++ b/backend/spec/factories/tags.rb @@ -0,0 +1,12 @@ +FactoryBot.define do + factory :tag do + category { 'general' } + post_count { 0 } + association :tag_name + + trait :nico do + category { 'nico' } + tag_name { association(:tag_name, name: "nico:#{ SecureRandom.hex(4) }") } + end + end +end diff --git a/backend/spec/factories/users.rb b/backend/spec/factories/users.rb new file mode 100644 index 0000000..18548b6 --- /dev/null +++ b/backend/spec/factories/users.rb @@ -0,0 +1,11 @@ +FactoryBot.define do + factory :user do + name { "test-user" } + inheritance_code { SecureRandom.uuid } + role { "guest" } + + trait :member do + role { "member" } + end + end +end diff --git a/backend/spec/rails_helper.rb b/backend/spec/rails_helper.rb index 829cb4a..22122cb 100644 --- a/backend/spec/rails_helper.rb +++ b/backend/spec/rails_helper.rb @@ -8,6 +8,10 @@ abort("The Rails environment is running in production mode!") if Rails.env.produ # that will avoid rails generators crashing because migrations haven't been run yet # return unless Rails.env.test? require 'rspec/rails' +Dir[Rails.root.join('spec/support/**/*.rb')].each do |f| + require f +end + # Add additional requires below this line. Rails is not loaded until this point! # Requires supporting ruby files with custom matchers and macros, etc, in @@ -34,12 +38,16 @@ begin rescue ActiveRecord::PendingMigrationError => e abort e.to_s.strip end -Dir[Rails.root.join('spec/support/**/*.rb')].each do |f| - require f -end RSpec.configure do |config| config.include TestRecords + # FactoryBot の create / create_list を使へるやぅにする + config.include FactoryBot::Syntax::Methods + + # request spec で helper 使へるやぅにする + config.include AuthHelper, type: :request + config.include JsonHelper, type: :request + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_paths = [ Rails.root.join('spec/fixtures') diff --git a/backend/spec/requests/nico_tags_spec.rb b/backend/spec/requests/nico_tags_spec.rb new file mode 100644 index 0000000..6ee9479 --- /dev/null +++ b/backend/spec/requests/nico_tags_spec.rb @@ -0,0 +1,38 @@ +require 'rails_helper' + + +RSpec.describe 'NicoTags', type: :request do + describe 'GET /tags/nico' do + it 'returns tags and next_cursor when overflowing limit' do + create_list(:tag, 21, :nico) + get '/tags/nico', params: { limit: 20 } + expect(response).to have_http_status(:ok) + expect(json['tags'].size).to eq(20) + expect(json['next_cursor']).to be_present + end + end + + describe 'PATCH /tags/nico/:id' do + let(:member) { create(:user, :member) } + let(:nico_tag) { create(:tag, :nico) } + + it '401 when not logged in' do + sign_out + patch "/tags/nico/#{nico_tag.id}", params: { tags: 'a b' } + expect(response).to have_http_status(:unauthorized) + end + + it '403 when not member' do + sign_in_as(create(:user, role: 'guest')) + patch "/tags/nico/#{nico_tag.id}", params: { tags: 'a b' } + expect(response).to have_http_status(:forbidden) + end + + it '400 when target is not nico category' do + sign_in_as(member) + non_nico = create(:tag, :general) + patch "/tags/nico/#{non_nico.id}", params: { tags: 'a b' } + expect(response).to have_http_status(:bad_request) + end + end +end diff --git a/backend/spec/requests/posts_spec.rb b/backend/spec/requests/posts_spec.rb index 5b18521..4366a64 100644 --- a/backend/spec/requests/posts_spec.rb +++ b/backend/spec/requests/posts_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' RSpec.describe 'Posts API', type: :request do describe 'GET /posts' do it 'returns tags with name in JSON' do - tn = TagName.create!(name: 'gen:spec_tag') + tn = TagName.create!(name: 'spec_tag') tag = Tag.create!(tag_name: tn, category: 'general') post = Post.create!(title: 'spec post', url: 'https://example.com/spec') @@ -14,7 +14,6 @@ RSpec.describe 'Posts API', type: :request do expect(response).to have_http_status(:ok) - json = JSON.parse(response.body) expect(json).to have_key('posts') expect(json['posts']).to be_a(Array) expect(json['posts']).not_to be_empty @@ -24,7 +23,10 @@ RSpec.describe 'Posts API', type: :request do expect(tags).not_to be_empty expect(tags[0]).to have_key('name') - expect(tags[0]['name']).to eq('gen:spec_tag') + expect(tags[0]['name']).to eq('spec_tag') + + expect(tags.map { |t| t['name'] }).to include('spec_tag') + expect(tags[0]).to include('category') end end end diff --git a/backend/spec/requests/preview_spec.rb b/backend/spec/requests/preview_spec.rb new file mode 100644 index 0000000..c7d9d25 --- /dev/null +++ b/backend/spec/requests/preview_spec.rb @@ -0,0 +1,28 @@ +require "rails_helper" + + +RSpec.describe "Preview", type: :request do + describe "GET /preview/title" do + it "401 unless logged in" do + sign_out + get "/preview/title", params: { url: "example.com" } + expect(response).to have_http_status(:unauthorized) + end + + it "400 when url blank" do + sign_in_as(create(:user)) + get "/preview/title", params: { url: "" } + expect(response).to have_http_status(:bad_request) + end + + it "returns parsed title (stubbing URI.open)" do + sign_in_as(create(:user)) + fake_html = "