fat_free_crm 0.19.2 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fat_free_crm might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/brakeman-analysis.yml +46 -0
- data/.github/workflows/rubocop-analysis.yml +40 -0
- data/.github/workflows/ruby.yml +52 -0
- data/.rubocop_todo.yml +49 -43
- data/.travis.yml +1 -20
- data/CHANGELOG.md +13 -0
- data/Gemfile +9 -5
- data/Gemfile.lock +163 -119
- data/README.md +4 -3
- data/SECURITY.md +11 -0
- data/app/assets/javascripts/application.js.erb +3 -0
- data/app/assets/stylesheets/application.css.erb +1 -0
- data/app/assets/stylesheets/base.scss +9 -2
- data/app/assets/stylesheets/bootstrap-custom.scss +206 -0
- data/app/assets/stylesheets/common.scss +87 -67
- data/app/assets/stylesheets/header.scss +0 -8
- data/app/controllers/admin/field_groups_controller.rb +1 -1
- data/app/controllers/admin/fields_controller.rb +1 -1
- data/app/controllers/admin/groups_controller.rb +1 -1
- data/app/controllers/admin/tags_controller.rb +2 -2
- data/app/controllers/admin/users_controller.rb +2 -1
- data/app/controllers/application_controller.rb +10 -0
- data/app/controllers/comments_controller.rb +1 -1
- data/app/controllers/entities/accounts_controller.rb +1 -1
- data/app/controllers/entities/campaigns_controller.rb +1 -1
- data/app/controllers/home_controller.rb +3 -1
- data/app/controllers/lists_controller.rb +1 -1
- data/app/controllers/tasks_controller.rb +3 -3
- data/app/controllers/users_controller.rb +3 -1
- data/app/helpers/accounts_helper.rb +12 -0
- data/app/helpers/application_helper.rb +3 -5
- data/app/helpers/tasks_helper.rb +2 -2
- data/app/models/entities/account.rb +1 -1
- data/app/models/entities/account_contact.rb +1 -1
- data/app/models/entities/account_opportunity.rb +1 -1
- data/app/models/entities/campaign.rb +1 -1
- data/app/models/entities/contact.rb +1 -1
- data/app/models/entities/lead.rb +1 -1
- data/app/models/entities/opportunity.rb +1 -1
- data/app/models/fields/custom_field_pair.rb +2 -2
- data/app/models/observers/opportunity_observer.rb +1 -1
- data/app/models/polymorphic/address.rb +1 -1
- data/app/models/polymorphic/comment.rb +1 -1
- data/app/models/polymorphic/email.rb +1 -1
- data/app/models/polymorphic/task.rb +1 -1
- data/app/models/setting.rb +4 -2
- data/app/models/users/preference.rb +2 -2
- data/app/models/users/user.rb +2 -2
- data/app/views/accounts/_edit.html.haml +2 -2
- data/app/views/accounts/_new.html.haml +2 -2
- data/app/views/accounts/_sidebar_index.html.haml +2 -2
- data/app/views/accounts/_sidebar_show.html.haml +19 -19
- data/app/views/accounts/create.js.haml +1 -2
- data/app/views/accounts/destroy.js.haml +1 -1
- data/app/views/accounts/show.html.haml +1 -0
- data/app/views/accounts/update.js.haml +2 -3
- data/app/views/admin/field_groups/create.js.haml +0 -1
- data/app/views/admin/field_groups/destroy.js.haml +0 -1
- data/app/views/admin/field_groups/update.js.haml +0 -1
- data/app/views/admin/fields/create.js.haml +0 -1
- data/app/views/admin/fields/destroy.js.haml +0 -1
- data/app/views/admin/fields/update.js.haml +0 -1
- data/app/views/admin/groups/create.js.haml +0 -1
- data/app/views/admin/groups/destroy.js.haml +0 -1
- data/app/views/admin/groups/update.js.haml +0 -1
- data/app/views/admin/tags/create.js.haml +0 -1
- data/app/views/admin/tags/destroy.js.haml +0 -1
- data/app/views/admin/tags/update.js.haml +0 -1
- data/app/views/admin/users/create.js.haml +0 -1
- data/app/views/admin/users/destroy.js.haml +0 -1
- data/app/views/admin/users/update.js.haml +0 -1
- data/app/views/campaigns/_edit.html.haml +1 -1
- data/app/views/campaigns/_new.html.haml +1 -1
- data/app/views/campaigns/_sidebar_index.html.haml +2 -2
- data/app/views/campaigns/_sidebar_show.html.haml +68 -67
- data/app/views/campaigns/create.js.haml +1 -2
- data/app/views/campaigns/destroy.js.haml +1 -1
- data/app/views/campaigns/show.html.haml +1 -0
- data/app/views/campaigns/update.js.haml +3 -4
- data/app/views/comments/_edit.html.haml +1 -1
- data/app/views/comments/_new.html.haml +1 -1
- data/app/views/comments/update.js.haml +0 -1
- data/app/views/contacts/_edit.html.haml +1 -1
- data/app/views/contacts/_new.html.haml +1 -1
- data/app/views/contacts/_sidebar_show.html.haml +18 -18
- data/app/views/contacts/create.js.haml +0 -1
- data/app/views/contacts/destroy.js.haml +1 -1
- data/app/views/contacts/show.html.haml +1 -0
- data/app/views/contacts/update.js.haml +2 -3
- data/app/views/entities/_title_bar.html.haml +1 -1
- data/app/views/entities/attach.js.haml +2 -2
- data/app/views/entities/discard.js.haml +2 -2
- data/app/views/home/_opportunity.html.haml +1 -1
- data/app/views/home/_task.html.haml +1 -1
- data/app/views/home/index.xls.builder +51 -0
- data/app/views/layouts/_sidebar.html.haml +2 -2
- data/app/views/layouts/_tabbed.html.haml +14 -11
- data/app/views/layouts/application.html.haml +2 -2
- data/app/views/leads/_edit.html.haml +2 -2
- data/app/views/leads/_new.html.haml +2 -2
- data/app/views/leads/_sidebar_index.html.haml +2 -2
- data/app/views/leads/_sidebar_show.html.haml +30 -30
- data/app/views/leads/create.js.haml +2 -3
- data/app/views/leads/destroy.js.haml +2 -2
- data/app/views/leads/promote.js.haml +3 -4
- data/app/views/leads/reject.js.haml +3 -3
- data/app/views/leads/show.html.haml +1 -1
- data/app/views/leads/update.js.haml +4 -5
- data/app/views/lists/create.js.haml +0 -1
- data/app/views/opportunities/_edit.html.haml +1 -1
- data/app/views/opportunities/_index_brief.html.haml +1 -1
- data/app/views/opportunities/_index_long.html.haml +1 -1
- data/app/views/opportunities/_new.html.haml +1 -1
- data/app/views/opportunities/_sidebar_index.html.haml +2 -2
- data/app/views/opportunities/_sidebar_show.html.haml +47 -46
- data/app/views/opportunities/create.js.haml +3 -4
- data/app/views/opportunities/destroy.js.haml +3 -3
- data/app/views/opportunities/show.html.haml +1 -0
- data/app/views/opportunities/update.js.haml +5 -6
- data/app/views/shared/_inline_styles.html.haml +0 -26
- data/app/views/tasks/_assigned.html.haml +1 -1
- data/app/views/tasks/_completed.html.haml +1 -1
- data/app/views/tasks/_edit.html.haml +1 -1
- data/app/views/tasks/_new.html.haml +1 -1
- data/app/views/tasks/_pending.html.haml +1 -1
- data/app/views/tasks/_related.html.haml +1 -1
- data/app/views/tasks/_selector.html.haml +7 -8
- data/app/views/tasks/_sidebar_index.html.haml +2 -2
- data/app/views/tasks/_title.html.haml +1 -1
- data/app/views/tasks/complete.js.haml +1 -1
- data/app/views/tasks/create.js.haml +1 -2
- data/app/views/tasks/destroy.js.haml +1 -1
- data/app/views/tasks/uncomplete.js.haml +1 -2
- data/app/views/tasks/update.js.haml +0 -1
- data/app/views/users/change_password.js.haml +0 -1
- data/app/views/users/update.js.haml +0 -1
- data/app/views/users/upload_avatar.js.haml +0 -1
- data/app/views/versions/_version_item.html.haml +1 -1
- data/bin/setup +6 -6
- data/config/application.rb +1 -1
- data/config/environment.rb +1 -1
- data/config/initializers/content_security_policy.rb +5 -0
- data/config/initializers/new_framework_defaults_6_0.rb +46 -0
- data/config/initializers/simple_form.rb +135 -55
- data/config/initializers/simple_form_bootstrap.rb +433 -0
- data/config/locales/fat_free_crm.cs.yml +86 -47
- data/config/locales/fat_free_crm.ru.yml +1 -0
- data/config/settings.default.yml +0 -41
- data/db/migrate/20200806004152_add_pattern_to_fields.rb +7 -0
- data/db/migrate/20200806004459_add_html5_to_fields.rb +10 -0
- data/db/schema.rb +11 -6
- data/fat_free_crm.gemspec +4 -4
- data/lib/fat_free_crm/core_ext.rb +1 -1
- data/lib/fat_free_crm/gem_ext.rb +0 -1
- data/lib/fat_free_crm/tabs.rb +2 -2
- data/lib/fat_free_crm/version.rb +2 -2
- data/lib/gravatar_image_tag.rb +1 -1
- data/lib/tasks/ffcrm/preference_update.rake +19 -0
- data/lib/tasks/ffcrm/setup.rake +1 -1
- data/lib/templates/erb/scaffold/_form.html.erb +4 -2
- data/spec/controllers/comments_controller_spec.rb +6 -6
- data/spec/controllers/home_controller_spec.rb +3 -3
- data/spec/controllers/users_controller_spec.rb +13 -1
- data/spec/factories/user_factories.rb +5 -2
- data/spec/features/acceptance_helper.rb +1 -1
- data/spec/features/accounts_spec.rb +2 -2
- data/spec/features/admin/groups_spec.rb +1 -1
- data/spec/features/admin/users_spec.rb +1 -1
- data/spec/features/campaigns_spec.rb +2 -2
- data/spec/features/contacts_spec.rb +2 -5
- data/spec/features/leads_spec.rb +11 -7
- data/spec/features/opportunities_spec.rb +4 -4
- data/spec/features/support/browser.rb +6 -2
- data/spec/features/support/selector_helpers.rb +10 -1
- data/spec/features/tasks_spec.rb +6 -6
- data/spec/helpers/accounts_helper_spec.rb +57 -0
- data/spec/models/entities/opportunity_spec.rb +2 -2
- data/spec/models/fields/custom_field_pair_spec.rb +2 -2
- data/spec/models/observers/entity_observer_spec.rb +3 -3
- data/spec/models/polymorphic/task_spec.rb +11 -11
- data/spec/models/polymorphic/version_spec.rb +2 -2
- data/spec/models/users/preference_spec.rb +1 -1
- data/spec/views/accounts/_edit.haml_spec.rb +1 -1
- data/spec/views/accounts/_new.haml_spec.rb +1 -1
- data/spec/views/accounts/create.js.haml_spec.rb +0 -1
- data/spec/views/accounts/update.js.haml_spec.rb +2 -5
- data/spec/views/admin/field_groups/create.js.haml_spec.rb +0 -1
- data/spec/views/admin/field_groups/update.js.haml_spec.rb +0 -1
- data/spec/views/admin/users/create.js.haml_spec.rb +0 -1
- data/spec/views/admin/users/destroy.js.haml_spec.rb +0 -6
- data/spec/views/admin/users/update.js.haml_spec.rb +1 -2
- data/spec/views/campaigns/_edit.haml_spec.rb +1 -1
- data/spec/views/campaigns/_new.haml_spec.rb +1 -1
- data/spec/views/campaigns/create.js.haml_spec.rb +0 -1
- data/spec/views/campaigns/destroy.js.haml_spec.rb +0 -1
- data/spec/views/campaigns/update.js.haml_spec.rb +2 -6
- data/spec/views/contacts/_edit.haml_spec.rb +1 -1
- data/spec/views/contacts/_new.haml_spec.rb +1 -1
- data/spec/views/contacts/create.js.haml_spec.rb +0 -1
- data/spec/views/contacts/update.js.haml_spec.rb +3 -7
- data/spec/views/home/index.haml_spec.rb +2 -2
- data/spec/views/leads/_edit.haml_spec.rb +1 -1
- data/spec/views/leads/_new.haml_spec.rb +1 -1
- data/spec/views/leads/create.js.haml_spec.rb +0 -3
- data/spec/views/leads/destroy.js.haml_spec.rb +0 -2
- data/spec/views/leads/promote.js.haml_spec.rb +3 -11
- data/spec/views/leads/reject.js.haml_spec.rb +0 -3
- data/spec/views/leads/update.js.haml_spec.rb +3 -11
- data/spec/views/opportunities/_edit.haml_spec.rb +1 -1
- data/spec/views/opportunities/_new.haml_spec.rb +1 -1
- data/spec/views/opportunities/create.js.haml_spec.rb +0 -2
- data/spec/views/opportunities/destroy.js.haml_spec.rb +0 -3
- data/spec/views/opportunities/update.js.haml_spec.rb +3 -11
- data/spec/views/tasks/_edit.haml_spec.rb +1 -1
- data/spec/views/tasks/complete.js.haml_spec.rb +0 -1
- data/spec/views/tasks/create.js.haml_spec.rb +0 -2
- data/spec/views/tasks/destroy.js.haml_spec.rb +0 -1
- data/spec/views/tasks/uncomplete.js.haml_spec.rb +0 -1
- data/spec/views/tasks/update.js.haml_spec.rb +1 -4
- data/spec/views/users/change_password.js.haml_spec.rb +1 -2
- data/spec/views/users/update.js.haml_spec.rb +1 -2
- data/spec/views/users/upload_avatar.js.haml_spec.rb +1 -2
- metadata +23 -14
- data/config/initializers/new_framework_defaults_5_2.rb +0 -40
- data/lib/fat_free_crm/gem_ext/simple_form/action_view_extensions/form_helper.rb +0 -24
@@ -7,7 +7,7 @@
|
|
7
7
|
#------------------------------------------------------------------------------
|
8
8
|
FactoryBot.define do
|
9
9
|
factory :user do
|
10
|
-
username {
|
10
|
+
username { FFaker::InternetSE.user_name_variant_short }
|
11
11
|
email { FFaker::Internet.email }
|
12
12
|
first_name { FFaker::Name.first_name }
|
13
13
|
last_name { FFaker::Name.last_name }
|
@@ -34,8 +34,11 @@ FactoryBot.define do
|
|
34
34
|
suspended_at { nil }
|
35
35
|
password { "password" }
|
36
36
|
password_confirmation { "password" }
|
37
|
-
end
|
38
37
|
|
38
|
+
# For unit tests, we dont need to enforce uniqueness
|
39
|
+
to_create { |instance| instance.save(validate: false) }
|
40
|
+
end
|
41
|
+
|
39
42
|
factory :admin do
|
40
43
|
admin { true }
|
41
44
|
end
|
@@ -31,8 +31,8 @@ feature 'Accounts', '
|
|
31
31
|
click_link 'Create Account'
|
32
32
|
expect(page).to have_selector('#account_name', visible: true)
|
33
33
|
fill_in 'account_name', with: 'My new account'
|
34
|
-
|
35
|
-
|
34
|
+
select2 'Affiliate', from: 'Category:'
|
35
|
+
select2 'Myself', from: 'Assigned to:'
|
36
36
|
click_link 'Contact Information'
|
37
37
|
fill_in 'account_phone', with: '+1 2345 6789'
|
38
38
|
fill_in 'account_website', with: 'http://www.example.com'
|
@@ -23,7 +23,7 @@ feature 'Groups tab', '
|
|
23
23
|
click_link 'create a new group'
|
24
24
|
expect(page).to have_selector('#group_name', visible: true)
|
25
25
|
fill_in 'group_name', with: 'The Enterprise Bridge'
|
26
|
-
|
26
|
+
select2 'Mr Spock', from: 'Users'
|
27
27
|
click_button 'Create Group'
|
28
28
|
expect(page).to have_content('The Enterprise Bridge')
|
29
29
|
expect(page).to have_content('members: Mr Spock')
|
@@ -29,7 +29,7 @@ feature 'Users tab', '
|
|
29
29
|
fill_in 'user_password_confirmation', with: 'password'
|
30
30
|
fill_in 'user_title', with: 'Chief'
|
31
31
|
fill_in 'user_company', with: 'Weather Inc.'
|
32
|
-
|
32
|
+
select2 'Superheroes', from: 'Groups:'
|
33
33
|
|
34
34
|
click_button 'Create User'
|
35
35
|
expect(find('#users')).to have_content('Captain Thunder')
|
@@ -31,7 +31,7 @@ feature 'Campaigns', '
|
|
31
31
|
click_link 'Create Campaign'
|
32
32
|
expect(page).to have_selector('#campaign_name', visible: true)
|
33
33
|
fill_in 'campaign_name', with: 'Cool Campaign'
|
34
|
-
|
34
|
+
select2 'On Hold', from: 'Status:'
|
35
35
|
click_link 'Comment'
|
36
36
|
fill_in 'comment_body', with: 'This campaign is very important'
|
37
37
|
click_button 'Create Campaign'
|
@@ -66,7 +66,7 @@ feature 'Campaigns', '
|
|
66
66
|
click_link 'My Cool Campaign'
|
67
67
|
click_link 'Edit'
|
68
68
|
fill_in 'campaign_name', with: 'My Even Cooler Campaign'
|
69
|
-
|
69
|
+
select2 'Started', from: 'Status:'
|
70
70
|
click_button 'Save Campaign'
|
71
71
|
expect(page).to have_content('My Even Cooler Campaign')
|
72
72
|
expect(page).to have_content('My Even Cooler Campaign')
|
@@ -77,7 +77,8 @@ feature 'Contacts', '
|
|
77
77
|
fill_in 'contact_last_name', with: 'Subject'
|
78
78
|
fill_in 'contact_email', with: "test.subject@example.com"
|
79
79
|
click_button 'Save Contact'
|
80
|
-
|
80
|
+
sleep(3) # TODO: A better ajax wait, or redirect on save
|
81
|
+
expect(find('#edit_contact_title')).to have_content('Test Subject')
|
81
82
|
|
82
83
|
click_link 'Dashboard'
|
83
84
|
expect(activities_element).to have_content("Bill Murray updated contact Test Subject")
|
@@ -115,10 +116,6 @@ feature 'Contacts', '
|
|
115
116
|
find('#main')
|
116
117
|
end
|
117
118
|
|
118
|
-
def summary_element
|
119
|
-
find('#summary')
|
120
|
-
end
|
121
|
-
|
122
119
|
def menu_element
|
123
120
|
find('#menu')
|
124
121
|
end
|
data/spec/features/leads_spec.rb
CHANGED
@@ -36,13 +36,16 @@ feature 'Leads', '
|
|
36
36
|
fill_in 'lead_email', with: 'mr_lead@example.com'
|
37
37
|
fill_in 'lead_phone', with: '+44 1234 567890'
|
38
38
|
click_link 'Status'
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
select2 'Myself', from: 'Assigned to:'
|
40
|
+
select2 'Contacted', from: 'Status:'
|
41
|
+
select2 'Campaign', from: 'Source:'
|
42
42
|
click_link 'Comment'
|
43
43
|
fill_in 'comment_body', with: 'This is an important lead.'
|
44
|
-
|
45
|
-
|
44
|
+
|
45
|
+
# TODO: Refactor to a page object
|
46
|
+
# This panel is already open, so clicking status again closed the div.
|
47
|
+
# click_link 'Status'
|
48
|
+
select2 'Contacted', from: 'Status:'
|
46
49
|
click_button 'Create Lead'
|
47
50
|
expect(leads_element).to have_content('Mr Lead')
|
48
51
|
|
@@ -79,9 +82,10 @@ feature 'Leads', '
|
|
79
82
|
fill_in 'lead_first_name', with: 'Mrs'
|
80
83
|
fill_in 'lead_phone', with: '+44 0987 654321'
|
81
84
|
click_link('Status')
|
82
|
-
|
85
|
+
select2 'Rejected', from: 'Status:'
|
83
86
|
click_button 'Save Lead'
|
84
|
-
|
87
|
+
sleep(3) # TODO: A better AJAX observing call, or just a redirect on save.
|
88
|
+
expect(find('#title')).to have_content('Mrs Lead')
|
85
89
|
|
86
90
|
click_link "Dashboard"
|
87
91
|
expect(activities_element).to have_content("Bill Murray updated lead Mrs Lead")
|
@@ -38,7 +38,7 @@ feature 'Opportunities', '
|
|
38
38
|
sleep(1)
|
39
39
|
find('li', text: 'Example Account').click
|
40
40
|
expect(page).to have_content('Example Account')
|
41
|
-
|
41
|
+
select2 'Prospecting', from: 'Stage'
|
42
42
|
click_link 'Comment'
|
43
43
|
fill_in 'comment_body', with: 'This is a very important opportunity.'
|
44
44
|
click_button 'Create Opportunity'
|
@@ -67,7 +67,7 @@ feature 'Opportunities', '
|
|
67
67
|
scenario "remembers the comment field when the creation was unsuccessful", js: true do
|
68
68
|
visit opportunities_page
|
69
69
|
click_link 'Create Opportunity'
|
70
|
-
|
70
|
+
select2 'Prospecting', from: 'Stage:'
|
71
71
|
|
72
72
|
click_link 'Comment'
|
73
73
|
fill_in 'comment_body', with: 'This is a very important opportunity.'
|
@@ -85,8 +85,8 @@ feature 'Opportunities', '
|
|
85
85
|
click_link 'A Cool Opportunity'
|
86
86
|
click_link 'Edit'
|
87
87
|
fill_in 'opportunity_name', with: 'An Even Cooler Opportunity'
|
88
|
-
|
89
|
-
|
88
|
+
select2 'Other Example Account', from: 'Account (create new or select existing):'
|
89
|
+
select2 'Analysis', from: 'Stage:'
|
90
90
|
click_button 'Save Opportunity'
|
91
91
|
expect(page).to have_content('An Even Cooler Opportunity')
|
92
92
|
click_link "Dashboard"
|
@@ -15,10 +15,14 @@ if ENV['BROWSER'] == 'chrome'
|
|
15
15
|
Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
|
16
16
|
end
|
17
17
|
else
|
18
|
+
# For local testing in an environment with a display or remote X server configured
|
19
|
+
# such as WSL2, use NO_HEADLESS=1 bundle exec rspec spec/features
|
20
|
+
#
|
21
|
+
# For modern firefox, use MARIONETTE=1 bundle exec rspec spec/features
|
18
22
|
Capybara.register_driver :selenium do |app|
|
19
23
|
options = Selenium::WebDriver::Firefox::Options.new
|
20
|
-
options.args << '--headless'
|
21
|
-
capabilities = Selenium::WebDriver::Remote::Capabilities.firefox(marionette:
|
24
|
+
options.args << '--headless' unless ENV['NO_HEADLESS'].present?
|
25
|
+
capabilities = Selenium::WebDriver::Remote::Capabilities.firefox(marionette: ENV['MARIONETTE'].present?)
|
22
26
|
Capybara::Selenium::Driver.new(app, browser: :firefox, options: options, desired_capabilities: capabilities)
|
23
27
|
end
|
24
28
|
end
|
@@ -7,7 +7,7 @@
|
|
7
7
|
#------------------------------------------------------------------------------
|
8
8
|
module SelectorHelpers
|
9
9
|
def click_filter_tab(filter_name)
|
10
|
-
tab = find(:xpath, "//div[@class='filters']//
|
10
|
+
tab = find(:xpath, "//div[@class='filters']//a[contains(text(), '#{filter_name}')]")
|
11
11
|
tab.click
|
12
12
|
end
|
13
13
|
|
@@ -22,6 +22,15 @@ module SelectorHelpers
|
|
22
22
|
page.execute_script "$('#task_#{task_id} a')[1].click()"
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
# See github.com/goodwill/capybara-select2
|
27
|
+
def select2(value, options = {})
|
28
|
+
select2_container = find("div.label", text: options[:from]).find(:xpath, '..').find('.select2-container')
|
29
|
+
|
30
|
+
select2_container.find(".select2-selection").click
|
31
|
+
drop_container = ".select2-dropdown"
|
32
|
+
find(:xpath, "//body").find("#{drop_container} li.select2-results__option", text: value).click
|
33
|
+
end
|
25
34
|
end
|
26
35
|
|
27
36
|
RSpec.configuration.include SelectorHelpers, type: :feature
|
data/spec/features/tasks_spec.rb
CHANGED
@@ -33,9 +33,9 @@ feature 'Tasks', '
|
|
33
33
|
click_link 'Create Task'
|
34
34
|
expect(page).to have_selector('#task_name', visible: true)
|
35
35
|
fill_in 'task_name', with: 'Task I Need To Do'
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
select2 'Tomorrow', from: 'Due:'
|
37
|
+
select2 'Myself', from: 'Assign to:'
|
38
|
+
select2 'Call', from: 'Category:'
|
39
39
|
click_button 'Create Task'
|
40
40
|
expect(page).to have_content('Task I Need To Do')
|
41
41
|
|
@@ -51,9 +51,9 @@ feature 'Tasks', '
|
|
51
51
|
click_link 'Create Task'
|
52
52
|
expect(page).to have_selector('#task_name', visible: true)
|
53
53
|
fill_in 'task_name', with: 'Task For Someone Else'
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
select2 'Tomorrow', from: 'Due:'
|
55
|
+
select2 'Another User', from: 'Assign to:'
|
56
|
+
select2 'Call', from: 'Category:'
|
57
57
|
click_button 'Create Task'
|
58
58
|
expect(page).to have_content('The task has been created and assigned to Another User')
|
59
59
|
|
@@ -8,9 +8,66 @@
|
|
8
8
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
9
9
|
|
10
10
|
describe AccountsHelper do
|
11
|
+
let(:assignee) { create(:user) }
|
11
12
|
# Delete this example and add some real ones or delete this file
|
12
13
|
it "should be included in the object returned by #helper" do
|
13
14
|
included_modules = (class << helper; self; end).send :included_modules
|
14
15
|
expect(included_modules).to include(AccountsHelper)
|
15
16
|
end
|
17
|
+
describe '#display_pipeline' do
|
18
|
+
context 'when the pipeline is zero' do
|
19
|
+
it 'returns "N/A"' do
|
20
|
+
expect(display_value(0)).to eq('N/A')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
context 'when the pipeline is has 300' do
|
24
|
+
it 'returns "$300"' do
|
25
|
+
expect(display_value(300)).to eq('$300')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
describe '#display_won' do
|
30
|
+
context 'when the won is zero' do
|
31
|
+
it 'returns "N/A"' do
|
32
|
+
expect(display_value(0)).to eq('N/A')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
context 'when the won is has 300' do
|
36
|
+
it 'returns "$300"' do
|
37
|
+
expect(display_value(300)).to eq('$300')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
describe '#display_lost' do
|
42
|
+
context 'when the lost is zero' do
|
43
|
+
it 'returns "N/A"' do
|
44
|
+
expect(display_value(0)).to eq('N/A')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
context 'when the lost is has 300' do
|
48
|
+
it 'returns "$300"' do
|
49
|
+
expect(display_value(300)).to eq('$300')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
describe '#display_assigned' do
|
54
|
+
context 'when the name is under 16 chars' do
|
55
|
+
it 'returns the name' do
|
56
|
+
@account = create(:account)
|
57
|
+
allow(@account).to receive(:assignee).and_return(assignee)
|
58
|
+
allow(assignee).to receive(:full_name).and_return('Abe Lincoln')
|
59
|
+
allow(@account).to receive(:assigned_to).and_return(1)
|
60
|
+
expect(display_assigned(@account)).to eq('Abe Lincoln')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
context 'when the name is over 16 chars' do
|
64
|
+
it 'returns the truncated name' do
|
65
|
+
@account = create(:account)
|
66
|
+
allow(@account).to receive(:assignee).and_return(assignee)
|
67
|
+
allow(assignee).to receive(:full_name).and_return('Richard Milhouse Nixon')
|
68
|
+
allow(@account).to receive(:assigned_to).and_return(1)
|
69
|
+
expect(display_assigned(@account)).to eq('Richard Milho...')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
16
73
|
end
|
@@ -113,14 +113,14 @@ describe Opportunity do
|
|
113
113
|
|
114
114
|
it "should set the probability to 0% if opportunity has been lost" do
|
115
115
|
opportunity = create(:opportunity, stage: "prospecting", probability: 25)
|
116
|
-
opportunity.
|
116
|
+
opportunity.update(stage: 'lost')
|
117
117
|
opportunity.reload
|
118
118
|
expect(opportunity.probability).to eq(0)
|
119
119
|
end
|
120
120
|
|
121
121
|
it "should set the probablility to 100% if opportunity has been won" do
|
122
122
|
opportunity = create(:opportunity, stage: "prospecting", probability: 65)
|
123
|
-
opportunity.
|
123
|
+
opportunity.update(stage: 'won')
|
124
124
|
opportunity.reload
|
125
125
|
expect(opportunity.probability).to eq(100)
|
126
126
|
end
|
@@ -45,9 +45,9 @@ describe CustomFieldPair do
|
|
45
45
|
|
46
46
|
it "should update the pair" do
|
47
47
|
foo1 = double(required: true, disabled: 'false')
|
48
|
-
expect(foo1).to receive(:
|
48
|
+
expect(foo1).to receive(:update).with(@field.merge(@pair1))
|
49
49
|
foo2 = double
|
50
|
-
expect(foo2).to receive(:
|
50
|
+
expect(foo2).to receive(:update).with(@field.merge(@pair2).merge('required' => true, 'disabled' => 'false'))
|
51
51
|
expect(foo1).to receive(:paired_with).and_return(foo2)
|
52
52
|
expect(CustomFieldPair).to receive(:find).with('3').and_return(foo1)
|
53
53
|
|
@@ -52,7 +52,7 @@ describe EntityObserver do
|
|
52
52
|
|
53
53
|
it "notifies the new owner if the entity is re-assigned" do
|
54
54
|
expect(UserMailer).to receive(:assigned_entity_notification).with(entity, assigner).and_return(mail)
|
55
|
-
entity.
|
55
|
+
entity.update(assignee: assignee)
|
56
56
|
end
|
57
57
|
|
58
58
|
it "does not notify the owner if the entity is not re-assigned" do
|
@@ -62,12 +62,12 @@ describe EntityObserver do
|
|
62
62
|
|
63
63
|
it "does not notify anyone if the entity becomes unassigned" do
|
64
64
|
expect(UserMailer).not_to receive(:assigned_entity_notification)
|
65
|
-
entity.
|
65
|
+
entity.update(assignee: nil)
|
66
66
|
end
|
67
67
|
|
68
68
|
it "does not notify me if I re-assign an entity to myself" do
|
69
69
|
expect(UserMailer).not_to receive(:assigned_entity_notification)
|
70
|
-
entity.
|
70
|
+
entity.update(assignee: assigner)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
@@ -63,14 +63,14 @@ describe Task do
|
|
63
63
|
describe "Task/Update" do
|
64
64
|
it "should update task name" do
|
65
65
|
task = create(:task, name: "Hello")
|
66
|
-
task.
|
66
|
+
task.update(name: "World")
|
67
67
|
expect(task.errors).to be_empty
|
68
68
|
expect(task.name).to eq("World")
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should update task category" do
|
72
72
|
task = create(:task, category: "call")
|
73
|
-
task.
|
73
|
+
task.update(category: "email")
|
74
74
|
expect(task.errors).to be_empty
|
75
75
|
expect(task.category).to eq("email")
|
76
76
|
end
|
@@ -79,7 +79,7 @@ describe Task do
|
|
79
79
|
him = create(:user)
|
80
80
|
her = create(:user)
|
81
81
|
task = create(:task, assigned_to: him.id)
|
82
|
-
task.
|
82
|
+
task.update(assigned_to: her.id)
|
83
83
|
expect(task.errors).to be_empty
|
84
84
|
expect(task.assigned_to).to eq(her.id)
|
85
85
|
expect(task.assignee).to eq(her)
|
@@ -88,7 +88,7 @@ describe Task do
|
|
88
88
|
it "should reassign the task from another person to myself" do
|
89
89
|
him = create(:user)
|
90
90
|
task = create(:task, assigned_to: him.id)
|
91
|
-
task.
|
91
|
+
task.update(assigned_to: "")
|
92
92
|
expect(task.errors).to be_empty
|
93
93
|
expect(task.assigned_to).to eq(nil)
|
94
94
|
expect(task.assignee).to eq(nil)
|
@@ -101,7 +101,7 @@ describe Task do
|
|
101
101
|
|
102
102
|
it "should update due date based on selected bucket within #{offset ? 'different' : 'current'} timezone" do
|
103
103
|
task = create(:task, due_at: Time.now.midnight.tomorrow, bucket: "due_tomorrow")
|
104
|
-
task.
|
104
|
+
task.update(bucket: "due_this_week")
|
105
105
|
expect(task.errors).to be_empty
|
106
106
|
expect(task.bucket).to eq("due_this_week")
|
107
107
|
expect(task.due_at.change(usec: 0)).to eq(Time.zone.now.end_of_week.change(usec: 0))
|
@@ -109,7 +109,7 @@ describe Task do
|
|
109
109
|
|
110
110
|
it "should update due date if specific calendar date selected within #{offset ? 'different' : 'current'} timezone" do
|
111
111
|
task = create(:task, due_at: Time.now.midnight.tomorrow, bucket: "due_tomorrow")
|
112
|
-
task.
|
112
|
+
task.update(bucket: "specific_time", calendar: "2020-03-20")
|
113
113
|
expect(task.errors).to be_empty
|
114
114
|
expect(task.bucket).to eq("specific_time")
|
115
115
|
expect(task.due_at.to_i).to eq(Time.parse("2020-03-20").to_i)
|
@@ -120,7 +120,7 @@ describe Task do
|
|
120
120
|
describe "Task/Complete" do
|
121
121
|
it "should complete a task that is overdue" do
|
122
122
|
task = create(:task, due_at: 2.days.ago, bucket: "overdue")
|
123
|
-
task.
|
123
|
+
task.update(completed_at: Time.now, completed_by: task.user.id)
|
124
124
|
|
125
125
|
expect(task.errors).to be_empty
|
126
126
|
expect(task.completed_at).not_to eq(nil)
|
@@ -129,7 +129,7 @@ describe Task do
|
|
129
129
|
|
130
130
|
it "should complete a task due sometime in the future" do
|
131
131
|
task = create(:task, due_at: Time.now.midnight.tomorrow, bucket: "due_tomorrow")
|
132
|
-
task.
|
132
|
+
task.update(completed_at: Time.now, completed_by: task.user.id)
|
133
133
|
|
134
134
|
expect(task.errors).to be_empty
|
135
135
|
expect(task.completed_at).not_to eq(nil)
|
@@ -139,7 +139,7 @@ describe Task do
|
|
139
139
|
it "should complete a task that is due on specific date in the future" do
|
140
140
|
task = create(:task, calendar: "10/10/2022 12:00 AM", bucket: "specific_time")
|
141
141
|
task.calendar = nil # Calendar is not saved in the database; we need it only to set the :due_at.
|
142
|
-
task.
|
142
|
+
task.update(completed_at: Time.now, completed_by: task.user.id)
|
143
143
|
expect(task.errors).to be_empty
|
144
144
|
expect(task.completed_at).not_to eq(nil)
|
145
145
|
expect(task.completor).to eq(task.user)
|
@@ -148,7 +148,7 @@ describe Task do
|
|
148
148
|
it "should complete a task that is due on specific date in the past" do
|
149
149
|
task = create(:task, calendar: "10/10/1992 12:00 AM", bucket: "specific_time")
|
150
150
|
task.calendar = nil # Calendar is not saved in the database; we need it only to set the :due_at.
|
151
|
-
task.
|
151
|
+
task.update(completed_at: Time.now, completed_by: task.user.id)
|
152
152
|
expect(task.errors).to be_empty
|
153
153
|
expect(task.completed_at).not_to eq(nil)
|
154
154
|
expect(task.completor).to eq(task.user)
|
@@ -158,7 +158,7 @@ describe Task do
|
|
158
158
|
due_at = Time.now - 42.days
|
159
159
|
task = create(:task, due_at: due_at, bucket: "specific_time",
|
160
160
|
calendar: due_at.strftime('%Y-%m-%d %H:%M'))
|
161
|
-
task.
|
161
|
+
task.update(completed_at: Time.now, completed_by: task.user.id, calendar: '')
|
162
162
|
|
163
163
|
expect(task.completed?).to eq(true)
|
164
164
|
expect(task.due_at).to eq(due_at.utc.strftime('%Y-%m-%d %H:%M'))
|
@@ -82,9 +82,9 @@ describe Version, versioning: true do
|
|
82
82
|
|
83
83
|
it "should add a version when updating existing #{item}" do
|
84
84
|
if @item.respond_to?(:full_name)
|
85
|
-
@item.
|
85
|
+
@item.update(first_name: "Billy", last_name: "Bones")
|
86
86
|
else
|
87
|
-
@item.
|
87
|
+
@item.update(name: "Billy Bones")
|
88
88
|
end
|
89
89
|
@version = Version.where(@conditions.merge(event: 'update')).first
|
90
90
|
|
@@ -22,7 +22,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
22
22
|
describe Preference do
|
23
23
|
before(:each) do
|
24
24
|
@user = create(:user)
|
25
|
-
@magoody = Base64.encode64(
|
25
|
+
@magoody = Base64.encode64("magoody".to_json)
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should create a new instance given valid attributes" do
|
@@ -22,7 +22,7 @@ describe "/accounts/_edit" do
|
|
22
22
|
expect(view).to render_template(partial: "_contact_info")
|
23
23
|
expect(view).to render_template(partial: "_permissions")
|
24
24
|
|
25
|
-
expect(rendered).to have_tag(
|
25
|
+
expect(rendered).to have_tag('form[class="simple_form edit_account"]') do |form|
|
26
26
|
expect(form).to have_tag "input[type=hidden][id=account_user_id][value='#{@account.user_id}']"
|
27
27
|
end
|
28
28
|
end
|
@@ -23,7 +23,7 @@ describe "/accounts/_new" do
|
|
23
23
|
expect(view).to render_template(partial: "_contact_info")
|
24
24
|
expect(view).to render_template(partial: "_permissions")
|
25
25
|
|
26
|
-
expect(rendered).to have_tag(
|
26
|
+
expect(rendered).to have_tag('form[class="simple_form new_account"]')
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should render background info field if settings require so" do
|
@@ -34,7 +34,6 @@ describe "/accounts/update" do
|
|
34
34
|
render
|
35
35
|
expect(rendered).to include("$('#sidebar').html")
|
36
36
|
expect(rendered).to have_text("Recent Items")
|
37
|
-
expect(rendered).to include("$('#summary').effect('shake'")
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
@@ -70,11 +69,10 @@ describe "/accounts/update" do
|
|
70
69
|
controller.request.env["HTTP_REFERER"] = "http://localhost/accounts/123"
|
71
70
|
end
|
72
71
|
|
73
|
-
it "should redraw the [edit_account] form
|
72
|
+
it "should redraw the [edit_account] form" do
|
74
73
|
render
|
75
74
|
|
76
75
|
expect(rendered).to include("#edit_account")
|
77
|
-
expect(rendered).to include(%/$('#edit_account').effect("shake"/)
|
78
76
|
expect(rendered).to include('focus()')
|
79
77
|
end
|
80
78
|
end
|
@@ -84,11 +82,10 @@ describe "/accounts/update" do
|
|
84
82
|
controller.request.env["HTTP_REFERER"] = "http://localhost/accounts"
|
85
83
|
end
|
86
84
|
|
87
|
-
it "should redraw the [edit_account] form
|
85
|
+
it "should redraw the [edit_account] form" do
|
88
86
|
render
|
89
87
|
|
90
88
|
expect(rendered).to include("account_#{@account.id}")
|
91
|
-
expect(rendered).to include(%/$('#account_#{@account.id}').effect("shake"/)
|
92
89
|
expect(rendered).to include('focus()')
|
93
90
|
end
|
94
91
|
end
|
@@ -26,6 +26,5 @@ describe "admin/field_groups/create" do
|
|
26
26
|
allow(field_group).to receive(:valid?).and_return(false)
|
27
27
|
render
|
28
28
|
expect(view).to render_template("admin/field_groups/create")
|
29
|
-
expect(rendered).to have_text("effect(\"shake\", { duration:250, distance: 6 });")
|
30
29
|
end
|
31
30
|
end
|
@@ -25,6 +25,5 @@ describe "admin/field_groups/update" do
|
|
25
25
|
it "renders javascript for invalid field group" do
|
26
26
|
allow(field_group.errors).to receive(:empty?).and_return(false)
|
27
27
|
render
|
28
|
-
expect(rendered).to have_text("$('##{dom_id(field_group, :edit)}').effect('shake', { distance:5 }, 250);")
|
29
28
|
end
|
30
29
|
end
|
@@ -37,12 +37,6 @@ describe "admin/users/destroy" do
|
|
37
37
|
expect(rendered).to include(%/crm.flick('#{dom_id(@user, :confirm)}', 'remove');/)
|
38
38
|
end
|
39
39
|
|
40
|
-
it "should shake user partial" do
|
41
|
-
render
|
42
|
-
|
43
|
-
expect(rendered).to include(%/$('#user_#{@user.id}').effect('shake'/)
|
44
|
-
end
|
45
|
-
|
46
40
|
it "should show flash message" do
|
47
41
|
render
|
48
42
|
|
@@ -27,11 +27,10 @@ describe "admin/users/update" do
|
|
27
27
|
@user.errors.add(:name)
|
28
28
|
end
|
29
29
|
|
30
|
-
it "redraws [Edit User] form
|
30
|
+
it "redraws [Edit User] form" do
|
31
31
|
render
|
32
32
|
|
33
33
|
expect(rendered).to include("user_#{@user.id}")
|
34
|
-
expect(rendered).to include(%/$('#user_#{@user.id}').effect("shake"/)
|
35
34
|
expect(rendered).to include(%/$('#user_username').focus()/)
|
36
35
|
end
|
37
36
|
end
|
@@ -23,7 +23,7 @@ describe "/campaigns/_edit" do
|
|
23
23
|
expect(view).to render_template(partial: "campaigns/_objectives")
|
24
24
|
expect(view).to render_template(partial: "_permissions")
|
25
25
|
|
26
|
-
expect(view).to have_tag(
|
26
|
+
expect(view).to have_tag('form[class="simple_form edit_campaign"]') do
|
27
27
|
with_tag "input[type=hidden][id=campaign_user_id][value='#{@campaign.user_id}']"
|
28
28
|
end
|
29
29
|
end
|
@@ -22,7 +22,7 @@ describe "/campaigns/_new" do
|
|
22
22
|
expect(view).to render_template(partial: "campaigns/_objectives")
|
23
23
|
expect(view).to render_template(partial: "_permissions")
|
24
24
|
|
25
|
-
expect(rendered).to have_tag(
|
25
|
+
expect(rendered).to have_tag('form[class="simple_form new_campaign"]')
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should render background info field if settings require so" do
|
@@ -23,7 +23,6 @@ describe "/campaigns/destroy" do
|
|
23
23
|
it "should update Campaigns sidebar" do
|
24
24
|
expect(rendered).to include("#sidebar")
|
25
25
|
expect(rendered).to have_text("Recent Items")
|
26
|
-
expect(rendered).to include(%/$('#filters').effect('shake'/)
|
27
26
|
end
|
28
27
|
|
29
28
|
it "should update pagination" do
|