mirror of
https://github.com/usetrmnl/terminus.git
synced 2026-08-13 14:29:27 -07:00
Added designs importer
Necessary to handle the validation and importing of data into the database for a design (screen template). Milestone: minor
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "core"
|
||||
require "dry/monads"
|
||||
require "initable"
|
||||
require "pipeable"
|
||||
require "yaml"
|
||||
|
||||
module Terminus
|
||||
module Aspects
|
||||
module Designs
|
||||
# Imports (creates) screen template from zip file.
|
||||
class Importer
|
||||
include Deps["aspects.unzipper", :logger, repository: "repositories.screen_template"]
|
||||
include Initable[
|
||||
key_map: {
|
||||
"configuration.yml" => :configuration,
|
||||
"index.html.liquid" => :content
|
||||
},
|
||||
problem: Aspects::Errors::Problem
|
||||
]
|
||||
include Dry::Monads[:result]
|
||||
include Pipeable
|
||||
|
||||
def initialize(
|
||||
schema: Schemas::Designs::Import,
|
||||
error_joiner: Aspects::Errors::ResultJoiner,
|
||||
**
|
||||
)
|
||||
@schema = schema
|
||||
@error_joiner = error_joiner
|
||||
super(**)
|
||||
end
|
||||
|
||||
def call io
|
||||
process io
|
||||
rescue ROM::SQL::UniqueConstraintError => error
|
||||
Failure problem.duplicate(error.message, nil).detail
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :schema, :error_joiner
|
||||
|
||||
def process io
|
||||
pipe(
|
||||
unzipper.call(io),
|
||||
fmap { |entries| transform entries },
|
||||
validate(schema),
|
||||
amap { error_joiner.call "Import", it },
|
||||
fmap { create it.to_h }
|
||||
)
|
||||
end
|
||||
|
||||
def transform entries
|
||||
entries.transform_keys!(key_map).then { {**it, **YAML.load(it[:configuration])} }
|
||||
end
|
||||
|
||||
def create attributes
|
||||
repository.create(attributes).tap { |screen_template| log screen_template }
|
||||
end
|
||||
|
||||
def log screen_template
|
||||
logger.debug do
|
||||
{tags: [{screen_template_id: screen_template.id}], message: "Imported design."}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "hanami_helper"
|
||||
|
||||
RSpec.describe Terminus::Aspects::Designs::Importer, :db do
|
||||
subject(:creator) { described_class.new }
|
||||
|
||||
describe "#call" do
|
||||
let :io do
|
||||
manifest = {"configuration.yml" => configuration, "index.html.liquid" => "<h1>Test</h1>"}
|
||||
Terminus::Aspects::Zipper.new.call(manifest).value!
|
||||
end
|
||||
|
||||
let :configuration do
|
||||
<<~CONTENT
|
||||
version: 1.2.3
|
||||
name: test
|
||||
label: Test
|
||||
CONTENT
|
||||
end
|
||||
|
||||
it "creates screen template" do
|
||||
relation = Hanami.app["relations.screen_template"]
|
||||
expectation = proc { creator.call io }
|
||||
count = proc { relation.count }
|
||||
|
||||
expect(&expectation).to change(&count).by(1)
|
||||
end
|
||||
|
||||
it "answers success" do
|
||||
expect(creator.call(io)).to match(Success(kind_of(Terminus::Structs::ScreenTemplate)))
|
||||
end
|
||||
|
||||
context "with invalid configuration" do
|
||||
let(:configuration) { "version: 1.2.3" }
|
||||
|
||||
it "answers failure configuration is missing keys" do
|
||||
expect(creator.call(io)).to be_failure("Import name is missing and label is missing.")
|
||||
end
|
||||
end
|
||||
|
||||
it "answers failure when screen template isn't unique" do
|
||||
Factory[:screen_template, name: "test"]
|
||||
|
||||
expect(creator.call(io)).to be_failure(
|
||||
%(Name must be unique. Please use a value other than "test".)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user