diff --git a/Gemfile b/Gemfile index d438b1724b..7a7d4b4980 100644 --- a/Gemfile +++ b/Gemfile @@ -105,6 +105,7 @@ group :test do gem "axe-matchers", ">= 2.5.0", require: false gem "capybara" gem "climate_control" + gem "generator_spec" gem "guard-rspec", require: false gem "rails-controller-testing" gem "rspec-json_expectations" diff --git a/Gemfile.lock b/Gemfile.lock index 124e4c8323..8e39d21d30 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -276,6 +276,9 @@ GEM fog-core nokogiri (>= 1.5.11, < 2.0.0) formatador (1.1.0) + generator_spec (0.10.0) + activesupport (>= 3.0.0) + railties (>= 3.0.0) geocoder (1.8.2) globalid (1.2.1) activesupport (>= 6.1) @@ -777,6 +780,7 @@ DEPENDENCIES faker faraday fog-aws + generator_spec geocoder (>= 1.6.6) graphlient graphql diff --git a/config/application.rb b/config/application.rb index b664729b81..4ea9b3abba 100644 --- a/config/application.rb +++ b/config/application.rb @@ -19,7 +19,7 @@ class Application < Rails::Application # 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. - config.autoload_lib(ignore: %w[assets tasks]) + config.autoload_lib(ignore: %w[assets tasks generators]) # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers diff --git a/lib/generators/strapi/component_generator.rb b/lib/generators/strapi/component_generator.rb new file mode 100644 index 0000000000..ce693f3c1a --- /dev/null +++ b/lib/generators/strapi/component_generator.rb @@ -0,0 +1,95 @@ +module Strapi + class ComponentGenerator < Rails::Generators::Base + source_root File.expand_path("component_templates", __dir__) + + argument :component_name, type: :string, required: true + argument :component_type, type: :string, required: true + class_option :strapi_params, type: :array, default: [] + + COMPONENT_TYPES = %w[blocks content_blocks buttons email_content] + PROVIDER = "providers/strapi/" + BASE_PATH = "app/services/cms/" + STRAPI_PATH = "#{BASE_PATH}#{PROVIDER}" + TEST_PATH = "spec/services/cms/#{PROVIDER}" + + def setup_params + raise StandardError unless COMPONENT_TYPES.include?(component_type) + @component_name_class = component_name.classify + @component_type_class = component_type.camelize + @component_filename = component_name.underscore + @component_type_filename = component_type.underscore + @component_strapi_name = component_name.underscore.tr("_", "-") + @strapi_params = options["strapi_params"] + @rails_param_names = options["strapi_params"].map { _1.underscore } + end + + def create_query_file + template("query_template.rb.tt", "#{STRAPI_PATH}queries/components/#{@component_type_filename}/#{@component_filename}.rb") + end + + def create_query_test + template("query_test_template.rb.tt", "#{TEST_PATH}queries/components/#{@component_type_filename}/#{@component_filename}_spec.rb") + end + + def create_mock_file + template("mock_template.rb.tt", "#{STRAPI_PATH}mocks/dynamic_components/#{@component_type_filename}/#{@component_filename}.rb") + end + + def create_data_file + template("mapping_template.rb.tt", "#{BASE_PATH}dynamic_components/#{@component_type_filename}/#{@component_filename}.rb") + end + + def run_view_component_generator + Rails::Generators.invoke( + "component", + ["Cms::#{@component_name_class}", *@rails_param_names, "--test-framework=rspec", "--sidecar"].compact, + behaviour: :invoke, + destination_root: + ) + rescue + puts <<~HEREDOC + #{"*" * 80} + Unable to create component, please run this command seperatly + + rails generate component Cms::#{@component_name_class} #{@rails_param_names.join(" ")} --test-framework=rspec + #{"*" * 80} + + HEREDOC + end + + def print_method_defintions + puts <<~HEREDOC + + #{"*" * 80} + + Remember to add the mapping method to #{STRAPI_PATH}factories/#{@component_type_filename}_factory.rb + + !! Code provided below, but may require modification depending on data types !! + + #{factory_key} + #{"-" * 80} + + #{method_defintion} + #{"*" * 80} + + HEREDOC + end + + def factory_key + <<~RUBY + when "#{@component_strapi_name}": + to_#{@component_filename}(strapi_data) + RUBY + end + + def method_defintion + <<~RUBY + def to_#{@component_filename}(strapi_data) + DynamicsComponents::Blocks::#{@component_name_class}.new( + #{@strapi_params.map { "#{_1.underscore}: strapi_data[:#{_1}]" }.join(",\n\s\s\s\s")} + ) + end + RUBY + end + end +end diff --git a/lib/generators/strapi/component_templates/mapping_template.rb.tt b/lib/generators/strapi/component_templates/mapping_template.rb.tt new file mode 100644 index 0000000000..9dc1f88101 --- /dev/null +++ b/lib/generators/strapi/component_templates/mapping_template.rb.tt @@ -0,0 +1,19 @@ +module Cms + module DynamicComponents + module <%= @component_type_class %> + class <%= @component_name_class %> + attr_accessor <%= @rails_param_names.map{":#{_1}"}.join(", ") %> + + def initialize(<%= @rails_param_names.map{"#{_1}:"}.join(", ") %>) + <%- @rails_param_names.each do |param| -%> + <%= "@#{param} = #{param}" %> + <%- end -%> + end + + def render + Cms::<%= @component_name_class %>Component.new(<%= @rails_param_names.map{"#{_1}:"}.join(", ") %>) + end + end + end + end +end diff --git a/lib/generators/strapi/component_templates/mock_template.rb.tt b/lib/generators/strapi/component_templates/mock_template.rb.tt new file mode 100644 index 0000000000..f7b7c802a4 --- /dev/null +++ b/lib/generators/strapi/component_templates/mock_template.rb.tt @@ -0,0 +1,19 @@ +module Cms + module Providers + module Strapi + module Mocks + module DynamicComponents + module <%= @component_type_class %> + class <%= @component_name_class %> < StrapiMock + strapi_component "blocks.<%= @component_strapi_name %>" + + <%- @strapi_params.each do |param| -%> + attribute(:<%= param %>) { } + <%- end -%> + end + end + end + end + end + end +end \ No newline at end of file diff --git a/lib/generators/strapi/component_templates/query_template.rb.tt b/lib/generators/strapi/component_templates/query_template.rb.tt new file mode 100644 index 0000000000..1f9aa6ccfd --- /dev/null +++ b/lib/generators/strapi/component_templates/query_template.rb.tt @@ -0,0 +1,23 @@ +module Cms + module Providers + module Strapi + module Queries + module Components + module <%= @component_type_class %> + class <%= @component_name_class %> < BaseComponentQuery + def self.name = "Component<%= @component_name_class %>" + + def self.base_fields + <<~GRAPHQL.freeze + <%- @strapi_params.each do |param| -%> + <%= param %> + <%- end -%> + GRAPHQL + end + end + end + end + end + end + end +end diff --git a/lib/generators/strapi/component_templates/query_test_template.rb.tt b/lib/generators/strapi/component_templates/query_test_template.rb.tt new file mode 100644 index 0000000000..ee1870e28f --- /dev/null +++ b/lib/generators/strapi/component_templates/query_test_template.rb.tt @@ -0,0 +1,10 @@ +require "rails_helper" + +RSpec.describe Cms::Providers::Strapi::Queries::Components::<%= @component_type_class %>::<%= @component_name_class %> do + it_should_behave_like "a strapi graphql component", + %w[ + <%- @strapi_params.each do |param| -%> + <%= param %> + <%- end -%> + ] +end diff --git a/spec/lib/generators/strapi/component_generator_spec.rb b/spec/lib/generators/strapi/component_generator_spec.rb new file mode 100644 index 0000000000..9aea55074b --- /dev/null +++ b/spec/lib/generators/strapi/component_generator_spec.rb @@ -0,0 +1,58 @@ +require "rails_helper" +require "generator_spec" +require "generators/strapi/component_generator" + +RSpec.describe Strapi::ComponentGenerator, type: :generator do + let(:tmp_dir) { Rails.root.join("tmp/gen_test") } + tests Strapi::ComponentGenerator + destination Rails.root.join("tmp/gen_test") + + before do + FileUtils.rm_rf(tmp_dir) + prepare_destination + end + + after do + FileUtils.rm_rf(tmp_dir) + end + + context "with all arguments" do + before do + run_generator %w[gen_test blocks --strapi-params=title textContent] + end + + it "creates the query file" do + expect(File).to exist(file_path("app/services/cms/providers/strapi/queries/components/blocks/gen_test.rb")) + end + + it "creates the query test file" do + expect(File).to exist(file_path("spec/services/cms/providers/strapi/queries/components/blocks/gen_test_spec.rb")) + end + + it "creates data file" do + expect(File).to exist(file_path("app/services/cms/dynamic_components/blocks/gen_test.rb")) + end + + it "creates mock file" do + expect(File).to exist(file_path("app/services/cms/providers/strapi/mocks/dynamic_components/blocks/gen_test.rb")) + end + + it "creates component file" do + expect(File).to exist(file_path("app/components/cms/gen_test_component.rb")) + expect(File).to exist(file_path("app/components/cms/gen_test_component/gen_test_component.html.erb")) + expect(File).to exist(file_path("spec/components/cms/gen_test_component_spec.rb")) + end + + def file_path(file) + "tmp/gen_test/#{file}" + end + end + + context "with invalid type" do + it "creates the query file" do + expect { + run_generator %w[gen_test not-a-type --strapi-params=title textContent] + }.to raise_error(StandardError) + end + end +end