From cc09e7864f246bed14fe940bd0af88dbdab1e2b8 Mon Sep 17 00:00:00 2001 From: Aidan Cornelius-Bell Date: Sat, 11 Jan 2025 18:33:50 +1030 Subject: [PATCH] A base to the test suite --- Gemfile | 3 + Gemfile.lock | 7 ++ test/controllers/pages_controller_test.rb | 62 +++++++++++++ test/controllers/posts_controller_test.rb | 102 ++++++++++++++++++++++ test/fixtures/files/invalid.json | 3 + test/fixtures/files/posts.json | 10 +++ test/fixtures/pages.yml | 11 +++ test/fixtures/posts.yml | 13 +++ test/fixtures/users.yml | 7 ++ test/models/page_test.rb | 52 +++++++++++ test/models/post_test.rb | 100 +++++++++++++++++++++ test/test_helper.rb | 23 +++-- 12 files changed, 388 insertions(+), 5 deletions(-) create mode 100644 test/controllers/pages_controller_test.rb create mode 100644 test/controllers/posts_controller_test.rb create mode 100644 test/fixtures/files/invalid.json create mode 100644 test/fixtures/files/posts.json create mode 100644 test/fixtures/pages.yml create mode 100644 test/fixtures/posts.yml create mode 100644 test/fixtures/users.yml create mode 100644 test/models/page_test.rb create mode 100644 test/models/post_test.rb diff --git a/Gemfile b/Gemfile index 43de942..7fd6a65 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,8 @@ gem "dotenv" gem "hcaptcha" # subscribers gem "stripe" +# Adding this because: ostruct.rb was loaded from the standard library, but will no longer be part of the default gems starting from Ruby 3.5.0. +gem 'ostruct' # Scheduling gem "whenever", require: false # 2FA @@ -66,5 +68,6 @@ group :test do # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] gem "capybara" gem "selenium-webdriver" + gem "rails-controller-testing" gem "stripe-ruby-mock", '~> 3.1.0', require: 'stripe_mock' end diff --git a/Gemfile.lock b/Gemfile.lock index 98e89d6..00aa9c9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -199,6 +199,7 @@ GEM nokogiri (1.18.1-x86_64-linux-gnu) racc (~> 1.4) orm_adapter (0.5.0) + ostruct (0.6.1) parallel (1.26.3) parser (3.3.6.0) ast (~> 2.4.1) @@ -232,6 +233,10 @@ GEM activesupport (= 8.0.1) bundler (>= 1.15.0) railties (= 8.0.1) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -364,8 +369,10 @@ DEPENDENCIES kaminari letter_opener mysql2 (~> 0.5) + ostruct puma (>= 5.0) rails (~> 8.0.1) + rails-controller-testing redcarpet rouge rqrcode diff --git a/test/controllers/pages_controller_test.rb b/test/controllers/pages_controller_test.rb new file mode 100644 index 0000000..e5abe20 --- /dev/null +++ b/test/controllers/pages_controller_test.rb @@ -0,0 +1,62 @@ +require "test_helper" + +class PagesControllerTest < ActionDispatch::IntegrationTest + include Devise::Test::IntegrationHelpers + + setup do + @admin = users(:admin) # You'll need to set up this fixture + @page = pages(:one) # You'll need to set up this fixture + sign_in @admin + end + + test "should get index" do + get pages_url + assert_response :success + end + + test "should get new" do + get new_page_url + assert_response :success + end + + test "should create page" do + assert_difference("Page.count") do + post pages_url, params: { + page: { + title: "New Page", + content: "New content", + visibility: "visible" + } + } + end + + assert_redirected_to page_url(Page.last) + end + + test "should show page" do + get page_url(@page) + assert_response :success + end + + test "should get edit" do + get edit_page_url(@page) + assert_response :success + end + + test "should update page" do + patch page_url(@page), params: { + page: { + title: "Updated Title" + } + } + assert_redirected_to page_url(@page) + end + + test "should destroy page" do + assert_difference("Page.count", -1) do + delete page_url(@page) + end + + assert_redirected_to pages_url + end +end diff --git a/test/controllers/posts_controller_test.rb b/test/controllers/posts_controller_test.rb new file mode 100644 index 0000000..ba22759 --- /dev/null +++ b/test/controllers/posts_controller_test.rb @@ -0,0 +1,102 @@ +require "test_helper" + +class PostsControllerTest < ActionDispatch::IntegrationTest + include Devise::Test::IntegrationHelpers + + setup do + @admin = users(:admin) # You'll need to set up this fixture + @post = posts(:dispatch) # You'll need to set up this fixture + sign_in @admin + end + + test "should get index" do + get posts_url + assert_response :success + end + + test "should get new" do + get new_post_url + assert_response :success + end + + test "should create dispatch post" do + assert_difference("Post.count") do + post posts_url, params: { + post: { + title: "New Dispatch", + content: "Test content", + post_type: "dispatch", + published_at: Time.current + } + } + end + + assert_redirected_to post_url(Post.last) + end + + test "should create bookmark post" do + assert_difference("Post.count") do + post posts_url, params: { + post: { + title: "New Bookmark", + url: "https://example.com", + post_type: "bookmark" + } + } + end + + assert_redirected_to post_url(Post.last) + end + + test "should show post" do + get post_url(@post) + assert_response :success + end + + test "should get edit" do + get edit_post_url(@post) + assert_response :success + end + + test "should update post" do + patch post_url(@post), params: { + post: { + title: "Updated Title" + } + } + assert_redirected_to post_url(@post) + end + + test "should destroy post" do + assert_difference("Post.count", -1) do + delete post_url(@post) + end + + assert_redirected_to posts_url + end + + test "should export posts" do + get export_url + assert_response :success + assert_equal "application/json", response.content_type + end + + test "should get importer page" do + get importer_url + assert_response :success + end + + test "should import json file" do + file = fixture_file_upload('posts.json', 'application/json') + post import_url, params: { file: file } + assert_redirected_to posts_url + assert_not_nil flash[:notice] + end + + test "should handle invalid import file" do + file = fixture_file_upload('invalid.json', 'application/json') + post import_url, params: { file: file } + assert_redirected_to posts_url + assert_not_nil flash[:alert] + end +end diff --git a/test/fixtures/files/invalid.json b/test/fixtures/files/invalid.json new file mode 100644 index 0000000..3848732 --- /dev/null +++ b/test/fixtures/files/invalid.json @@ -0,0 +1,3 @@ +{ + invalid json content +} diff --git a/test/fixtures/files/posts.json b/test/fixtures/files/posts.json new file mode 100644 index 0000000..da516e6 --- /dev/null +++ b/test/fixtures/files/posts.json @@ -0,0 +1,10 @@ +{ + "posts": [ + { + "title": "Imported Post", + "content": "This is an imported post", + "post_type": "dispatch", + "published_at": "2024-01-01T12:00:00Z" + } + ] +} diff --git a/test/fixtures/pages.yml b/test/fixtures/pages.yml new file mode 100644 index 0000000..485de4b --- /dev/null +++ b/test/fixtures/pages.yml @@ -0,0 +1,11 @@ +one: + title: Sample Page + slug: sample-page + content: This is a sample page content + visibility: visible + +two: + title: Another Page + slug: another-page + content: This is another page content + visibility: hidden diff --git a/test/fixtures/posts.yml b/test/fixtures/posts.yml new file mode 100644 index 0000000..14d7368 --- /dev/null +++ b/test/fixtures/posts.yml @@ -0,0 +1,13 @@ +dispatch: + title: Sample Dispatch + slug: sample-dispatch + content: This is a sample dispatch post + post_type: dispatch + published_at: <%= Time.current %> + +bookmark: + title: Sample Bookmark + slug: sample-bookmark + url: https://example.com + post_type: bookmark + published_at: <%= Time.current %> diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000..96d8246 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,7 @@ +admin: + email: admin@example.com + encrypted_password: <%= User.new.send(:password_digest, 'password123') %> + first_name: Admin + last_name: User + admin: true + confirmed_at: <%= Time.current %> diff --git a/test/models/page_test.rb b/test/models/page_test.rb new file mode 100644 index 0000000..489eb5b --- /dev/null +++ b/test/models/page_test.rb @@ -0,0 +1,52 @@ +require "test_helper" + +class PageTest < ActiveSupport::TestCase + def setup + @page = Page.new( + title: "About Us", + content: "Welcome to our site", + visibility: "visible" + ) + end + + test "should be valid with valid attributes" do + assert @page.valid? + end + + test "should require a title" do + @page.title = nil + assert_not @page.valid? + assert_includes @page.errors[:title], "can't be blank" + end + + test "should automatically generate slug from title" do + @page.slug = nil + @page.valid? + assert_equal "about-us", @page.slug + end + + test "should enforce unique slugs" do + @page.save! + duplicate_page = Page.new( + title: "About Us", + content: "Different content", + visibility: "visible" + ) + assert_not duplicate_page.valid? + assert_includes duplicate_page.errors[:slug], "has already been taken" + end + + test "should validate slug format" do + @page.slug = "Invalid Slug!" + assert_not @page.valid? + assert_includes @page.errors[:slug], "can only contain lowercase letters, numbers, and hyphens" + end + + test "should have valid visibility values" do + valid_visibilities = ['hidden', 'visible', 'user_only', 'admin_only'] + valid_visibilities.each do |visibility| + @page.visibility = visibility + assert @page.valid?, "#{visibility} should be valid" + end + end +end diff --git a/test/models/post_test.rb b/test/models/post_test.rb new file mode 100644 index 0000000..dc639c1 --- /dev/null +++ b/test/models/post_test.rb @@ -0,0 +1,100 @@ +require "test_helper" + +class PostTest < ActiveSupport::TestCase + def setup + @dispatch = Post.new( + title: "Test Dispatch", + content: "Test content", + post_type: "dispatch", + published_at: Time.current + ) + + @bookmark = Post.new( + title: "Test Bookmark", + url: "https://example.com", + post_type: "bookmark", + published_at: Time.current + ) + end + + test "should be valid with valid dispatch attributes" do + assert @dispatch.valid? + end + + test "should be valid with valid bookmark attributes" do + assert @bookmark.valid? + end + + test "should require post_type" do + @dispatch.post_type = nil + assert_not @dispatch.valid? + assert_includes @dispatch.errors[:post_type], "can't be blank" + end + + test "should only allow valid post types" do + @dispatch.post_type = "invalid" + assert_not @dispatch.valid? + assert_includes @dispatch.errors[:post_type], "is not included in the list" + end + + test "should require content for dispatch posts" do + @dispatch.content = nil + assert_not @dispatch.valid? + assert_includes @dispatch.errors[:content], "can't be blank" + end + + test "should require url for bookmark posts" do + @bookmark.url = nil + assert_not @bookmark.valid? + assert_includes @bookmark.errors[:url], "can't be blank" + end + + test "should handle duplicate slugs" do + # Create first post + first_post = Post.create!( + title: "Test Post", + content: "Original content", + post_type: "dispatch", + published_at: Time.current + ) + + # Create second post with same title but modified slug + second_post = Post.create!( + title: "Test Post", + content: "Different content", + post_type: "dispatch", + published_at: Time.current, + slug: "test-post-1" # Manually set a unique slug + ) + + # Verify posts have different slugs + assert_not_equal first_post.slug, second_post.slug + assert_equal "test-post", first_post.slug + assert_equal "test-post-1", second_post.slug + end + + test "should generate excerpt" do + @dispatch.content = "This is a test post with multiple sentences. This is the second sentence." + assert_equal "This is a test post with multiple sentences", @dispatch.generate_excerpt + end + + test "should identify short dispatches" do + @dispatch.content = "Short content" + assert @dispatch.short_dispatch? + + @dispatch.content = "Dear friends, " + "word " * 150 + assert_not @dispatch.short_dispatch? + end + + test "should format tags" do + @dispatch.tags = "ruby, rails" + assert_equal "ruby, rails.", @dispatch.format_tags + end + + test "should generate slug from url for bookmarks without title" do + @bookmark.title = nil + @bookmark.url = "https://example.com/page" + @bookmark.valid? + assert_match /^example-com-\d{14}$/, @bookmark.slug + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 9c9ba95..b99ca90 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,7 +1,20 @@ -require "test_helper" +ENV["RAILS_ENV"] ||= "test" +require "dotenv" +Dotenv.load(".env.test") -class ArticleTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end +require_relative "../config/environment" +require "rails/test_help" + +class ActiveSupport::TestCase + # Run tests in parallel with specified workers + parallelize(workers: :number_of_processors) unless ENV["PARALLEL_WORKERS"] == "1" + + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order + fixtures :all + + # Add more helper methods to be used by all tests here... +end + +class ActionDispatch::IntegrationTest + include Devise::Test::IntegrationHelpers end -- 2.39.5