add base feature specs

pull/105/head
Alex Turchyn 2 years ago
parent 6b4e7c2264
commit cbc6f4497a

@ -53,10 +53,13 @@ RSpec/NestedGroups:
Max: 6
RSpec/MultipleExpectations:
Max: 7
Max: 20
RSpec/ExampleLength:
Max: 15
Max: 40
RSpec/RSpec/MultipleMemoizedHelpers:
Max: 6
Rails/I18nLocaleTexts:
Enabled: false

@ -16,16 +16,17 @@ class SetupController < ApplicationController
def create
@account = Account.new(account_params)
@account.timezone = Accounts.normalize_timezone(@account.timezone)
@user = @account.users.new(user_params)
@encrypted_config = EncryptedConfig.new(encrypted_config_params)
unless URI.parse(encrypted_config_params[:value].to_s).class.in?([URI::HTTP, URI::HTTPS])
@encrypted_config = EncryptedConfig.new(encrypted_config_params)
@encrypted_config.errors.add(:value, 'should be a valid URL')
return render :index, status: :unprocessable_entity
end
return render :index, status: :unprocessable_entity unless @account.valid?
if @user.save
encrypted_configs = [
{ key: EncryptedConfig::APP_URL_KEY, value: encrypted_config_params[:value] },

@ -10,6 +10,7 @@
data-tip="Type text"
>
<button
id="type_text_button"
class="btn btn-sm btn-circle"
:class="{ 'btn-neutral': isTextSignature, 'btn-outline': !isTextSignature }"
@click.prevent="toggleTextInput"
@ -78,6 +79,7 @@
/>
<input
v-if="isTextSignature"
id="signature_text_input"
ref="textInput"
class="base-input !text-2xl w-full mt-6"
:required="field.required"

@ -21,14 +21,18 @@
# fk_rails_... (account_id => accounts.id)
#
class EncryptedConfig < ApplicationRecord
FILES_STORAGE_KEY = 'active_storage'
EMAIL_SMTP_KEY = 'action_mailer_smtp'
ESIGN_CERTS_KEY = 'esign_certs'
APP_URL_KEY = 'app_url'
WEBHOOK_URL_KEY = 'webhook_url'
CONFIG_KEYS = [
FILES_STORAGE_KEY = 'active_storage',
EMAIL_SMTP_KEY = 'action_mailer_smtp',
ESIGN_CERTS_KEY = 'esign_certs',
APP_URL_KEY = 'app_url',
WEBHOOK_URL_KEY = 'webhook_url'
].freeze
belongs_to :account
validates :key, inclusion: { in: CONFIG_KEYS }
encrypts :value
serialize :value, JSON

@ -40,7 +40,9 @@
# fk_rails_... (account_id => accounts.id)
#
class User < ApplicationRecord
ROLES = %w[admin].freeze
ROLES = [
ADMIN_ROLE = 'admin'
].freeze
EMAIL_REGEXP = /[^@,\s]+@[^@,\s]+/
@ -51,10 +53,11 @@ class User < ApplicationRecord
devise :database_authenticatable, :recoverable, :rememberable, :validatable, :trackable
devise :registerable, :omniauthable, omniauth_providers: [:google_oauth2] if Docuseal.multitenant?
attribute :role, :string, default: 'admin'
attribute :role, :string, default: ADMIN_ROLE
attribute :uuid, :string, default: -> { SecureRandom.uuid }
scope :active, -> { where(deleted_at: nil) }
scope :admins, -> { where(role: ADMIN_ROLE) }
def access_token
super || build_access_token.tap(&:save!)

@ -59,4 +59,10 @@ Rails.application.configure do
# Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true
config.active_record.encryption = {
primary_key: 'test master key',
deterministic_key: 'test deterministic key',
key_derivation_salt: 'test key derivation salt'
}
end

@ -27,3 +27,8 @@ azure:
storage_access_key: <%= ENV['AZURE_STORAGE_ACCESS_KEY'] %>
container: <%= ENV['AZURE_CONTAINER'] %>
public: <%= ENV['ACTIVE_STORAGE_PUBLIC'] == 'true' %>
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
public: true

@ -4,6 +4,8 @@ module ActionMailerConfigsInterceptor
module_function
def delivering_email(message)
return message unless Rails.env.production?
if Docuseal.demo?
message.delivery_method(:test)

@ -18,6 +18,7 @@ module LoadActiveStorageConfigs
def reload
return if Docuseal.multitenant?
return if IS_ENV_CONFIGURED
return if Rails.env.test?
encrypted_config = EncryptedConfig.find_by(key: EncryptedConfig::FILES_STORAGE_KEY)

@ -19,7 +19,7 @@ module Submitters
SendWebhookRequestJob.perform_later(submitter)
end
submitter.submission.template.account.users.active.each do |user|
submitter.submission.template.account.users.active.admins.each do |user|
SubmitterMailer.completed_email(submitter, user).deliver_later!
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
FactoryBot.define do
factory :account do
name { Faker::Company.name }
locale { 'en-US' }
timezone { 'UTC' }
end
end

@ -0,0 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
factory :encrypted_config do
account
end
end

@ -0,0 +1,14 @@
# frozen_string_literal: true
FactoryBot.define do
factory :submission do
template
created_by_user factory: %i[user]
before(:create) do |submission, _|
submission.template_fields = submission.template.fields
submission.template_schema = submission.template.schema
submission.template_submitters = submission.template.submitters
end
end
end

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :submitter do
submission
email { Faker::Internet.email }
end
end

@ -0,0 +1,62 @@
# frozen_string_literal: true
FactoryBot.define do
factory :template do
account
author factory: %i[user]
name { Faker::Book.title }
after(:create) do |template|
blob = ActiveStorage::Blob.create_and_upload!(
io: Rails.root.join('spec/fixtures/sample-document.pdf').open,
filename: 'sample-document.pdf',
content_type: 'application/pdf'
)
attachment = ActiveStorage::Attachment.create!(
blob:,
name: :documents,
record: template
)
Templates::ProcessDocument.call(attachment)
template.schema = [{ attachment_uuid: attachment.uuid, name: 'sample-document' }]
template.submitters = [
{
'name' => 'First Submitter',
'uuid' => '513848eb-1096-4abc-a743-68596b5aaa4c'
}
]
template.fields = [
{
'uuid' => '21637fc9-0655-45df-8952-04ec64949e85',
'submitter_uuid' => '513848eb-1096-4abc-a743-68596b5aaa4c',
'name' => 'First Name',
'type' => 'text',
'required' => true,
'areas' => [
{
'x' => 0.09027777777777778,
'y' => 0.1197252208047105,
'w' => 0.3069444444444444,
'h' => 0.03336604514229637,
'attachment_uuid' => attachment.uuid,
'page' => 0
}
]
},
{
'uuid' => '1f97f8e3-dc82-4586-aeea-6ebed6204e46',
'submitter_uuid' => '513848eb-1096-4abc-a743-68596b5aaa4c',
'name' => '',
'type' => 'signature',
'required' => true,
'areas' => []
}
]
template.save!
end
end
end

@ -0,0 +1,12 @@
# frozen_string_literal: true
FactoryBot.define do
factory :user do
account
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
password { 'password' }
role { User::ADMIN_ROLE }
email { Faker::Internet.email }
end
end

Binary file not shown.

@ -7,6 +7,7 @@ require_relative '../config/environment'
abort('The Rails environment is running in production mode!') if Rails.env.production?
require 'rspec/rails'
require 'capybara/cuprite'
require 'capybara/rspec'
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
@ -45,6 +46,7 @@ RSpec.configure do |config|
config.filter_rails_from_backtrace!
config.include FactoryBot::Syntax::Methods
config.include Devise::Test::IntegrationHelpers
config.before(:each, type: :system) do
if ENV['HEADLESS'] == 'false'

@ -0,0 +1,39 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Account Settings' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
let!(:encrypted_config) { create(:encrypted_config, account:, key: EncryptedConfig::APP_URL_KEY, value: 'https://www.test.com') }
before do
sign_in(user)
visit settings_account_path
end
it 'shows pre-filled account settings page' do
expect(page).to have_content('Account')
expect(page).to have_field('Company Name', with: account.name)
expect(page).to have_field('Timezone', with: account.timezone)
expect(page).to have_field('Time format', with: account.locale)
expect(page).to have_field('App URL', with: encrypted_config.value)
end
it 'updates the account settings' do
fill_in 'Company Name', with: 'New Company Name'
fill_in 'App URL', with: 'https://example.com'
select '(GMT+01:00) Berlin', from: 'Timezone'
select 'Spanish (Spain)', from: 'Time format'
click_button 'Update'
account.reload
encrypted_config.reload
expect(account.name).to eq('New Company Name')
expect(account.timezone).to eq('Berlin')
expect(account.locale).to eq('es-ES')
expect(encrypted_config.value).to eq('https://example.com')
end
end

@ -0,0 +1,18 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'API Settings' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
before do
sign_in(user)
visit settings_api_index_path
end
it 'shows verify signed PDF page' do
expect(page).to have_content('API')
expect(page).to have_field('X-Auth-Token', with: user.access_token.token)
end
end

@ -0,0 +1,55 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Dashboard Page' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
before do
sign_in(user)
end
context 'when are no templates' do
it 'shows empty state' do
visit root_path
expect(page).to have_content('Welcome to DocuSeal')
expect(page).to have_content('Streamline document workflows, from creating customizable')
expect(page).to have_link('Create Template', href: new_template_path)
end
end
context 'when there are templates' do
let!(:authors) { create_list(:user, 5, account:) }
let!(:templates) { authors.map { |author| create(:template, account:, author:) } }
before do
visit root_path
end
it 'shows the list of templates' do
templates.each do |template|
expect(page).to have_content(template.name)
expect(page).to have_content(template.author.full_name)
end
expect(page).to have_content('Templates')
expect(page).to have_link('Create', href: new_template_path)
end
it 'initializes the template creation process' do
click_link 'Create'
within('#modal') do
fill_in 'template[name]', with: 'New Template'
expect do
click_button 'Create'
end.to change(Template, :count).by(1)
expect(page).to have_current_path(edit_template_path(Template.last), ignore_query: true)
end
end
end
end

@ -0,0 +1,98 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Email Settings' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
before do
sign_in(user)
end
context 'when SMTP settings are not set' do
it 'setup SMTP settings' do
visit settings_email_index_path
fill_in 'Host', with: 'smtp.example.com'
fill_in 'Port', with: '587'
fill_in 'Username', with: 'user@example.com'
fill_in 'Password', with: 'password'
fill_in 'Domain', with: 'example.com'
fill_in 'Send from Email', with: 'user@example.com'
select 'Plain', from: 'Authentication'
choose 'TLS'
expect do
click_button 'Save'
end.to change(EncryptedConfig, :count).by(1)
encrypted_config = EncryptedConfig.find_by(account:, key: EncryptedConfig::EMAIL_SMTP_KEY)
expect(encrypted_config.value['host']).to eq('smtp.example.com')
expect(encrypted_config.value['port']).to eq('587')
expect(encrypted_config.value['username']).to eq('user@example.com')
expect(encrypted_config.value['password']).to eq('password')
expect(encrypted_config.value['domain']).to eq('example.com')
expect(encrypted_config.value['authentication']).to eq('plain')
expect(encrypted_config.value['security']).to eq('tls')
expect(encrypted_config.value['from_email']).to eq('user@example.com')
end
end
context 'when SMTP settings are set' do
let!(:encrypted_config) do
create(:encrypted_config, account:, key: EncryptedConfig::EMAIL_SMTP_KEY, value: {
host: 'smtp.example.com',
port: '587',
username: 'user@example.co',
password: 'password',
domain: 'example.com',
authentication: 'plain',
security: 'tls',
from_email: 'user@example.co'
})
end
before do
visit settings_email_index_path
end
it 'shows pre-filled SMTP settings' do
expect(page).to have_content('Email SMTP')
expect(page).to have_field('Host', with: encrypted_config.value['host'])
expect(page).to have_field('Port', with: encrypted_config.value['port'])
expect(page).to have_field('Username', with: encrypted_config.value['username'])
expect(page).to have_field('Password', with: encrypted_config.value['password'])
expect(page).to have_field('Domain', with: encrypted_config.value['domain'])
expect(page).to have_select('Authentication', selected: 'Plain')
expect(page).to have_field('Send from Email', with: encrypted_config.value['from_email'])
end
it 'updates SMTP settings' do
fill_in 'Host', with: 'smtp.gmail.com'
fill_in 'Port', with: '465'
fill_in 'Username', with: 'user@gmail.com'
fill_in 'Password', with: 'new_password'
fill_in 'Domain', with: 'gmail.com'
fill_in 'Send from Email', with: 'user@gmail.com'
select 'Plain', from: 'Authentication'
choose 'SSL'
expect do
click_button 'Save'
end.not_to change(EncryptedConfig, :count)
encrypted_config.reload
expect(encrypted_config.value['host']).to eq('smtp.gmail.com')
expect(encrypted_config.value['port']).to eq('465')
expect(encrypted_config.value['username']).to eq('user@gmail.com')
expect(encrypted_config.value['password']).to eq('new_password')
expect(encrypted_config.value['domain']).to eq('gmail.com')
expect(encrypted_config.value['authentication']).to eq('plain')
expect(encrypted_config.value['security']).to eq('ssl')
expect(encrypted_config.value['from_email']).to eq('user@gmail.com')
end
end
end

@ -0,0 +1,20 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'PDF Signature Settings' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
before do
sign_in(user)
visit settings_esign_index_path
end
it 'shows verify signed PDF page' do
expect(page).to have_content('PDF Signature')
expect(page).to have_content('Upload signed PDF file to validate its signature')
expect(page).to have_content('Verify Signed PDF')
expect(page).to have_content('Click to upload or drag and drop files')
end
end

@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Newsletter' do
let(:user) { create(:user, account: create(:account)) }
before do
sign_in(user)
stub_request(:post, Docuseal::NEWSLETTER_URL).to_return(status: 200)
visit newsletter_path
end
it 'shows the newsletter page' do
expect(page).to have_content('Developer Newsletters')
expect(page).to have_button('Submit')
expect(page).to have_content('Skip')
expect(page).to have_field('user[email]', with: user.email)
end
it 'submits the newsletter form' do
click_button 'Submit'
expect(a_request(:post, Docuseal::NEWSLETTER_URL)).to have_been_made.once
end
it 'skips the newsletter form' do
click_on 'Skip'
expect(page).to have_current_path(root_path, ignore_query: true)
end
end

@ -0,0 +1,23 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Personalization' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
before do
sign_in(user)
visit settings_personalization_path
end
it 'shows the personalization page' do
expect(page).to have_content('Email Templates')
expect(page).to have_content('Signature Request Email')
expect(page).to have_content('Form Completed Email')
expect(page).to have_content('Documents Copy Email')
expect(page).to have_content('Company Logo')
expect(page).to have_content('Unlock with DocuSeal Enterprise')
expect(page).to have_content('Display your company name and logo when signing documents')
end
end

@ -0,0 +1,59 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Profile Settings' do
let(:user) { create(:user, account: create(:account)) }
before do
sign_in(user)
visit settings_profile_index_path
end
it 'shows the profile settings page' do
expect(page).to have_content('Profile')
expect(page).to have_field('user[email]', with: user.email)
expect(page).to have_field('user[first_name]', with: user.first_name)
expect(page).to have_field('user[last_name]', with: user.last_name)
expect(page).to have_content('Change Password')
expect(page).to have_field('user[password]')
expect(page).to have_field('user[password_confirmation]')
end
context 'when changes contact information' do
it 'updates first name, last name and email' do
fill_in 'First name', with: 'Devid'
fill_in 'Last name', with: 'Beckham'
fill_in 'Email', with: 'david.beckham@example.com'
all(:button, 'Update')[0].click
user.reload
expect(user.first_name).to eq('Devid')
expect(user.last_name).to eq('Beckham')
expect(user.email).to eq('david.beckham@example.com')
end
end
context 'when changes password' do
it 'updates password' do
fill_in 'New password', with: 'newpassword'
fill_in 'Confirm new password', with: 'newpassword'
all(:button, 'Update')[1].click
expect(page).to have_content('Password has been changed')
end
it 'does not update if password confirmation does not match' do
fill_in 'New password', with: 'newpassword'
fill_in 'Confirm new password', with: 'newpassword1'
all(:button, 'Update')[1].click
expect(page).to have_content("Password confirmation doesn't match Password")
end
end
end

@ -0,0 +1,88 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'App Setup', js: true do
let(:form_data) do
{
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
company_name: 'Example Company',
password: 'password',
app_url: 'https://example.com'
}
end
before do
visit setup_index_path
end
it 'shows the setup page' do
expect(page).to have_content('Initial Setup')
['First name', 'Last name', 'Email', 'Company name', 'Password', 'App URL'].each do |field|
expect(page).to have_field(field)
end
end
context 'when valid information' do
it 'setups the app' do
fill_setup_form(form_data)
expect do
click_button 'Submit'
sleep 1
end.to change(Account, :count).by(1).and change(User, :count).by(1).and change(EncryptedConfig, :count).by(2)
user = User.last
encrypted_config_app_url = EncryptedConfig.find_by(account: user.account,
key: EncryptedConfig::APP_URL_KEY)
encrypted_config_esign_certs = EncryptedConfig.find_by(account: user.account,
key: EncryptedConfig::ESIGN_CERTS_KEY)
expect(user.first_name).to eq(form_data[:first_name])
expect(user.last_name).to eq(form_data[:last_name])
expect(user.email).to eq(form_data[:email])
expect(user.account.timezone).to eq('UTC')
expect(user.account.locale).to eq('en-US')
expect(user.account.name).to eq(form_data[:company_name])
expect(encrypted_config_app_url.value).to eq(form_data[:app_url])
expect(encrypted_config_esign_certs.value).to be_present
end
end
context 'when invalid information' do
it 'does not setup the app if the password is too short' do
fill_setup_form(form_data.merge(password: 'pass'))
expect do
click_button 'Submit'
end.not_to(change(User, :count))
expect(page).to have_content('Password is too short (minimum is 6 characters)')
end
end
context 'when the app is already setup' do
let!(:user) { create(:user, account: create(:account)) }
it 'redirects to the dashboard page' do
sign_in(user)
visit setup_index_path
expect(page).to have_content('Welcome to DocuSeal')
end
end
private
def fill_setup_form(form_data)
fill_in 'First name', with: form_data[:first_name]
fill_in 'Last name', with: form_data[:last_name]
fill_in 'Email', with: form_data[:email]
fill_in 'Company name', with: form_data[:company_name]
fill_in 'Password', with: form_data[:password]
fill_in 'App URL', with: form_data[:app_url]
end
end

@ -0,0 +1,247 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Storage Settings' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
before do
sign_in(user)
end
context 'when storage settings are not set' do
before do
visit settings_storage_index_path
end
context 'when Disk is selected' do
it 'shows default storage settings page' do
expect(page).to have_content('Storage')
expect(page).to have_content('Store all files on disk')
expect(page).to have_content('No configs are needed but make sure your disk is persistent')
expect(page).to have_checked_field('Disk')
end
end
context 'when AWS S3 is selected' do
it 'setups AWS S3 storage settings' do
choose 'AWS'
fill_in 'Access key ID', with: 'access_key_id'
fill_in 'Secret access key', with: 'secret_access_key'
fill_in 'Region', with: 'us-west-1'
fill_in 'Bucket', with: 'bucket'
fill_in 'Endpoint', with: 'https://s3.us-west-1.amazonaws.com'
expect do
click_button 'Save'
end.to change(EncryptedConfig, :count).by(1)
encrypted_config = EncryptedConfig.find_by(account:, key: EncryptedConfig::FILES_STORAGE_KEY)
configs = encrypted_config.value['configs']
expect(encrypted_config.value['service']).to eq('aws_s3')
expect(configs['access_key_id']).to eq('access_key_id')
expect(configs['secret_access_key']).to eq('secret_access_key')
expect(configs['region']).to eq('us-west-1')
expect(configs['bucket']).to eq('bucket')
expect(configs['endpoint']).to eq('https://s3.us-west-1.amazonaws.com')
end
end
context 'when Google Cloud Storage is selected' do
it 'setups Google Cloud Storage settings' do
choose 'GCP'
fill_in 'Project', with: 'project_id'
fill_in 'Bucket', with: 'bucket'
fill_in 'Credentials (JSON key content)', with: '{ "type": "service_account", "project_id": "project_id" }'
expect do
click_button 'Save'
end.to change(EncryptedConfig, :count).by(1)
encrypted_config = EncryptedConfig.find_by(account:, key: EncryptedConfig::FILES_STORAGE_KEY)
configs = encrypted_config.value['configs']
expect(encrypted_config.value['service']).to eq('google')
expect(configs['project']).to eq('project_id')
expect(configs['bucket']).to eq('bucket')
expect(configs['credentials']).to eq('{ "type": "service_account", "project_id": "project_id" }')
end
end
context 'when Azure is selected' do
it 'setup Azure storage settings' do
choose 'Azure'
fill_in 'Storage Account Name', with: 'storage_account_name'
fill_in 'Container', with: 'container'
fill_in 'Storage Access Key', with: 'storage_access_key'
expect do
click_button 'Save'
end.to change(EncryptedConfig, :count).by(1)
encrypted_config = EncryptedConfig.find_by(account:, key: EncryptedConfig::FILES_STORAGE_KEY)
configs = encrypted_config.value['configs']
expect(encrypted_config.value['service']).to eq('azure')
expect(configs['storage_account_name']).to eq('storage_account_name')
expect(configs['container']).to eq('container')
expect(configs['storage_access_key']).to eq('storage_access_key')
end
end
end
context 'when storage settings are set' do
context 'when updates the same storage settings' do
context 'when AWS S3' do
let!(:encrypted_config) do
create(:encrypted_config, account:, key: EncryptedConfig::FILES_STORAGE_KEY, value: {
service: 'aws_s3',
configs: {
access_key_id: 'access_key_id',
secret_access_key: 'secret_access_key',
region: 'us-west-1',
bucket: 'bucket',
endpoint: 'https://s3.us-west-1.amazonaws.com'
}
})
end
it 'updates AWS S3 storage settings' do
visit settings_storage_index_path
fill_in 'Access key ID', with: 'new_access_key_id'
fill_in 'Secret access key', with: 'new_secret_access_key'
fill_in 'Region', with: 'us-west-2'
fill_in 'Bucket', with: 'new_bucket'
fill_in 'Endpoint', with: 'https://s3.us-west-2.amazonaws.com'
expect do
click_button 'Save'
end.not_to(change(EncryptedConfig, :count))
encrypted_config.reload
configs = encrypted_config.value['configs']
expect(encrypted_config.value['service']).to eq('aws_s3')
expect(configs['access_key_id']).to eq('new_access_key_id')
expect(configs['secret_access_key']).to eq('new_secret_access_key')
expect(configs['region']).to eq('us-west-2')
expect(configs['bucket']).to eq('new_bucket')
expect(configs['endpoint']).to eq('https://s3.us-west-2.amazonaws.com')
end
end
context 'when Google Cloud Storage' do
let!(:encrypted_config) do
create(:encrypted_config, account:, key: EncryptedConfig::FILES_STORAGE_KEY, value: {
service: 'google',
configs: {
project: 'project_id',
bucket: 'bucket',
credentials: '{ "type": "service_account", "project_id": "project_id" }'
}
})
end
it 'updates Google Cloud Storage settings' do
visit settings_storage_index_path
fill_in 'Project', with: 'new_project_id'
fill_in 'Bucket', with: 'new_bucket'
fill_in 'Credentials (JSON key content)',
with: '{ "type": "new_service_account", "project_id": "new_project_id" }'
expect do
click_button 'Save'
end.not_to(change(EncryptedConfig, :count))
encrypted_config.reload
configs = encrypted_config.value['configs']
expect(encrypted_config.value['service']).to eq('google')
expect(configs['project']).to eq('new_project_id')
expect(configs['bucket']).to eq('new_bucket')
expect(configs['credentials']).to eq('{ "type": "new_service_account", "project_id": "new_project_id" }')
end
end
context 'when Azure' do
let!(:encrypted_config) do
create(:encrypted_config, account:, key: EncryptedConfig::FILES_STORAGE_KEY, value: {
service: 'azure',
configs: {
storage_account_name: 'storage_account_name',
container: 'container',
storage_access_key: 'storage_access_key'
}
})
end
it 'updates Azure storage settings' do
visit settings_storage_index_path
fill_in 'Storage Account Name', with: 'new_storage_account_name'
fill_in 'Container', with: 'new_container'
fill_in 'Storage Access Key', with: 'new_storage_access_key'
expect do
click_button 'Save'
end.not_to(change(EncryptedConfig, :count))
encrypted_config.reload
configs = encrypted_config.value['configs']
expect(encrypted_config.value['service']).to eq('azure')
expect(configs['storage_account_name']).to eq('new_storage_account_name')
expect(configs['container']).to eq('new_container')
expect(configs['storage_access_key']).to eq('new_storage_access_key')
end
end
end
context 'when switches to another storage settings' do
context 'when Google Cloud Storage' do
let!(:encrypted_config) do
create(:encrypted_config, account:, key: EncryptedConfig::FILES_STORAGE_KEY, value: {
service: 'google',
configs: {
project: 'project_id',
bucket: 'bucket',
credentials: '{ "type": "service_account", "project_id": "project_id" }'
}
})
end
it 'switches to AWS S3' do
visit settings_storage_index_path
choose 'AWS'
fill_in 'Access key ID', with: 'access_key_id'
fill_in 'Secret access key', with: 'secret_access_key'
fill_in 'Region', with: 'us-west-1'
fill_in 'Bucket', with: 'bucket'
fill_in 'Endpoint', with: 'https://s3.us-west-1.amazonaws.com'
expect do
click_button 'Save'
end.not_to(change(EncryptedConfig, :count))
encrypted_config.reload
configs = encrypted_config.value['configs']
expect(encrypted_config.value['service']).to eq('aws_s3')
expect(configs['access_key_id']).to eq('access_key_id')
expect(configs['secret_access_key']).to eq('secret_access_key')
expect(configs['region']).to eq('us-west-1')
expect(configs['bucket']).to eq('bucket')
expect(configs['endpoint']).to eq('https://s3.us-west-1.amazonaws.com')
end
end
end
end
end

@ -0,0 +1,95 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Submit Form' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
let!(:template) { create(:template, account:, author: user) }
before do
sign_in(user)
end
context 'when initialized by shared link' do
before do
visit start_form_path(slug: template.slug)
end
it 'shows start form page' do
expect(page).to have_content('You have been invited to submit a form')
expect(page).to have_content(template.name)
expect(page).to have_content("Invited by #{template.account.name}")
end
it 'complete the form' do
fill_in 'Email', with: 'john.dou@example.com'
click_button 'Start'
fill_in 'First Name', with: 'Adam'
click_on 'Next'
click_on 'type_text_button'
fill_in 'signature_text_input', with: 'Adam'
expect do
click_on 'Submit'
end.not_to(change(Submitter, :count))
submitter = Submitter.find_by(email: 'john.dou@example.com')
expect(page).to have_button('Download')
expect(submitter.email).to eq('john.dou@example.com')
expect(submitter.ip).to eq('127.0.0.1')
expect(submitter.ua).to be_present
expect(submitter.opened_at).to be_present
expect(submitter.completed_at).to be_present
expect(submitter.values.values).to include('Adam')
end
end
context 'when initialized by shared email address' do
let!(:submission) { create(:submission, template:, created_by_user: user) }
let!(:submitters) { template.submitters.map { |s| create(:submitter, submission:, uuid: s['uuid']) } }
let(:submitter) { submitters.first }
before do
visit submit_form_path(slug: submitter.slug)
end
it 'completes the form' do
fill_in 'First Name', with: 'Sally'
click_on 'Next'
click_on 'type_text_button'
fill_in 'signature_text_input', with: 'Sally'
click_on 'Submit'
submitter.reload
expect(page).to have_button('Download')
expect(submitter.ip).to eq('127.0.0.1')
expect(submitter.ua).to be_present
expect(submitter.opened_at).to be_present
expect(submitter.completed_at).to be_present
expect(submitter.values.values).to include('Sally')
end
it 'sends completed email' do
fill_in 'First Name', with: 'Adam'
click_on 'Next'
click_on 'type_text_button'
fill_in 'signature_text_input', with: 'Adam'
expect do
click_on 'Submit'
end.to change { ActionMailer::Base.deliveries.size }.by(1)
email = ActionMailer::Base.deliveries.last
expect(email.subject).to eq("#{submitter.email} has completed the \"#{template.name}\" form")
expect(email.body.encoded).to include "Hi #{user.first_name},"
expect(email.body.encoded).to include "#{submitter.email} has completed the \"#{template.name}\" form."
expect(email.body.encoded).to have_link('View Submission')
end
end
end

@ -0,0 +1,96 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Team Settings' do
let(:account) { create(:account) }
let(:current_user) { create(:user, account:) }
before do
sign_in(current_user)
end
context 'when multiple users' do
let!(:users) { create_list(:user, 2, account:) }
before do
visit settings_users_path
end
it 'shows all users' do
within '.table' do
users.each do |user|
expect(page).to have_content(user.full_name)
expect(page).to have_content(user.email)
end
end
end
it 'creates a new user' do
click_link 'New User'
within '#modal' do
fill_in 'First name', with: 'Joseph'
fill_in 'Last name', with: 'Smith'
fill_in 'Email', with: 'joseph.smith@example.com'
fill_in 'Password', with: 'password'
expect do
click_button 'Submit'
end.to change(User, :count).by(1)
user = User.last
expect(user.first_name).to eq('Joseph')
expect(user.last_name).to eq('Smith')
expect(user.email).to eq('joseph.smith@example.com')
expect(user.account).to eq(account)
end
end
it 'updates a user' do
first(:link, 'Edit').click
fill_in 'First name', with: 'Adam'
fill_in 'Last name', with: 'Meier'
fill_in 'Email', with: 'adam.meier@example.com'
fill_in 'Password', with: 'new_password'
expect do
click_button 'Submit'
end.not_to change(User, :count)
user = User.find_by(email: 'adam.meier@example.com')
expect(user.first_name).to eq('Adam')
expect(user.last_name).to eq('Meier')
expect(user.email).to eq('adam.meier@example.com')
end
it 'removes a user' do
expect do
accept_confirm('Are you sure?') do
first(:link, 'Delete').click
end
end.to change { User.active.count }.by(-1)
expect(page).to have_content('User has been removed')
end
end
context 'when single user' do
before do
visit settings_users_path
end
it 'does not allow to remove the current user' do
expect do
accept_confirm('Are you sure?') do
first(:link, 'Delete').click
end
end.not_to(change { User.admins.count })
expect(page).to have_content('Unable to remove user')
end
end
end

@ -0,0 +1,80 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Template' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
let!(:template) { create(:template, account:, author: user) }
before do
sign_in(user)
end
context 'when no submissions' do
it 'shows the template page' do
visit template_path(template)
expect(page).to have_content(template.name)
expect(page).to have_content('There are no Submissions')
expect(page).to have_content('Send an invitation to fill and complete the form')
expect(page).to have_link('Add Recipients', href: new_template_submission_path(template))
expect(page).to have_link('Submit it Yourself')
end
end
context 'when there are submissions' do
let!(:submission) { create(:submission, template:, created_by_user: user) }
let!(:submitters) { template.submitters.map { |s| create(:submitter, submission:, uuid: s['uuid']) } }
it 'shows the template page with submissions' do
visit template_path(template)
submitters.each do |submitter|
expect(page).to have_content(submitter.email)
end
expect(page).to have_content(template.name)
end
end
context 'when managing a template' do
before do
visit template_path(template)
end
it 'removes a template' do
expect do
accept_confirm('Are you sure?') do
click_button 'Remove'
end
end.to change { Template.active.count }.by(-1)
expect(page).to have_content('Template has been archived')
expect(page).to have_current_path(root_path, ignore_query: true)
end
it 'edits a template' do
click_link 'Edit'
expect(page).to have_current_path(edit_template_path(template), ignore_query: true)
end
it 'clones a template' do
click_link 'Clone'
within '#modal' do
fill_in 'template[name]', with: 'New Template Name'
expect do
click_button 'Submit'
end.to change { Template.active.count }.by(1)
template = Template.last
expect(template.name).to eq('New Template Name')
expect(page).to have_current_path(edit_template_path(template), ignore_query: true)
end
end
end
end

@ -0,0 +1,31 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Webhook Settings' do
let!(:account) { create(:account) }
let!(:user) { create(:user, account:) }
before do
sign_in(user)
visit settings_webhooks_path
end
it 'shows webhook settings page' do
expect(page).to have_content('Webhooks')
expect(page).to have_field('Webhook URL')
expect(page).to have_button('Save')
end
it 'updates the webhook URL' do
fill_in 'Webhook URL', with: 'https://example.com'
expect do
click_button 'Save'
end.to change(EncryptedConfig, :count).by(1)
encrypted_config = EncryptedConfig.find_by(account:, key: EncryptedConfig::WEBHOOK_URL_KEY)
expect(encrypted_config.value).to eq('https://example.com')
end
end
Loading…
Cancel
Save