diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1549d7a..e3b4807 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,6 @@ name: CI -on: - push: - branches: - - main - - 5.1-stable - - 5.0-stable - pull_request: - branches: - - main - - 5.1-stable - - 5.0-stable +on: [push, pull_request] jobs: RSpec: @@ -19,21 +9,28 @@ jobs: fail-fast: false matrix: alchemy_branch: - - 5.0-stable - - 5.1-stable + - 5.3-stable + - 6.0-stable - main ruby: - - '2.5' - - '2.6' - - '2.7' + - "2.6" + - "2.7" + - "3.0" database: - mysql - postgresql + exclude: + - alchemy_branch: 5.3-stable + ruby: "3.0" + database: mysql + - alchemy_branch: 5.3-stable + ruby: "3.0" + database: postgresql env: DB: ${{ matrix.database }} DB_USER: alchemy_user DB_PASSWORD: password - DB_HOST: '127.0.0.1' + DB_HOST: "127.0.0.1" RAILS_ENV: test ALCHEMY_BRANCH: ${{ matrix.alchemy_branch }} services: @@ -43,11 +40,11 @@ jobs: POSTGRES_USER: ${{ env.DB_USER }} POSTGRES_PASSWORD: ${{ env.DB_PASSWORD }} POSTGRES_DB: alchemy_devise_dummy_test - ports: ['5432:5432'] + ports: ["5432:5432"] options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 mysql: image: mysql:latest - ports: ['3306:3306'] + ports: ["3306:3306"] env: MYSQL_USER: ${{ env.DB_USER }} MYSQL_PASSWORD: ${{ env.DB_PASSWORD }} @@ -57,12 +54,13 @@ jobs: steps: - uses: actions/checkout@v2.3.4 - name: Set up Ruby - uses: actions/setup-ruby@v1.1.2 + uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} + bundler-cache: true - name: Restore apt cache id: apt-cache - uses: actions/cache@v2.1.3 + uses: actions/cache@v2 with: path: /home/runner/apt/cache key: ${{ runner.os }}-apt-${{ matrix.database }} @@ -82,24 +80,9 @@ jobs: sudo apt update -qq sudo apt install -qq --fix-missing libmysqlclient-dev -o dir::cache::archives="/home/runner/apt/cache" sudo chown -R runner /home/runner/apt/cache - - name: Install bundler - run: | - gem install bundler - - name: Restore Ruby Gems cache - id: cache - uses: actions/cache@v2.1.3 - with: - path: vendor/bundle - key: ${{ runner.os }}-bundle-${{ matrix.ruby }}-${{ matrix.alchemy_branch }}-${{ matrix.database }}-${{ hashFiles('**/Gemfile') }} - restore-keys: | - ${{ runner.os }}-bundle- - - name: Install bundle - timeout-minutes: 10 - run: | - bundle install --jobs 4 --retry 3 --path vendor/bundle - name: Restore node modules cache id: yarn-cache - uses: actions/cache@v2.1.3 + uses: actions/cache@v2 with: path: spec/dummy/node_modules key: ${{ runner.os }}-yarn-dummy-${{ hashFiles('./package.json') }} diff --git a/Gemfile b/Gemfile index f6e8478..568e0fc 100644 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,13 @@ source "https://rubygems.org" alchemy_branch = ENV.fetch("ALCHEMY_BRANCH", "main") gem "alchemy_cms", github: "AlchemyCMS/alchemy_cms", branch: alchemy_branch +case alchemy_branch +when /5\.3/ + gem "rails", github: "rails/rails", branch: "6-0-stable" +else + gem "rails", github: "rails/rails", branch: "6-1-stable" +end + # Specify your gem's dependencies in alchemy-solidus.gemspec gemspec diff --git a/config/initializers/alchemy.rb b/config/initializers/alchemy.rb index 85a1d29..b699287 100644 --- a/config/initializers/alchemy.rb +++ b/config/initializers/alchemy.rb @@ -1,28 +1,24 @@ # frozen_string_literal: true -require "alchemy/devise/ability" +Rails.application.config.to_prepare do + require "alchemy/devise/ability" -Alchemy.register_ability(Alchemy::Devise::Ability) + Alchemy.register_ability(Alchemy::Devise::Ability) -Alchemy::Modules.register_module({ - name: "users", - engine_name: "alchemy", - position: 4.1, - navigation: { - name: "modules.users", - controller: "/alchemy/admin/users", - action: "index", - icon: "users", - }, -}) + Alchemy::Modules.register_module({ + name: "users", + engine_name: "alchemy", + position: 4.1, + navigation: { + name: "modules.users", + controller: "/alchemy/admin/users", + action: "index", + icon: "users", + }, + }) -Alchemy.user_class_name = "Alchemy::User" -Alchemy.signup_path = "/admin/signup" -Alchemy.login_path = "/admin/login" -Alchemy.logout_path = "/admin/logout" - -if Alchemy.respond_to?(:logout_method) - Rails.application.config.after_initialize do - Alchemy.logout_method = Devise.sign_out_via - end + Alchemy.signup_path = "/admin/signup" + Alchemy.login_path = "/admin/login" + Alchemy.logout_path = "/admin/logout" + Alchemy.logout_method = Devise.sign_out_via end diff --git a/lib/alchemy/devise/engine.rb b/lib/alchemy/devise/engine.rb index 4f63238..0583651 100644 --- a/lib/alchemy/devise/engine.rb +++ b/lib/alchemy/devise/engine.rb @@ -7,6 +7,10 @@ class Engine < ::Rails::Engine isolate_namespace Alchemy engine_name 'alchemy_devise' + initializer "alchemy_devise.user_class", before: "alchemy.userstamp" do + Alchemy.user_class_name = "Alchemy::User" + end + initializer 'alchemy_devise.assets' do |app| app.config.assets.precompile += [ 'alchemy-devise.css' diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb index f3f2e58..8c3b956 100644 --- a/spec/dummy/config/application.rb +++ b/spec/dummy/config/application.rb @@ -1,4 +1,4 @@ -require_relative 'boot' +require_relative "boot" require "rails" # Pick the frameworks you want: @@ -23,7 +23,12 @@ module Dummy class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 6.0 + case ENV.fetch("ALCHEMY_BRANCH", "main") + when /5\.3/ + config.load_defaults 6.0 + else + config.load_defaults 6.1 + end # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a8eae50..11af267 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,5 +1,6 @@ -require 'rails_helper' -require 'alchemy/test_support/factories/page_factory' +# frozen_string_literal: true + +require "rails_helper" module Alchemy describe User do @@ -8,34 +9,34 @@ module Alchemy it "should have at least member role" do expect(user.alchemy_roles).not_to be_blank - expect(user.alchemy_roles).to include('member') + expect(user.alchemy_roles).to include("member") end - describe '.search' do + describe ".search" do subject { User.search(query) } let!(:user1) do create :alchemy_user, - email: 'find@me.com', - login: 'user1', - firstname: 'Michael', - lastname: 'Jackson' + email: "find@me.com", + login: "user1", + firstname: "Michael", + lastname: "Jackson" end let!(:user2) do create :alchemy_user, - email: 'find@me-not.com', - login: 'user2', - firstname: 'Prince Rogers', - lastname: 'Nelson' + email: "find@me-not.com", + login: "user2", + firstname: "Prince Rogers", + lastname: "Nelson" end let!(:users) do [user1, user1] end - context 'by email' do - let(:query) { 'find@me.com' } + context "by email" do + let(:query) { "find@me.com" } it "returns all matching users" do is_expected.to include(user1) @@ -43,38 +44,38 @@ module Alchemy end end - context 'by login' do - let(:query) { 'User1' } + context "by login" do + let(:query) { "User1" } - it 'returns all matching users' do + it "returns all matching users" do is_expected.to include(user1) is_expected.to_not include(user2) end end - context 'by firstname' do - let(:query) { 'prince' } + context "by firstname" do + let(:query) { "prince" } - it 'returns all matching users' do + it "returns all matching users" do is_expected.to_not include(user1) is_expected.to include(user2) end end - context 'by lastname' do - let(:query) { 'jackson' } + context "by lastname" do + let(:query) { "jackson" } - it 'returns all matching users' do + it "returns all matching users" do is_expected.to include(user1) is_expected.to_not include(user2) end end end - describe 'scopes' do + describe "scopes" do let(:user) { create(:alchemy_admin_user) } - describe '.admins' do + describe ".admins" do it "should only return users with admin role" do expect(User.admins).to include(user) end @@ -83,17 +84,16 @@ module Alchemy describe ".human_rolename" do it "return a translated role name" do - expect(User.human_rolename('member')).to eq("Member") + expect(User.human_rolename("member")).to eq("Member") end end - describe '#deliver_welcome_mail' do + describe "#deliver_welcome_mail" do let(:user) { build_stubbed(:alchemy_admin_user) } it "delivers the admin welcome mail." do - expect(Notifications) - .to receive(:alchemy_user_created) - .and_return(OpenStruct.new(deliver: true)) + expect(Notifications).to receive(:alchemy_user_created) + .and_return(OpenStruct.new(deliver: true)) user.deliver_welcome_mail end @@ -102,9 +102,8 @@ module Alchemy before { user.alchemy_roles = %w(author) } it "delivers the admin welcome mail." do - expect(Notifications) - .to receive(:alchemy_user_created) - .and_return(OpenStruct.new(deliver: true)) + expect(Notifications).to receive(:alchemy_user_created) + .and_return(OpenStruct.new(deliver: true)) user.deliver_welcome_mail end @@ -114,9 +113,8 @@ module Alchemy before { user.alchemy_roles = %w(member) } it "delivers the welcome mail." do - expect(Notifications) - .to receive(:member_created) - .and_return(OpenStruct.new(deliver: true)) + expect(Notifications).to receive(:member_created) + .and_return(OpenStruct.new(deliver: true)) user.deliver_welcome_mail end @@ -125,21 +123,21 @@ module Alchemy describe "#human_roles_string" do it "should return a humanized roles string." do - user.alchemy_roles = ['member', 'admin'] + user.alchemy_roles = ["member", "admin"] expect(user.human_roles_string).to eq("Member and Administrator") end end - describe '#role_symbols' do + describe "#role_symbols" do it "should return an array of user role symbols" do expect(user.role_symbols).to eq([:member]) end end - describe '#has_role?' do + describe "#has_role?" do context "with given role" do it "should return true." do - expect(user.has_role?('member')).to be_truthy + expect(user.has_role?("member")).to be_truthy end end @@ -151,16 +149,16 @@ module Alchemy context "without given role" do it "should return true." do - expect(user.has_role?('admin')).to be_falsey + expect(user.has_role?("admin")).to be_falsey end end end - describe '#role' do + describe "#role" do context "when user doesn't have any roles" do before { user.alchemy_roles = [] } - it 'should return nil' do + it "should return nil" do expect(user.role).to be_nil end end @@ -168,20 +166,19 @@ module Alchemy context "when user has multiple roles" do before { user.alchemy_roles = ["admin", "member"] } - it 'should return the first role' do + it "should return the first role" do expect(user.role).to eq("admin") end end end - describe '#alchemy_roles' do + describe "#alchemy_roles" do it "should return an array of user roles" do expect(user.alchemy_roles).to eq(["member"]) end end - describe '#alchemy_roles=' do - + describe "#alchemy_roles=" do it "should accept an array of user roles" do user.alchemy_roles = ["admin"] expect(user.alchemy_roles).to eq(["admin"]) @@ -196,7 +193,6 @@ module Alchemy user.alchemy_roles = ["admin", "member"] expect(user.read_attribute(:alchemy_roles)).to eq("admin member") end - end describe "#add_role" do @@ -211,7 +207,7 @@ module Alchemy end end - describe '#logged_in?' do + describe "#logged_in?" do let(:user) { build(:alchemy_user) } before { allow(Config).to receive(:get).and_return 60 } @@ -223,7 +219,7 @@ module Alchemy end end - describe '#logged_out?' do + describe "#logged_out?" do let(:user) { build(:alchemy_user) } before { allow(Config).to receive(:get).and_return 60 } @@ -248,7 +244,7 @@ module Alchemy end end - describe '#unlock_pages' do + describe "#unlock_pages" do let(:user) { create(:alchemy_user) } let(:page) { create(:alchemy_page) } @@ -262,14 +258,14 @@ module Alchemy end end - describe '#is_admin?' do + describe "#is_admin?" do it "should return true if the user has admin role" do user.alchemy_roles = "admin" expect(user.is_admin?).to be_truthy end end - describe '#fullname' do + describe "#fullname" do it "should return the firstname and lastname" do expect(user.fullname).to eq("John Doe") end @@ -296,7 +292,7 @@ module Alchemy end end - describe '#store_request_time!' do + describe "#store_request_time!" do let(:user) { create(:alchemy_admin_user) } it "should store the timestamp of the request" do diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 5f8eadb..4e69b2a 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,18 +1,23 @@ # frozen_string_literal: true -require_relative './spec_helper' +require_relative "./spec_helper" # Configure Rails Environment ENV["RAILS_ENV"] ||= "test" require File.expand_path("../dummy/config/environment.rb", __FILE__) -require 'rails-controller-testing' +require "rails-controller-testing" require "rspec/rails" -require 'rspec/active_model/mocks' +require "rspec/active_model/mocks" require "capybara/rails" -require 'factory_bot' -require 'alchemy/test_support/integration_helpers' -require 'alchemy/devise/test_support/factories' +require "factory_bot_rails" +require "alchemy/test_support/integration_helpers" + +require "alchemy/test_support" +FactoryBot.definition_file_paths.append(Alchemy::TestSupport.factories_path) +FactoryBot.reload + +require "alchemy/devise/test_support/factories" ActionMailer::Base.delivery_method = :test ActionMailer::Base.perform_deliveries = true