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
# 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
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)
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
kaminari
letter_opener
mysql2 (~> 0.5)
+ ostruct
puma (>= 5.0)
rails (~> 8.0.1)
+ rails-controller-testing
redcarpet
rouge
rqrcode
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+{
+ invalid json content
+}
--- /dev/null
+{
+ "posts": [
+ {
+ "title": "Imported Post",
+ "content": "This is an imported post",
+ "post_type": "dispatch",
+ "published_at": "2024-01-01T12:00:00Z"
+ }
+ ]
+}
--- /dev/null
+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
--- /dev/null
+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 %>
--- /dev/null
+admin:
+ encrypted_password: <%= User.new.send(:password_digest, 'password123') %>
+ first_name: Admin
+ last_name: User
+ admin: true
+ confirmed_at: <%= Time.current %>
--- /dev/null
+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
--- /dev/null
+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 "<code>ruby</code>, <code>rails</code>.", @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
-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